From 8f8362d586d8619906e1f993d69e393c753a1bf3 Mon Sep 17 00:00:00 2001 From: Alex Panshin Date: Tue, 2 Oct 2018 13:41:25 +0300 Subject: [PATCH 001/585] add more CDATA-related tests for `Magento\Framework\Config\Dom::merge` and create a fix for failing ones --- lib/internal/Magento/Framework/Config/Dom.php | 55 ++++++++++++++++++- .../Framework/Config/Test/Unit/DomTest.php | 7 +++ .../Config/Test/Unit/_files/dom/big_cdata.xml | 12 ++++ .../Unit/_files/dom/big_cdata_attribute.xml | 12 ++++ .../_files/dom/big_cdata_attribute_merged.xml | 12 ++++ .../_files/dom/big_cdata_attribute_new.xml | 12 ++++ .../Test/Unit/_files/dom/big_cdata_merged.xml | 12 ++++ .../Test/Unit/_files/dom/big_cdata_new.xml | 12 ++++ .../Test/Unit/_files/dom/big_cdata_text.xml | 12 ++++ .../Unit/_files/dom/big_cdata_text_merged.xml | 10 ++++ .../Unit/_files/dom/big_cdata_text_new.xml | 10 ++++ .../Config/Test/Unit/_files/dom/cdata.xml | 10 ++++ .../Test/Unit/_files/dom/cdata_html.xml | 10 ++++ .../Unit/_files/dom/cdata_html_merged.xml | 10 ++++ .../Test/Unit/_files/dom/cdata_html_new.xml | 10 ++++ .../Test/Unit/_files/dom/cdata_merged.xml | 10 ++++ .../Config/Test/Unit/_files/dom/cdata_new.xml | 10 ++++ .../Test/Unit/_files/dom/cdata_text.xml | 10 ++++ .../Unit/_files/dom/cdata_text_merged.xml | 10 ++++ .../Test/Unit/_files/dom/cdata_text_new.xml | 10 ++++ .../Test/Unit/_files/dom/text_node_cdata.xml | 12 ++++ .../_files/dom/text_node_cdata_merged.xml | 14 +++++ .../Unit/_files/dom/text_node_cdata_new.xml | 14 +++++ 23 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_merged.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_new.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_merged.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_new.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_merged.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_new.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_merged.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_new.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_merged.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_new.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_merged.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_new.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata_merged.xml create mode 100644 lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata_new.xml diff --git a/lib/internal/Magento/Framework/Config/Dom.php b/lib/internal/Magento/Framework/Config/Dom.php index 1d995bab007e5..2b9722e7cf88d 100644 --- a/lib/internal/Magento/Framework/Config/Dom.php +++ b/lib/internal/Magento/Framework/Config/Dom.php @@ -190,9 +190,15 @@ protected function _mergeNode(\DOMElement $node, $parentPath) /* override node value */ if ($this->_isTextNode($node)) { /* skip the case when the matched node has children, otherwise they get overridden */ - if (!$matchedNode->hasChildNodes() || $this->_isTextNode($matchedNode)) { + if (!$matchedNode->hasChildNodes() || $this->_isTextNode($matchedNode) || $this->_isCdataNode($matchedNode)) { $matchedNode->nodeValue = $node->childNodes->item(0)->nodeValue; } + } elseif ($this->_isCdataNode($node) && $this->_isTextNode($matchedNode) && $this->_findCdataSection($node)) { + /* Replace text node with CDATA section */ + $matchedNode->nodeValue = $this->_findCdataSection($node)->nodeValue; + } elseif ($this->_isCdataNode($node) && $this->_isCdataNode($matchedNode)) { + /* Replace CDATA with new one */ + $this->_replaceCdataNode($matchedNode, $node); } else { /* recursive merge for all child nodes */ foreach ($node->childNodes as $childNode) { @@ -220,6 +226,53 @@ protected function _isTextNode($node) return $node->childNodes->length == 1 && $node->childNodes->item(0) instanceof \DOMText; } + /** + * Check if the node content is CDATA (probably surrounded with text nodes) + * @param $node + * @return bool + */ + protected function _isCdataNode($node) + { + // If every child node of current is NOT \DOMElement + // It is arbitrary combination of text nodes and CDATA sections. + foreach ($node->childNodes as $childNode) { + if ($childNode instanceof \DOMElement) { + return false; + } + } + + return true; + } + + /** + * Finds CDATA section from given node children + * @param $node + * @return \DOMCdataSection|null + */ + protected function _findCdataSection($node) + { + foreach ($node->childNodes as $childNode) { + if ($childNode instanceof \DOMCdataSection) { + return $childNode; + } + } + } + + /** + * Replaces CDATA section in $oldNode with $newNode's + * @param $oldNode + * @param $newNode + */ + protected function _replaceCdataNode($oldNode, $newNode) + { + $oldCdata = $this->_findCdataSection($oldNode); + $newCdata = $this->_findCdataSection($newNode); + + if ($oldCdata && $newCdata) { + $oldCdata->nodeValue = $newCdata->nodeValue; + } + } + /** * Merges attributes of the merge node to the base node * diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php index 5c8f66683877c..a96e123c71d23 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php @@ -62,6 +62,13 @@ public function mergeDataProvider() ['override_node.xml', 'override_node_new.xml', [], null, 'override_node_merged.xml'], ['override_node_new.xml', 'override_node.xml', [], null, 'override_node_merged.xml'], ['text_node.xml', 'text_node_new.xml', [], null, 'text_node_merged.xml'], + 'text node replaced with cdata' => ['text_node_cdata.xml', 'text_node_cdata_new.xml', [], null, 'text_node_cdata_merged.xml'], + 'cdata' => ['cdata.xml', 'cdata_new.xml', [], null, 'cdata_merged.xml'], + 'cdata with html' => ['cdata_html.xml', 'cdata_html_new.xml', [], null, 'cdata_html_merged.xml'], + 'cdata replaced with text node' => ['cdata_text.xml', 'cdata_text_new.xml', [], null, 'cdata_text_merged.xml'], + 'big cdata' => ['big_cdata.xml', 'big_cdata_new.xml', [], null, 'big_cdata_merged.xml'], + 'big cdata with attribute' => ['big_cdata_attribute.xml', 'big_cdata_attribute_new.xml', [], null, 'big_cdata_attribute_merged.xml'], + 'big cdata replaced with text' => ['big_cdata_text.xml', 'big_cdata_text_new.xml', [], null, 'big_cdata_text_merged.xml'], [ 'recursive.xml', 'recursive_new.xml', diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata.xml new file mode 100644 index 0000000000000..6beac814f6e26 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute.xml new file mode 100644 index 0000000000000..4bd6bd7fffbe6 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_merged.xml new file mode 100644 index 0000000000000..8bf14adfe6ff3 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_merged.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_new.xml new file mode 100644 index 0000000000000..79700c8801b78 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_new.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_merged.xml new file mode 100644 index 0000000000000..79700c8801b78 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_merged.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_new.xml new file mode 100644 index 0000000000000..79700c8801b78 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_new.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text.xml new file mode 100644 index 0000000000000..6beac814f6e26 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_merged.xml new file mode 100644 index 0000000000000..e1535bf2de982 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_merged.xml @@ -0,0 +1,10 @@ + + + + + Some Other Phrase + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_new.xml new file mode 100644 index 0000000000000..e1535bf2de982 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_new.xml @@ -0,0 +1,10 @@ + + + + + Some Other Phrase + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata.xml new file mode 100644 index 0000000000000..b08031c6bbd79 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html.xml new file mode 100644 index 0000000000000..e04c47f406461 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html.xml @@ -0,0 +1,10 @@ + + + + + Phrase]]> + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_merged.xml new file mode 100644 index 0000000000000..b8dd1a2105946 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_merged.xml @@ -0,0 +1,10 @@ + + + + + Other
Phrase]]>
+
+
diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_new.xml new file mode 100644 index 0000000000000..b8dd1a2105946 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_new.xml @@ -0,0 +1,10 @@ + + + + + Other
Phrase]]>
+
+
diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_merged.xml new file mode 100644 index 0000000000000..a799004ae4775 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_merged.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_new.xml new file mode 100644 index 0000000000000..a799004ae4775 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_new.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text.xml new file mode 100644 index 0000000000000..b08031c6bbd79 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_merged.xml new file mode 100644 index 0000000000000..e1535bf2de982 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_merged.xml @@ -0,0 +1,10 @@ + + + + + Some Other Phrase + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_new.xml new file mode 100644 index 0000000000000..e1535bf2de982 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_new.xml @@ -0,0 +1,10 @@ + + + + + Some Other Phrase + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata.xml new file mode 100644 index 0000000000000..6807872aa3d3a --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata.xml @@ -0,0 +1,12 @@ + + + + + Some Phrase + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata_merged.xml new file mode 100644 index 0000000000000..b905781a9fe50 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata_merged.xml @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata_new.xml new file mode 100644 index 0000000000000..b905781a9fe50 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/text_node_cdata_new.xml @@ -0,0 +1,14 @@ + + + + + + + + + From 026a6bc7519119dfab9dc08abae8c8e0b4c0b4b2 Mon Sep 17 00:00:00 2001 From: Alex Panshin Date: Tue, 2 Oct 2018 17:40:21 +0200 Subject: [PATCH 002/585] fix code styling issues --- lib/internal/Magento/Framework/Config/Dom.php | 24 +++++++++----- .../Framework/Config/Test/Unit/DomTest.php | 32 ++++++++++++++++--- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/lib/internal/Magento/Framework/Config/Dom.php b/lib/internal/Magento/Framework/Config/Dom.php index 2b9722e7cf88d..c055cd6fb7dbd 100644 --- a/lib/internal/Magento/Framework/Config/Dom.php +++ b/lib/internal/Magento/Framework/Config/Dom.php @@ -190,12 +190,17 @@ protected function _mergeNode(\DOMElement $node, $parentPath) /* override node value */ if ($this->_isTextNode($node)) { /* skip the case when the matched node has children, otherwise they get overridden */ - if (!$matchedNode->hasChildNodes() || $this->_isTextNode($matchedNode) || $this->_isCdataNode($matchedNode)) { + if (!$matchedNode->hasChildNodes() + || $this->_isTextNode($matchedNode) + || $this->_isCdataNode($matchedNode) + ) { $matchedNode->nodeValue = $node->childNodes->item(0)->nodeValue; } - } elseif ($this->_isCdataNode($node) && $this->_isTextNode($matchedNode) && $this->_findCdataSection($node)) { + } elseif ($this->_isCdataNode($node) && $this->_isTextNode($matchedNode)) { /* Replace text node with CDATA section */ - $matchedNode->nodeValue = $this->_findCdataSection($node)->nodeValue; + if ($this->_findCdataSection($node)) { + $matchedNode->nodeValue = $this->_findCdataSection($node)->nodeValue; + } } elseif ($this->_isCdataNode($node) && $this->_isCdataNode($matchedNode)) { /* Replace CDATA with new one */ $this->_replaceCdataNode($matchedNode, $node); @@ -227,8 +232,9 @@ protected function _isTextNode($node) } /** - * Check if the node content is CDATA (probably surrounded with text nodes) - * @param $node + * Check if the node content is CDATA (probably surrounded with text nodes) or just text node + * + * @param \DOMNode $node * @return bool */ protected function _isCdataNode($node) @@ -246,7 +252,8 @@ protected function _isCdataNode($node) /** * Finds CDATA section from given node children - * @param $node + * + * @param \DOMNode $node * @return \DOMCdataSection|null */ protected function _findCdataSection($node) @@ -260,8 +267,9 @@ protected function _findCdataSection($node) /** * Replaces CDATA section in $oldNode with $newNode's - * @param $oldNode - * @param $newNode + * + * @param \DOMNode $oldNode + * @param \DOMNode $newNode */ protected function _replaceCdataNode($oldNode, $newNode) { diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php index a96e123c71d23..fa58bdb5a5ebb 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php @@ -62,13 +62,37 @@ public function mergeDataProvider() ['override_node.xml', 'override_node_new.xml', [], null, 'override_node_merged.xml'], ['override_node_new.xml', 'override_node.xml', [], null, 'override_node_merged.xml'], ['text_node.xml', 'text_node_new.xml', [], null, 'text_node_merged.xml'], - 'text node replaced with cdata' => ['text_node_cdata.xml', 'text_node_cdata_new.xml', [], null, 'text_node_cdata_merged.xml'], + 'text node replaced with cdata' => [ + 'text_node_cdata.xml', + 'text_node_cdata_new.xml', + [], + null, + 'text_node_cdata_merged.xml' + ], 'cdata' => ['cdata.xml', 'cdata_new.xml', [], null, 'cdata_merged.xml'], 'cdata with html' => ['cdata_html.xml', 'cdata_html_new.xml', [], null, 'cdata_html_merged.xml'], - 'cdata replaced with text node' => ['cdata_text.xml', 'cdata_text_new.xml', [], null, 'cdata_text_merged.xml'], + 'cdata replaced with text node' => [ + 'cdata_text.xml', + 'cdata_text_new.xml', + [], + null, + 'cdata_text_merged.xml' + ], 'big cdata' => ['big_cdata.xml', 'big_cdata_new.xml', [], null, 'big_cdata_merged.xml'], - 'big cdata with attribute' => ['big_cdata_attribute.xml', 'big_cdata_attribute_new.xml', [], null, 'big_cdata_attribute_merged.xml'], - 'big cdata replaced with text' => ['big_cdata_text.xml', 'big_cdata_text_new.xml', [], null, 'big_cdata_text_merged.xml'], + 'big cdata with attribute' => [ + 'big_cdata_attribute.xml', + 'big_cdata_attribute_new.xml', + [], + null, + 'big_cdata_attribute_merged.xml' + ], + 'big cdata replaced with text' => [ + 'big_cdata_text.xml', + 'big_cdata_text_new.xml', + [], + null, + 'big_cdata_text_merged.xml' + ], [ 'recursive.xml', 'recursive_new.xml', From 60d80ec1b3ab40e7cde4749f098b3dd69c28071a Mon Sep 17 00:00:00 2001 From: Alex Panshin Date: Tue, 9 Oct 2018 13:27:31 +0300 Subject: [PATCH 003/585] fix copyright notices according to Magento copyright policy --- .../Framework/Config/Test/Unit/_files/dom/big_cdata.xml | 6 ++++-- .../Config/Test/Unit/_files/dom/big_cdata_attribute.xml | 6 ++++-- .../Test/Unit/_files/dom/big_cdata_attribute_merged.xml | 6 ++++-- .../Config/Test/Unit/_files/dom/big_cdata_attribute_new.xml | 6 ++++-- .../Config/Test/Unit/_files/dom/big_cdata_merged.xml | 6 ++++-- .../Framework/Config/Test/Unit/_files/dom/big_cdata_new.xml | 6 ++++-- .../Config/Test/Unit/_files/dom/big_cdata_text.xml | 6 ++++-- .../Config/Test/Unit/_files/dom/big_cdata_text_merged.xml | 6 ++++-- .../Config/Test/Unit/_files/dom/big_cdata_text_new.xml | 6 ++++-- .../Magento/Framework/Config/Test/Unit/_files/dom/cdata.xml | 6 ++++-- .../Framework/Config/Test/Unit/_files/dom/cdata_html.xml | 6 ++++-- .../Config/Test/Unit/_files/dom/cdata_html_merged.xml | 6 ++++-- .../Config/Test/Unit/_files/dom/cdata_html_new.xml | 6 ++++-- .../Framework/Config/Test/Unit/_files/dom/cdata_merged.xml | 6 ++++-- .../Framework/Config/Test/Unit/_files/dom/cdata_new.xml | 6 ++++-- .../Framework/Config/Test/Unit/_files/dom/cdata_text.xml | 6 ++++-- .../Config/Test/Unit/_files/dom/cdata_text_merged.xml | 6 ++++-- .../Config/Test/Unit/_files/dom/cdata_text_new.xml | 6 ++++-- 18 files changed, 72 insertions(+), 36 deletions(-) diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata.xml index 6beac814f6e26..69eb0035958e6 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute.xml index 4bd6bd7fffbe6..12a9389e3d238 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_merged.xml index 8bf14adfe6ff3..6e95d843e34ba 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_merged.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_merged.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_new.xml index 79700c8801b78..b905781a9fe50 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_new.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_attribute_new.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_merged.xml index 79700c8801b78..b905781a9fe50 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_merged.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_merged.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_new.xml index 79700c8801b78..b905781a9fe50 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_new.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_new.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text.xml index 6beac814f6e26..69eb0035958e6 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_merged.xml index e1535bf2de982..3e37e67ffcf35 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_merged.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_merged.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_new.xml index e1535bf2de982..3e37e67ffcf35 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_new.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/big_cdata_text_new.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata.xml index b08031c6bbd79..f65a21e122394 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html.xml index e04c47f406461..15294f46445ec 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_merged.xml index b8dd1a2105946..709d921f737e4 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_merged.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_merged.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_new.xml index b8dd1a2105946..709d921f737e4 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_new.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_html_new.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_merged.xml index a799004ae4775..e6d2d809d7f7f 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_merged.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_merged.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_new.xml index a799004ae4775..e6d2d809d7f7f 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_new.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_new.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text.xml index b08031c6bbd79..f65a21e122394 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_merged.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_merged.xml index e1535bf2de982..3e37e67ffcf35 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_merged.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_merged.xml @@ -1,7 +1,9 @@ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_new.xml b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_new.xml index e1535bf2de982..3e37e67ffcf35 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_new.xml +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/dom/cdata_text_new.xml @@ -1,7 +1,9 @@ From 5d48710079f750181efc4bbb799dab9d43142789 Mon Sep 17 00:00:00 2001 From: Alex Panshin Date: Fri, 12 Oct 2018 15:02:59 +0300 Subject: [PATCH 004/585] make new methods private according to magento coding standards --- lib/internal/Magento/Framework/Config/Dom.php | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/internal/Magento/Framework/Config/Dom.php b/lib/internal/Magento/Framework/Config/Dom.php index c055cd6fb7dbd..e36f9615db26b 100644 --- a/lib/internal/Magento/Framework/Config/Dom.php +++ b/lib/internal/Magento/Framework/Config/Dom.php @@ -192,18 +192,18 @@ protected function _mergeNode(\DOMElement $node, $parentPath) /* skip the case when the matched node has children, otherwise they get overridden */ if (!$matchedNode->hasChildNodes() || $this->_isTextNode($matchedNode) - || $this->_isCdataNode($matchedNode) + || $this->isCdataNode($matchedNode) ) { $matchedNode->nodeValue = $node->childNodes->item(0)->nodeValue; } - } elseif ($this->_isCdataNode($node) && $this->_isTextNode($matchedNode)) { + } elseif ($this->isCdataNode($node) && $this->_isTextNode($matchedNode)) { /* Replace text node with CDATA section */ - if ($this->_findCdataSection($node)) { - $matchedNode->nodeValue = $this->_findCdataSection($node)->nodeValue; + if ($this->findCdataSection($node)) { + $matchedNode->nodeValue = $this->findCdataSection($node)->nodeValue; } - } elseif ($this->_isCdataNode($node) && $this->_isCdataNode($matchedNode)) { + } elseif ($this->isCdataNode($node) && $this->isCdataNode($matchedNode)) { /* Replace CDATA with new one */ - $this->_replaceCdataNode($matchedNode, $node); + $this->replaceCdataNode($matchedNode, $node); } else { /* recursive merge for all child nodes */ foreach ($node->childNodes as $childNode) { @@ -237,7 +237,7 @@ protected function _isTextNode($node) * @param \DOMNode $node * @return bool */ - protected function _isCdataNode($node) + private function isCdataNode($node) { // If every child node of current is NOT \DOMElement // It is arbitrary combination of text nodes and CDATA sections. @@ -256,7 +256,7 @@ protected function _isCdataNode($node) * @param \DOMNode $node * @return \DOMCdataSection|null */ - protected function _findCdataSection($node) + private function findCdataSection($node) { foreach ($node->childNodes as $childNode) { if ($childNode instanceof \DOMCdataSection) { @@ -271,10 +271,10 @@ protected function _findCdataSection($node) * @param \DOMNode $oldNode * @param \DOMNode $newNode */ - protected function _replaceCdataNode($oldNode, $newNode) + private function replaceCdataNode($oldNode, $newNode) { - $oldCdata = $this->_findCdataSection($oldNode); - $newCdata = $this->_findCdataSection($newNode); + $oldCdata = $this->findCdataSection($oldNode); + $newCdata = $this->findCdataSection($newNode); if ($oldCdata && $newCdata) { $oldCdata->nodeValue = $newCdata->nodeValue; From 39b8e35c8a0148b797c17b273c1e2db725b0fff4 Mon Sep 17 00:00:00 2001 From: Daniel Renaud Date: Mon, 19 Nov 2018 15:50:38 -0600 Subject: [PATCH 005/585] MC-5588: When using MysqlMQ messages are always set to complete even if exception occurs --- app/code/Magento/MysqlMq/Model/Driver/Queue.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/MysqlMq/Model/Driver/Queue.php b/app/code/Magento/MysqlMq/Model/Driver/Queue.php index b8dab6fac7b24..20b9496260a92 100644 --- a/app/code/Magento/MysqlMq/Model/Driver/Queue.php +++ b/app/code/Magento/MysqlMq/Model/Driver/Queue.php @@ -111,7 +111,6 @@ public function subscribe($callback) while ($envelope = $this->dequeue()) { try { call_user_func($callback, $envelope); - $this->acknowledge($envelope); } catch (\Exception $e) { $this->reject($envelope); } From 7a998bbf36c486fd907c242be51291b4d914bffe Mon Sep 17 00:00:00 2001 From: Daniel Renaud Date: Wed, 21 Nov 2018 16:18:08 -0600 Subject: [PATCH 006/585] MC-5588: When using MysqlMQ messages are always set to complete even if exception occurs - Unskip and refactor integration tests --- .../Magento/MysqlMq/Model/Driver/Queue.php | 10 +- .../TestModuleMysqlMq}/Model/DataObject.php | 19 +- .../Model/DataObjectRepository.php | 12 +- .../TestModuleMysqlMq/Model/Processor.php | 71 ++++++ .../TestModuleMysqlMq/etc/communication.xml | 14 ++ .../Magento/TestModuleMysqlMq/etc/module.xml | 11 + .../Magento/TestModuleMysqlMq/etc/queue.xml | 24 ++ .../TestModuleMysqlMq/etc/queue_consumer.xml | 14 ++ .../TestModuleMysqlMq/etc/queue_publisher.xml | 24 ++ .../TestModuleMysqlMq/etc/queue_topology.xml | 17 ++ .../TestModuleMysqlMq/registration.php | 12 + .../MessageQueue/_files/communication.xml | 2 +- .../_files/valid_expected_queue.php | 4 +- .../MessageQueue/_files/valid_queue_input.php | 2 +- .../Model/Cron/ConsumersRunnerTest.php | 3 + .../Magento/MysqlMq/Model/Processor.php | 28 --- .../MysqlMq/Model/PublisherConsumerTest.php | 222 +++++++----------- .../MysqlMq/Model/QueueManagementTest.php | 2 - .../testsuite/Magento/MysqlMq/etc/queue.xml | 67 ------ 19 files changed, 305 insertions(+), 253 deletions(-) rename dev/tests/integration/{testsuite/Magento/MysqlMq => _files/Magento/TestModuleMysqlMq}/Model/DataObject.php (68%) rename dev/tests/integration/{testsuite/Magento/MysqlMq => _files/Magento/TestModuleMysqlMq}/Model/DataObjectRepository.php (62%) create mode 100644 dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php create mode 100644 dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml create mode 100644 dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/module.xml create mode 100644 dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml create mode 100644 dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml create mode 100644 dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml create mode 100644 dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml create mode 100644 dev/tests/integration/_files/Magento/TestModuleMysqlMq/registration.php delete mode 100644 dev/tests/integration/testsuite/Magento/MysqlMq/Model/Processor.php delete mode 100644 dev/tests/integration/testsuite/Magento/MysqlMq/etc/queue.xml diff --git a/app/code/Magento/MysqlMq/Model/Driver/Queue.php b/app/code/Magento/MysqlMq/Model/Driver/Queue.php index 20b9496260a92..cc9ab2bf30d6c 100644 --- a/app/code/Magento/MysqlMq/Model/Driver/Queue.php +++ b/app/code/Magento/MysqlMq/Model/Driver/Queue.php @@ -73,7 +73,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function dequeue() { @@ -92,7 +92,7 @@ public function dequeue() } /** - * {@inheritdoc} + * @inheritdoc */ public function acknowledge(EnvelopeInterface $envelope) { @@ -103,7 +103,7 @@ public function acknowledge(EnvelopeInterface $envelope) } /** - * {@inheritdoc} + * @inheritdoc */ public function subscribe($callback) { @@ -120,7 +120,7 @@ public function subscribe($callback) } /** - * {@inheritdoc} + * @inheritdoc */ public function reject(EnvelopeInterface $envelope, $requeue = true, $rejectionMessage = null) { @@ -138,7 +138,7 @@ public function reject(EnvelopeInterface $envelope, $requeue = true, $rejectionM } /** - * {@inheritDoc} + * @inheritDoc */ public function push(EnvelopeInterface $envelope) { diff --git a/dev/tests/integration/testsuite/Magento/MysqlMq/Model/DataObject.php b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/DataObject.php similarity index 68% rename from dev/tests/integration/testsuite/Magento/MysqlMq/Model/DataObject.php rename to dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/DataObject.php index 31843be00a54b..ad3033cf7eeaa 100644 --- a/dev/tests/integration/testsuite/Magento/MysqlMq/Model/DataObject.php +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/DataObject.php @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\MysqlMq\Model; +namespace Magento\TestModuleMysqlMq\Model; class DataObject extends \Magento\Framework\Api\AbstractExtensibleObject { @@ -40,4 +40,21 @@ public function setEntityId($entityId) { return $this->setData('entity_id', $entityId); } + + /** + * @return string + */ + public function getOutputPath() + { + return $this->_get('outputPath'); + } + + /** + * @param string $path + * @return $this + */ + public function setOutputPath($path) + { + return $this->setData('outputPath', $path); + } } diff --git a/dev/tests/integration/testsuite/Magento/MysqlMq/Model/DataObjectRepository.php b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/DataObjectRepository.php similarity index 62% rename from dev/tests/integration/testsuite/Magento/MysqlMq/Model/DataObjectRepository.php rename to dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/DataObjectRepository.php index 879872315ec51..942298e49972f 100644 --- a/dev/tests/integration/testsuite/Magento/MysqlMq/Model/DataObjectRepository.php +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/DataObjectRepository.php @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\MysqlMq\Model; +namespace Magento\TestModuleMysqlMq\Model; class DataObjectRepository { @@ -11,15 +11,17 @@ class DataObjectRepository * @param DataObject $dataObject * @param string $requiredParam * @param int|null $optionalParam - * @return bool + * @return null */ public function delayedOperation( - \Magento\MysqlMq\Model\DataObject $dataObject, + \Magento\TestModuleMysqlMq\Model\DataObject $dataObject, $requiredParam, $optionalParam = null ) { - echo "Processed '{$dataObject->getEntityId()}'; " + $output = "Processed '{$dataObject->getEntityId()}'; " . "Required param '{$requiredParam}'; Optional param '{$optionalParam}'\n"; - return true; + file_put_contents($dataObject->getOutputPath(), $output); + + return null; } } diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php new file mode 100644 index 0000000000000..fb6fd4c5c2802 --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php @@ -0,0 +1,71 @@ +getOutputPath(), + "Processed {$message->getEntityId()}" . PHP_EOL, + FILE_APPEND + ); + } + + /** + * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + */ + public function processObjectCreated($message) + { + file_put_contents( + $message->getOutputPath(), + "Processed object created {$message->getEntityId()}" . PHP_EOL, + FILE_APPEND + ); + } + + /** + * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + */ + public function processCustomObjectCreated($message) + { + file_put_contents( + $message->getOutputPath(), + "Processed custom object created {$message->getEntityId()}" . PHP_EOL, + FILE_APPEND + ); + } + + /** + * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + */ + public function processObjectUpdated($message) + { + file_put_contents( + $message->getOutputPath(), + "Processed object updated {$message->getEntityId()}" . PHP_EOL, + FILE_APPEND + ); + } + + /** + * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + */ + public function processMessageWithException($message) + { + file_put_contents($message->getOutputPath(), "Exception processing {$message->getEntityId()}"); + throw new \LogicException( + "Exception during message processing happened. Entity: {{$message->getEntityId()}}" + ); + } +} diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml new file mode 100644 index 0000000000000..f3c1705f5afbd --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/module.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/module.xml new file mode 100644 index 0000000000000..8b6ea0f44ce9c --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/module.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml new file mode 100644 index 0000000000000..362237c0c5e62 --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml new file mode 100644 index 0000000000000..bb495a123a05d --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml new file mode 100644 index 0000000000000..a665e10ef5f14 --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml new file mode 100644 index 0000000000000..2df5485ee3447 --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/registration.php b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/registration.php new file mode 100644 index 0000000000000..4250e95bd7cc3 --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/registration.php @@ -0,0 +1,12 @@ +getPath(ComponentRegistrar::MODULE, 'Magento_TestModuleMysqlMq') === null) { + ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestModuleMysqlMq', __DIR__); +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/communication.xml b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/communication.xml index 0fc50f0432b93..1cc5d6cd3b714 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/communication.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/communication.xml @@ -7,6 +7,6 @@ --> - + diff --git a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_expected_queue.php b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_expected_queue.php index b5f5145c32c72..9a813b4424eaa 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_expected_queue.php +++ b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_expected_queue.php @@ -40,7 +40,7 @@ "name" => "publisher5.topic", "schema" => [ "schema_type" => "object", - "schema_value" => '\\' . \Magento\MysqlMq\Model\DataObject::class + "schema_value" => '\\' . \Magento\TestModuleMysqlMq\Model\DataObject::class ], "response_schema" => [ "schema_type" => "object", @@ -58,7 +58,7 @@ "handlers" => [ "topic.broker.test" => [ "0" => [ - "type" => \Magento\MysqlMq\Model\Processor::class, + "type" => \Magento\TestModuleMysqlMq\Model\Processor::class, "method" => "processMessage" ] ] diff --git a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php index fdd4a7d3007a7..e3d9a8a4eb197 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php +++ b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php @@ -23,7 +23,7 @@ "name" => "publisher5.topic", "schema" => [ "schema_type" => "object", - "schema_value" => "Magento\\MysqlMq\\Model\\DataObject" + "schema_value" => "Magento\\TestModuleMysqlMq\\Model\\DataObject" ], "response_schema" => [ "schema_type" => "object", diff --git a/dev/tests/integration/testsuite/Magento/MessageQueue/Model/Cron/ConsumersRunnerTest.php b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/Cron/ConsumersRunnerTest.php index 4acba63d98e66..eba5f9950534d 100644 --- a/dev/tests/integration/testsuite/Magento/MessageQueue/Model/Cron/ConsumersRunnerTest.php +++ b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/Cron/ConsumersRunnerTest.php @@ -117,6 +117,9 @@ protected function setUp() public function testCheckThatPidFilesWasCreated() { $this->consumersRunner->run(); + + sleep(20); + foreach ($this->consumerConfig->getConsumers() as $consumer) { $this->waitConsumerPidFile($consumer->getName()); } diff --git a/dev/tests/integration/testsuite/Magento/MysqlMq/Model/Processor.php b/dev/tests/integration/testsuite/Magento/MysqlMq/Model/Processor.php deleted file mode 100644 index 3b2a76104a2cd..0000000000000 --- a/dev/tests/integration/testsuite/Magento/MysqlMq/Model/Processor.php +++ /dev/null @@ -1,28 +0,0 @@ -getEntityId()}\n"; - } - - /** - * @param \Magento\MysqlMq\Model\DataObject $message - */ - public function processMessageWithException($message) - { - throw new \LogicException("Exception during message processing happened. Entity: {{$message->getEntityId()}}"); - } -} diff --git a/dev/tests/integration/testsuite/Magento/MysqlMq/Model/PublisherConsumerTest.php b/dev/tests/integration/testsuite/Magento/MysqlMq/Model/PublisherConsumerTest.php index f03d03d3a25fd..f911165bd27fb 100644 --- a/dev/tests/integration/testsuite/Magento/MysqlMq/Model/PublisherConsumerTest.php +++ b/dev/tests/integration/testsuite/Magento/MysqlMq/Model/PublisherConsumerTest.php @@ -3,87 +3,45 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MysqlMq\Model; -use Magento\Framework\MessageQueue\PublisherInterface; +use Magento\Framework\MessageQueue\UseCase\QueueTestCaseAbstract; +use Magento\MysqlMq\Model\ResourceModel\MessageCollection; +use Magento\MysqlMq\Model\ResourceModel\MessageStatusCollection; /** * Test for MySQL publisher class. * * @magentoDbIsolation disabled */ -class PublisherConsumerTest extends \PHPUnit\Framework\TestCase +class PublisherConsumerTest extends QueueTestCaseAbstract { const MAX_NUMBER_OF_TRIALS = 3; /** - * @var \Magento\Framework\MessageQueue\PublisherInterface + * @var string[] */ - protected $publisher; - - /** - * @var \Magento\Framework\ObjectManagerInterface - */ - protected $objectManager; - - protected function setUp() - { - $this->markTestIncomplete('Should be converted to queue config v2.'); - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - - $configPath = __DIR__ . '/../etc/queue.xml'; - $fileResolverMock = $this->createMock(\Magento\Framework\Config\FileResolverInterface::class); - $fileResolverMock->expects($this->any()) - ->method('get') - ->willReturn([$configPath => file_get_contents(($configPath))]); - - /** @var \Magento\Framework\MessageQueue\Config\Reader\Xml $xmlReader */ - $xmlReader = $this->objectManager->create( - \Magento\Framework\MessageQueue\Config\Reader\Xml::class, - ['fileResolver' => $fileResolverMock] - ); - - $newData = $xmlReader->read(); - - /** @var \Magento\Framework\MessageQueue\Config\Data $configData */ - $configData = $this->objectManager->get(\Magento\Framework\MessageQueue\Config\Data::class); - $configData->reset(); - $configData->merge($newData); - - $this->publisher = $this->objectManager->create(\Magento\Framework\MessageQueue\PublisherInterface::class); - } - - protected function tearDown() - { - $this->markTestIncomplete('Should be converted to queue config v2.'); - $this->consumeMessages('demoConsumerQueueOne', PHP_INT_MAX); - $this->consumeMessages('demoConsumerQueueTwo', PHP_INT_MAX); - $this->consumeMessages('demoConsumerQueueThree', PHP_INT_MAX); - $this->consumeMessages('demoConsumerQueueFour', PHP_INT_MAX); - $this->consumeMessages('demoConsumerQueueFive', PHP_INT_MAX); - $this->consumeMessages('demoConsumerQueueOneWithException', PHP_INT_MAX); - - $objectManagerConfiguration = [\Magento\Framework\MessageQueue\Config\Reader\Xml::class => [ - 'arguments' => [ - 'fileResolver' => ['instance' => \Magento\Framework\Config\FileResolverInterface::class], - ], - ], - ]; - $this->objectManager->configure($objectManagerConfiguration); - /** @var \Magento\Framework\MessageQueue\Config\Data $queueConfig */ - $queueConfig = $this->objectManager->get(\Magento\Framework\MessageQueue\Config\Data::class); - $queueConfig->reset(); - } + protected $consumers = [ + 'demoConsumerQueueOne', + 'demoConsumerQueueTwo', + 'demoConsumerQueueThree', + 'delayedOperationConsumer', + 'demoConsumerWithException' + ]; /** * @magentoDataFixture Magento/MysqlMq/_files/queues.php */ public function testPublishConsumeFlow() { - /** @var \Magento\MysqlMq\Model\DataObjectFactory $objectFactory */ - $objectFactory = $this->objectManager->create(\Magento\MysqlMq\Model\DataObjectFactory::class); - /** @var \Magento\MysqlMq\Model\DataObject $object */ + /** @var \Magento\TestModuleMysqlMq\Model\DataObjectFactory $objectFactory */ + $objectFactory = $this->objectManager->create(\Magento\TestModuleMysqlMq\Model\DataObjectFactory::class); + /** @var \Magento\TestModuleMysqlMq\Model\DataObject $object */ $object = $objectFactory->create(); + $object->setOutputPath($this->logFilePath); + file_put_contents($this->logFilePath, ''); for ($i = 0; $i < 10; $i++) { $object->setName('Object name ' . $i)->setEntityId($i); $this->publisher->publish('demo.object.created', $object); @@ -96,105 +54,87 @@ public function testPublishConsumeFlow() $object->setName('Object name ' . $i)->setEntityId($i); $this->publisher->publish('demo.object.custom.created', $object); } - - $outputPattern = '/(Processed \d+\s)/'; - /** There are total of 10 messages in the first queue, total expected consumption is 7, 3 then 0 */ - $this->consumeMessages('demoConsumerQueueOne', 7, 7, $outputPattern); - /** Consumer all messages which left in this queue */ - $this->consumeMessages('demoConsumerQueueOne', PHP_INT_MAX, 3, $outputPattern); - $this->consumeMessages('demoConsumerQueueOne', 7, 0, $outputPattern); - - /** Verify that messages were added correctly to second queue for update and create topics */ - $this->consumeMessages('demoConsumerQueueTwo', 20, 15, $outputPattern); - - /** Verify that messages were NOT added to fourth queue */ - $this->consumeMessages('demoConsumerQueueFour', 11, 0, $outputPattern); - - /** Verify that messages were added correctly by '*' pattern in bind config to third queue */ - $this->consumeMessages('demoConsumerQueueThree', 20, 15, $outputPattern); - - /** Verify that messages were added correctly by '#' pattern in bind config to fifth queue */ - $this->consumeMessages('demoConsumerQueueFive', 20, 18, $outputPattern); + $this->waitForAsynchronousResult(18, $this->logFilePath); + + //Check lines in file + $createdPattern = '/Processed object created \d+/'; + $updatedPattern = '/Processed object updated \d+/'; + $customCreatedPattern = '/Processed custom object created \d+/'; + $logFileContents = file_get_contents($this->logFilePath); + + preg_match_all($createdPattern, $logFileContents, $createdMatches); + $this->assertEquals(10, count($createdMatches[0])); + preg_match_all($updatedPattern, $logFileContents, $updatedMatches); + $this->assertEquals(5, count($updatedMatches[0])); + preg_match_all($customCreatedPattern, $logFileContents, $customCreatedMatches); + $this->assertEquals(3, count($customCreatedMatches[0])); } /** * @magentoDataFixture Magento/MysqlMq/_files/queues.php */ - public function testPublishAndConsumeWithFailedJobs() + public function testPublishAndConsumeSchemaDefinedByMethod() { - /** @var \Magento\MysqlMq\Model\DataObjectFactory $objectFactory */ - $objectFactory = $this->objectManager->create(\Magento\MysqlMq\Model\DataObjectFactory::class); - /** @var \Magento\MysqlMq\Model\DataObject $object */ - /** Try consume messages for MAX_NUMBER_OF_TRIALS and then consumer them without exception */ + $topic = 'test.schema.defined.by.method'; + /** @var \Magento\TestModuleMysqlMq\Model\DataObjectFactory $objectFactory */ + $objectFactory = $this->objectManager->create(\Magento\TestModuleMysqlMq\Model\DataObjectFactory::class); + /** @var \Magento\TestModuleMysqlMq\Model\DataObject $object */ $object = $objectFactory->create(); - for ($i = 0; $i < 5; $i++) { - $object->setName('Object name ' . $i)->setEntityId($i); - $this->publisher->publish('demo.object.created', $object); - } - $outputPattern = '/(Processed \d+\s)/'; - for ($i = 0; $i < self::MAX_NUMBER_OF_TRIALS; $i++) { - $this->consumeMessages('demoConsumerQueueOneWithException', PHP_INT_MAX, 0, $outputPattern); - } - $this->consumeMessages('demoConsumerQueueOne', PHP_INT_MAX, 0, $outputPattern); + $id = 33; + $object->setName('Object name ' . $id)->setEntityId($id); + $object->setOutputPath($this->logFilePath); + $requiredStringParam = 'Required value'; + $optionalIntParam = 44; + $this->publisher->publish($topic, [$object, $requiredStringParam, $optionalIntParam]); - /** Try consume messages for MAX_NUMBER_OF_TRIALS+1 and then consumer them without exception */ - for ($i = 0; $i < 5; $i++) { - $object->setName('Object name ' . $i)->setEntityId($i); - $this->publisher->publish('demo.object.created', $object); - } - /** Try consume messages for MAX_NUMBER_OF_TRIALS and then consumer them without exception */ - for ($i = 0; $i < self::MAX_NUMBER_OF_TRIALS + 1; $i++) { - $this->consumeMessages('demoConsumerQueueOneWithException', PHP_INT_MAX, 0, $outputPattern); - } - /** Make sure that messages are not accessible anymore after number of trials is exceeded */ - $this->consumeMessages('demoConsumerQueueOne', PHP_INT_MAX, 0, $outputPattern); + $expectedOutput = "Processed '{$object->getEntityId()}'; " + . "Required param '{$requiredStringParam}'; Optional param '{$optionalIntParam}'"; + + $this->waitForAsynchronousResult(1, $this->logFilePath); + + $this->assertEquals($expectedOutput, trim(file_get_contents($this->logFilePath))); } /** * @magentoDataFixture Magento/MysqlMq/_files/queues.php */ - public function testPublishAndConsumeSchemaDefinedByMethod() + public function testConsumeWithException() { - /** @var \Magento\MysqlMq\Model\DataObjectFactory $objectFactory */ - $objectFactory = $this->objectManager->create(\Magento\MysqlMq\Model\DataObjectFactory::class); - /** @var \Magento\MysqlMq\Model\DataObject $object */ + $topic = 'demo.exception'; + /** @var \Magento\TestModuleMysqlMq\Model\DataObjectFactory $objectFactory */ + $objectFactory = $this->objectManager->create(\Magento\TestModuleMysqlMq\Model\DataObjectFactory::class); + /** @var \Magento\TestModuleMysqlMq\Model\DataObject $object */ $object = $objectFactory->create(); - $id = 33; + $id = 99; + $object->setName('Object name ' . $id)->setEntityId($id); - $requiredStringParam = 'Required value'; - $optionalIntParam = 44; - $this->publisher->publish('test.schema.defined.by.method', [$object, $requiredStringParam, $optionalIntParam]); - $outputPattern = "/Processed '{$object->getEntityId()}'; " - . "Required param '{$requiredStringParam}'; Optional param '{$optionalIntParam}'/"; - $this->consumeMessages('delayedOperationConsumer', PHP_INT_MAX, 1, $outputPattern); + $object->setOutputPath($this->logFilePath); + $this->publisher->publish($topic, $object); + $expectedOutput = "Exception processing {$id}"; + $this->waitForAsynchronousResult(1, $this->logFilePath); + $message = $this->getTopicLatestMessage($topic); + $this->assertEquals($expectedOutput, trim(file_get_contents($this->logFilePath))); + $this->assertEquals(QueueManagement::MESSAGE_STATUS_ERROR, $message->getStatus()); } /** - * Make sure that consumers consume correct number of messages. - * - * @param string $consumerName - * @param int|null $messagesToProcess - * @param int|null $expectedNumberOfProcessedMessages - * @param string|null $outputPattern + * @param string $topic + * @return Message */ - protected function consumeMessages( - $consumerName, - $messagesToProcess, - $expectedNumberOfProcessedMessages = null, - $outputPattern = null - ) { - /** @var \Magento\Framework\MessageQueue\ConsumerFactory $consumerFactory */ - $consumerFactory = $this->objectManager->create(\Magento\Framework\MessageQueue\ConsumerFactory::class); - $consumer = $consumerFactory->get($consumerName); - ob_start(); - $consumer->process($messagesToProcess); - $consumersOutput = ob_get_contents(); - ob_end_clean(); - if ($outputPattern) { - $this->assertEquals( - $expectedNumberOfProcessedMessages, - preg_match_all($outputPattern, $consumersOutput) - ); - } + private function getTopicLatestMessage(string $topic) : Message + { + // Assert message status is error + $messageCollection = $this->objectManager->create(MessageCollection::class); + $messageStatusCollection = $this->objectManager->create(MessageStatusCollection::class); + + $messageCollection->addFilter('topic_name', $topic); + $messageCollection->join( + ['status' => $messageStatusCollection->getMainTable()], + "status.message_id = main_table.id" + ); + $messageCollection->addOrder('updated_at', MessageCollection::SORT_ORDER_DESC); + + $message = $messageCollection->getFirstItem(); + return $message; } } diff --git a/dev/tests/integration/testsuite/Magento/MysqlMq/Model/QueueManagementTest.php b/dev/tests/integration/testsuite/Magento/MysqlMq/Model/QueueManagementTest.php index 197df29233297..56dd77d3da17c 100644 --- a/dev/tests/integration/testsuite/Magento/MysqlMq/Model/QueueManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/MysqlMq/Model/QueueManagementTest.php @@ -5,8 +5,6 @@ */ namespace Magento\MysqlMq\Model; -use Magento\MysqlMq\Model\QueueManagement; - /** * Test for Queue Management class. */ diff --git a/dev/tests/integration/testsuite/Magento/MysqlMq/etc/queue.xml b/dev/tests/integration/testsuite/Magento/MysqlMq/etc/queue.xml deleted file mode 100644 index fd618d504df07..0000000000000 --- a/dev/tests/integration/testsuite/Magento/MysqlMq/etc/queue.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 9a7f3e6c567b1b83d920655be75176daaa66b4c8 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Thu, 11 Oct 2018 22:47:36 +0200 Subject: [PATCH 007/585] allows to define argument shareable state --- .../layout/adminhtml_notification_block.xml | 2 +- .../adminhtml/layout/catalog_search_block.xml | 2 +- .../layout/adminhtml_cache_block.xml | 2 +- .../adminhtml_system_design_grid_block.xml | 2 +- .../adminhtml_system_store_grid_block.xml | 2 +- .../adminhtml/layout/backup_index_block.xml | 2 +- .../layout/catalog_product_set_block.xml | 2 +- .../catalog_rule_promo_catalog_block.xml | 2 +- .../adminhtml_email_template_grid_block.xml | 2 +- .../layout/groupedproduct_popup_grid.xml | 2 +- .../layout/adminhtml_history_grid_block.xml | 2 +- .../layout/indexer_indexer_list_grid.xml | 2 +- .../adminhtml_integration_grid_block.xml | 2 +- .../layout/newsletter_problem_block.xml | 2 +- .../layout/newsletter_queue_grid_block.xml | 2 +- .../layout/newsletter_subscriber_block.xml | 2 +- .../layout/adminhtml_paypal_reports_block.xml | 2 +- .../paypal_billing_agreement_ordersgrid.xml | 2 +- .../layout/paypal_billing_agreement_view.xml | 2 +- .../reports_report_customer_accounts_grid.xml | 2 +- .../reports_report_customer_orders_grid.xml | 2 +- .../reports_report_customer_totals_grid.xml | 2 +- .../adminhtml/layout/reports_report_grid.xml | 2 +- .../reports_report_product_lowstock_grid.xml | 2 +- .../reports_report_product_sold_grid.xml | 2 +- .../reports_report_review_customer_grid.xml | 2 +- .../reports_report_review_product_grid.xml | 2 +- .../reports_report_statistics_index.xml | 2 +- .../view/adminhtml/layout/rating_block.xml | 2 +- .../sales_order_create_customer_block.xml | 2 +- .../sales_order_creditmemo_grid_block.xml | 2 +- .../layout/sales_order_invoice_grid_block.xml | 2 +- .../sales_order_shipment_grid_block.xml | 2 +- .../layout/sales_order_status_index.xml | 2 +- .../sales_order_transactions_grid_block.xml | 2 +- .../layout/sales_transaction_child_block.xml | 2 +- .../layout/sales_transactions_grid_block.xml | 2 +- .../layout/sales_rule_promo_quote_index.xml | 2 +- .../adminhtml/layout/search_term_block.xml | 2 +- .../layout/search_term_grid_block.xml | 2 +- .../layout/search_term_report_block.xml | 2 +- .../adminhtml_sitemap_index_grid_block.xml | 2 +- .../view/adminhtml/layout/tax_rate_block.xml | 2 +- .../view/adminhtml/layout/tax_rule_block.xml | 2 +- .../adminhtml_system_design_theme_block.xml | 2 +- .../layout/adminhtml_url_rewrite_index.xml | 2 +- .../layout/adminhtml_locks_block.xml | 2 +- .../layout/adminhtml_user_grid_block.xml | 2 +- .../layout/adminhtml_user_role_grid_block.xml | 2 +- .../adminhtml_system_variable_grid_block.xml | 2 +- .../adminhtml_widget_instance_block.xml | 2 +- .../layout/customer_index_wishlist.xml | 2 +- .../Argument/Interpreter/DataObject.php | 30 +++++-- .../Framework/View/Layout/etc/elements.xsd | 1 + .../Argument/Interpreter/ObjectTest.php | 86 ++++++++++++++++++- 55 files changed, 160 insertions(+), 61 deletions(-) diff --git a/app/code/Magento/AdminNotification/view/adminhtml/layout/adminhtml_notification_block.xml b/app/code/Magento/AdminNotification/view/adminhtml/layout/adminhtml_notification_block.xml index c68313211c2e6..06fd380cb2a44 100644 --- a/app/code/Magento/AdminNotification/view/adminhtml/layout/adminhtml_notification_block.xml +++ b/app/code/Magento/AdminNotification/view/adminhtml/layout/adminhtml_notification_block.xml @@ -11,7 +11,7 @@ notificationGrid - Magento\AdminNotification\Model\ResourceModel\Grid\Collection + Magento\AdminNotification\Model\ResourceModel\Grid\Collection DESC date_added 1 diff --git a/app/code/Magento/AdvancedSearch/view/adminhtml/layout/catalog_search_block.xml b/app/code/Magento/AdvancedSearch/view/adminhtml/layout/catalog_search_block.xml index b6ef596281e51..f3544863348ec 100644 --- a/app/code/Magento/AdvancedSearch/view/adminhtml/layout/catalog_search_block.xml +++ b/app/code/Magento/AdvancedSearch/view/adminhtml/layout/catalog_search_block.xml @@ -11,7 +11,7 @@ catalog_search_grid - Magento\AdvancedSearch\Model\ResourceModel\Search\Grid\Collection + Magento\AdvancedSearch\Model\ResourceModel\Search\Grid\Collection name ASC 1 diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml index 50d210f71025b..6d2ecd8d36a99 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml @@ -11,7 +11,7 @@ cache_grid - Magento\Backend\Model\Cache\ResourceModel\Grid\Collection + Magento\Backend\Model\Cache\ResourceModel\Grid\Collection 0 diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid_block.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid_block.xml index b96614f4bd8db..41bfe6e78a2ad 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid_block.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid_block.xml @@ -11,7 +11,7 @@ designGrid - Magento\Theme\Model\ResourceModel\Design\Collection + Magento\Theme\Model\ResourceModel\Design\Collection 1 1 diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_grid_block.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_grid_block.xml index 126de5eb4084f..d0c0d8fcbf69b 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_grid_block.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_grid_block.xml @@ -12,7 +12,7 @@ storeGrid 1 - Magento\Store\Model\ResourceModel\Website\Grid\Collection + Magento\Store\Model\ResourceModel\Website\Grid\Collection diff --git a/app/code/Magento/Backup/view/adminhtml/layout/backup_index_block.xml b/app/code/Magento/Backup/view/adminhtml/layout/backup_index_block.xml index e17618b97e21f..e3e984d933f25 100644 --- a/app/code/Magento/Backup/view/adminhtml/layout/backup_index_block.xml +++ b/app/code/Magento/Backup/view/adminhtml/layout/backup_index_block.xml @@ -11,7 +11,7 @@ backupsGrid - Magento\Backup\Model\Fs\Collection + Magento\Backup\Model\Fs\Collection time desc diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_block.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_block.xml index 44884897461a8..4e7396608826b 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_block.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_block.xml @@ -11,7 +11,7 @@ setGrid - Magento\Eav\Model\ResourceModel\Entity\Attribute\Grid\Collection + Magento\Eav\Model\ResourceModel\Entity\Attribute\Grid\Collection set_name ASC 1 diff --git a/app/code/Magento/CatalogRule/view/adminhtml/layout/catalog_rule_promo_catalog_block.xml b/app/code/Magento/CatalogRule/view/adminhtml/layout/catalog_rule_promo_catalog_block.xml index 99d64ed7a635f..f38f6e0fcd850 100644 --- a/app/code/Magento/CatalogRule/view/adminhtml/layout/catalog_rule_promo_catalog_block.xml +++ b/app/code/Magento/CatalogRule/view/adminhtml/layout/catalog_rule_promo_catalog_block.xml @@ -11,7 +11,7 @@ promo_catalog_grid - Magento\CatalogRule\Model\ResourceModel\Grid\Collection + Magento\CatalogRule\Model\ResourceModel\Grid\Collection name ASC 1 diff --git a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_grid_block.xml b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_grid_block.xml index fa15560817dd9..87da146d8ce56 100644 --- a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_grid_block.xml +++ b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_grid_block.xml @@ -11,7 +11,7 @@ systemEmailTemplateGrid - Magento\Email\Model\ResourceModel\Template\Collection + Magento\Email\Model\ResourceModel\Template\Collection 1 1 diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml index 503404c6cb3cf..fab7851df5bc4 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml @@ -11,7 +11,7 @@ grouped_grid_popup - Magento\GroupedProduct\Model\ResourceModel\Product\Type\Grouped\AssociatedProductsCollection + Magento\GroupedProduct\Model\ResourceModel\Product\Type\Grouped\AssociatedProductsCollection 1 id ASC diff --git a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_grid_block.xml b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_grid_block.xml index 02fc198cb0ada..51e5827c8ab98 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_grid_block.xml +++ b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_grid_block.xml @@ -11,7 +11,7 @@ importHistoryGrid - Magento\ImportExport\Model\ResourceModel\History\Collection + Magento\ImportExport\Model\ResourceModel\History\Collection history_id desc diff --git a/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml b/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml index bf6b2351f75f1..f1099c4133bca 100644 --- a/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml +++ b/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml @@ -13,7 +13,7 @@ 0 0 gridIndexer - Magento\Indexer\Ui\DataProvider\Indexer\DataCollection + Magento\Indexer\Ui\DataProvider\Indexer\DataCollection diff --git a/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml b/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml index 506f836f99514..43b67d6904f1a 100644 --- a/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml +++ b/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml @@ -13,7 +13,7 @@ integrationGrid - Magento\Integration\Model\ResourceModel\Integration\Collection + Magento\Integration\Model\ResourceModel\Integration\Collection 1 integration_id asc diff --git a/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_problem_block.xml b/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_problem_block.xml index 3eb7de194d242..008cb9c003e5f 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_problem_block.xml +++ b/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_problem_block.xml @@ -11,7 +11,7 @@ problemGrid - Magento\Newsletter\Model\ResourceModel\Grid\Collection + Magento\Newsletter\Model\ResourceModel\Grid\Collection true true 1 diff --git a/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_queue_grid_block.xml b/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_queue_grid_block.xml index 3bfb52157bb99..8a2c891c68f81 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_queue_grid_block.xml +++ b/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_queue_grid_block.xml @@ -11,7 +11,7 @@ queueGrid - Magento\Newsletter\Model\ResourceModel\Queue\Grid\Collection + Magento\Newsletter\Model\ResourceModel\Queue\Grid\Collection start_at DESC 1 diff --git a/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_subscriber_block.xml b/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_subscriber_block.xml index 9de1807af18ec..e8600c2d49d7b 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_subscriber_block.xml +++ b/app/code/Magento/Newsletter/view/adminhtml/layout/newsletter_subscriber_block.xml @@ -11,7 +11,7 @@ subscriberGrid - Magento\Newsletter\Model\ResourceModel\Subscriber\Grid\Collection + Magento\Newsletter\Model\ResourceModel\Subscriber\Grid\Collection subscriber_id desc 1 diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/adminhtml_paypal_reports_block.xml b/app/code/Magento/Paypal/view/adminhtml/layout/adminhtml_paypal_reports_block.xml index 12dcc46e3ecee..596381a4b1143 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/adminhtml_paypal_reports_block.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/adminhtml_paypal_reports_block.xml @@ -11,7 +11,7 @@ settlementGrid - Magento\Paypal\Model\ResourceModel\Report\Settlement\Row\Collection + Magento\Paypal\Model\ResourceModel\Report\Settlement\Row\Collection row_id DESC 1 diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml index 76a105f5abcdf..0510011a6a559 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml @@ -9,7 +9,7 @@ - + Magento\Paypal\Model\Billing\Agreement\OrdersUpdater diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_view.xml b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_view.xml index c76539f5cb206..d9c376701db33 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_view.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_view.xml @@ -12,7 +12,7 @@ - + Magento\Paypal\Model\Billing\Agreement\OrdersUpdater diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_accounts_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_accounts_grid.xml index 900dc08d571da..55ca286ad3d47 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_accounts_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_accounts_grid.xml @@ -11,7 +11,7 @@ gridAccounts - Magento\Reports\Model\ResourceModel\Accounts\Collection\Initial + Magento\Reports\Model\ResourceModel\Accounts\Collection\Initial diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_orders_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_orders_grid.xml index d886e5724cb0b..f97bec3c15253 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_orders_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_orders_grid.xml @@ -11,7 +11,7 @@ gridOrdersCustomer - Magento\Reports\Model\ResourceModel\Customer\Orders\Collection\Initial + Magento\Reports\Model\ResourceModel\Customer\Orders\Collection\Initial diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_totals_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_totals_grid.xml index 4914829cf6ebc..e1df04237c2a6 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_totals_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_customer_totals_grid.xml @@ -11,7 +11,7 @@ gridTotalsCustomer - Magento\Reports\Model\ResourceModel\Customer\Totals\Collection\Initial + Magento\Reports\Model\ResourceModel\Customer\Totals\Collection\Initial diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_grid.xml index 82aa475807a25..0f6fbabb6a55c 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_grid.xml @@ -24,7 +24,7 @@ 0 0 gridReport - Magento\Reports\Model\ResourceModel\Report\Collection + Magento\Reports\Model\ResourceModel\Report\Collection diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_product_lowstock_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_product_lowstock_grid.xml index 070c39259aabd..62916fe1c1d78 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_product_lowstock_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_product_lowstock_grid.xml @@ -12,7 +12,7 @@ gridLowstock 0 - Magento\Reports\Model\ResourceModel\Product\Lowstock\Collection + Magento\Reports\Model\ResourceModel\Product\Lowstock\Collection diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_product_sold_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_product_sold_grid.xml index a1b01aeeb526f..22c66352b32e4 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_product_sold_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_product_sold_grid.xml @@ -11,7 +11,7 @@ gridProductsSold - Magento\Reports\Model\ResourceModel\Product\Sold\Collection\Initial + Magento\Reports\Model\ResourceModel\Product\Sold\Collection\Initial diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_customer_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_customer_grid.xml index f941ca52eef59..a728f471e4def 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_customer_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_customer_grid.xml @@ -13,7 +13,7 @@ customers_grid review_cnt desc - Magento\Reports\Model\ResourceModel\Review\Customer\Collection + Magento\Reports\Model\ResourceModel\Review\Customer\Collection diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml index 1275e761ade3c..26d0e8b13659d 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml @@ -13,7 +13,7 @@ gridProducts review_cnt desc - Magento\Reports\Model\ResourceModel\Review\Product\Collection + Magento\Reports\Model\ResourceModel\Review\Product\Collection diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_statistics_index.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_statistics_index.xml index 4ec984ef9fc11..649dc7ceeb065 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_statistics_index.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_statistics_index.xml @@ -15,7 +15,7 @@ 0 0 0 - Magento\Reports\Model\ResourceModel\Refresh\Collection + Magento\Reports\Model\ResourceModel\Refresh\Collection diff --git a/app/code/Magento/Review/view/adminhtml/layout/rating_block.xml b/app/code/Magento/Review/view/adminhtml/layout/rating_block.xml index b439bcb1c2710..414cec14c3bec 100644 --- a/app/code/Magento/Review/view/adminhtml/layout/rating_block.xml +++ b/app/code/Magento/Review/view/adminhtml/layout/rating_block.xml @@ -11,7 +11,7 @@ ratingsGrid - Magento\Review\Model\ResourceModel\Rating\Grid\Collection + Magento\Review\Model\ResourceModel\Rating\Grid\Collection rating_code ASC 1 diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_customer_block.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_customer_block.xml index c321bee460e46..e11a5887beb61 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_customer_block.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_customer_block.xml @@ -13,7 +13,7 @@ sales_order_create_customer_grid 1 entity_id - Magento\Sales\Model\ResourceModel\Order\Customer\Collection + Magento\Sales\Model\ResourceModel\Order\Customer\Collection 1 customer_grid diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_grid_block.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_grid_block.xml index 7f14ff3728a47..318416a777f3f 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_grid_block.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_grid_block.xml @@ -11,7 +11,7 @@ order_creditmemos - Magento\Sales\Model\ResourceModel\Order\Creditmemo\Order\Grid\Collection + Magento\Sales\Model\ResourceModel\Order\Creditmemo\Order\Grid\Collection true created_at DESC diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_grid_block.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_grid_block.xml index 941696f0ce898..d69ed42677109 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_grid_block.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_grid_block.xml @@ -11,7 +11,7 @@ order_invoices - Magento\Sales\Model\ResourceModel\Order\Invoice\Orders\Grid\Collection + Magento\Sales\Model\ResourceModel\Order\Invoice\Orders\Grid\Collection true created_at DESC diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_shipment_grid_block.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_shipment_grid_block.xml index 0180efd29d2fc..21b5d3b06c167 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_shipment_grid_block.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_shipment_grid_block.xml @@ -11,7 +11,7 @@ order_shipments - Magento\Sales\Model\ResourceModel\Order\Shipment\Order\Grid\Collection + Magento\Sales\Model\ResourceModel\Order\Shipment\Order\Grid\Collection true created_at DESC diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_status_index.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_status_index.xml index 87d7644a4b00f..6854d3bb7bc38 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_status_index.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_status_index.xml @@ -12,7 +12,7 @@ sales_order_status_grid - Magento\Sales\Model\ResourceModel\Status\Collection + Magento\Sales\Model\ResourceModel\Status\Collection state desc 1 diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_transactions_grid_block.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_transactions_grid_block.xml index c2f5532857202..adb722f6d0f54 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_transactions_grid_block.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_transactions_grid_block.xml @@ -13,7 +13,7 @@ order_transactions - + Magento\Sales\Model\Grid\CollectionUpdater true diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_transaction_child_block.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_transaction_child_block.xml index aa8672a68bc6c..5bdad85ebc160 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_transaction_child_block.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_transaction_child_block.xml @@ -11,7 +11,7 @@ transactionChildGrid - + Magento\Sales\Model\Grid\Child\CollectionUpdater false diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_transactions_grid_block.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_transactions_grid_block.xml index 9f3b7f23ba20f..37b319b94352d 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_transactions_grid_block.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_transactions_grid_block.xml @@ -11,7 +11,7 @@ sales_transactions_grid - Magento\Sales\Model\ResourceModel\Transaction\Grid\Collection + Magento\Sales\Model\ResourceModel\Transaction\Grid\Collection true created_at DESC diff --git a/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_index.xml b/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_index.xml index 21ce8bfc3eaac..7796f280efcbc 100644 --- a/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_index.xml +++ b/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_index.xml @@ -12,7 +12,7 @@ promo_quote_grid - Magento\SalesRule\Model\ResourceModel\Rule\Quote\Collection + Magento\SalesRule\Model\ResourceModel\Rule\Quote\Collection sort_order ASC 1 diff --git a/app/code/Magento/Search/view/adminhtml/layout/search_term_block.xml b/app/code/Magento/Search/view/adminhtml/layout/search_term_block.xml index cc2e1509e4412..9dc60bde11315 100644 --- a/app/code/Magento/Search/view/adminhtml/layout/search_term_block.xml +++ b/app/code/Magento/Search/view/adminhtml/layout/search_term_block.xml @@ -11,7 +11,7 @@ searchReportGrid - Magento\Search\Model\ResourceModel\Query\Collection + Magento\Search\Model\ResourceModel\Query\Collection query_id DESC diff --git a/app/code/Magento/Search/view/adminhtml/layout/search_term_grid_block.xml b/app/code/Magento/Search/view/adminhtml/layout/search_term_grid_block.xml index 7330ac1f92712..38c6fa52455b9 100644 --- a/app/code/Magento/Search/view/adminhtml/layout/search_term_grid_block.xml +++ b/app/code/Magento/Search/view/adminhtml/layout/search_term_grid_block.xml @@ -11,7 +11,7 @@ search_term_grid - Magento\Search\Model\ResourceModel\Query\Collection + Magento\Search\Model\ResourceModel\Query\Collection name ASC 1 diff --git a/app/code/Magento/Search/view/adminhtml/layout/search_term_report_block.xml b/app/code/Magento/Search/view/adminhtml/layout/search_term_report_block.xml index b6b1455cf27ca..f4c5d1ab85a0a 100644 --- a/app/code/Magento/Search/view/adminhtml/layout/search_term_report_block.xml +++ b/app/code/Magento/Search/view/adminhtml/layout/search_term_report_block.xml @@ -12,7 +12,7 @@ searchReportGrid - Magento\Search\Model\ResourceModel\Query\Collection + Magento\Search\Model\ResourceModel\Query\Collection query_id DESC diff --git a/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index_grid_block.xml b/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index_grid_block.xml index cdaa6575d559c..632768e4a5f08 100644 --- a/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index_grid_block.xml +++ b/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index_grid_block.xml @@ -11,7 +11,7 @@ sitemapGrid - Magento\Sitemap\Model\ResourceModel\Sitemap\Collection + Magento\Sitemap\Model\ResourceModel\Sitemap\Collection sitemap_id diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml index 463994262b7d3..5c50b306411ed 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml @@ -11,7 +11,7 @@ tax_rate_grid - Magento\Tax\Model\TaxRateCollection + Magento\Tax\Model\TaxRateCollection region_name ASC 1 diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml index 5e42b835c035d..07afd05e63f8c 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml @@ -11,7 +11,7 @@ taxRuleGrid - Magento\Tax\Model\TaxRuleCollection + Magento\Tax\Model\TaxRuleCollection tax_rule_id ASC 1 diff --git a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_block.xml b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_block.xml index bb8fbd44629cf..e19460d56a89b 100644 --- a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_block.xml +++ b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_block.xml @@ -11,7 +11,7 @@ theme_grid - Magento\Theme\Model\ResourceModel\Theme\Grid\Collection + Magento\Theme\Model\ResourceModel\Theme\Grid\Collection 1 1 diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/layout/adminhtml_url_rewrite_index.xml b/app/code/Magento/UrlRewrite/view/adminhtml/layout/adminhtml_url_rewrite_index.xml index 7d8151d270308..8b4910b625321 100644 --- a/app/code/Magento/UrlRewrite/view/adminhtml/layout/adminhtml_url_rewrite_index.xml +++ b/app/code/Magento/UrlRewrite/view/adminhtml/layout/adminhtml_url_rewrite_index.xml @@ -12,7 +12,7 @@ urlrewriteGrid - Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection + Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection url_rewrite_id diff --git a/app/code/Magento/User/view/adminhtml/layout/adminhtml_locks_block.xml b/app/code/Magento/User/view/adminhtml/layout/adminhtml_locks_block.xml index 13cfbfe859333..d195ac93c16e5 100644 --- a/app/code/Magento/User/view/adminhtml/layout/adminhtml_locks_block.xml +++ b/app/code/Magento/User/view/adminhtml/layout/adminhtml_locks_block.xml @@ -12,7 +12,7 @@ lockedAdminsGrid - Magento\User\Model\ResourceModel\User\Locked\Collection + Magento\User\Model\ResourceModel\User\Locked\Collection user_id 1 diff --git a/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_grid_block.xml b/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_grid_block.xml index a4bc9aa5ed48b..9099028ce9bfc 100644 --- a/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_grid_block.xml +++ b/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_grid_block.xml @@ -11,7 +11,7 @@ permissionsUserGrid - Magento\User\Model\ResourceModel\User\Collection + Magento\User\Model\ResourceModel\User\Collection 1 username asc diff --git a/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_role_grid_block.xml b/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_role_grid_block.xml index 6d7ce67e2352b..f2d699b6cc08b 100644 --- a/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_role_grid_block.xml +++ b/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_role_grid_block.xml @@ -11,7 +11,7 @@ roleGrid - Magento\Authorization\Model\ResourceModel\Role\Grid\Collection + Magento\Authorization\Model\ResourceModel\Role\Grid\Collection 1 role_id asc diff --git a/app/code/Magento/Variable/view/adminhtml/layout/adminhtml_system_variable_grid_block.xml b/app/code/Magento/Variable/view/adminhtml/layout/adminhtml_system_variable_grid_block.xml index d934e46117fb1..edee7fcca8222 100644 --- a/app/code/Magento/Variable/view/adminhtml/layout/adminhtml_system_variable_grid_block.xml +++ b/app/code/Magento/Variable/view/adminhtml/layout/adminhtml_system_variable_grid_block.xml @@ -11,7 +11,7 @@ customVariablesGrid - Magento\Variable\Model\ResourceModel\Variable\Collection + Magento\Variable\Model\ResourceModel\Variable\Collection variable_id ASC diff --git a/app/code/Magento/Widget/view/adminhtml/layout/adminhtml_widget_instance_block.xml b/app/code/Magento/Widget/view/adminhtml/layout/adminhtml_widget_instance_block.xml index 934b0ca1a85b2..8ca3fab413b25 100644 --- a/app/code/Magento/Widget/view/adminhtml/layout/adminhtml_widget_instance_block.xml +++ b/app/code/Magento/Widget/view/adminhtml/layout/adminhtml_widget_instance_block.xml @@ -13,7 +13,7 @@ widgetInstanceGrid instance_id ASC - Magento\Widget\Model\ResourceModel\Widget\Instance\Collection + Magento\Widget\Model\ResourceModel\Widget\Instance\Collection diff --git a/app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_wishlist.xml b/app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_wishlist.xml index 95b786603390c..e364087405ed9 100644 --- a/app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_wishlist.xml +++ b/app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_wishlist.xml @@ -9,7 +9,7 @@ - Magento\Wishlist\Model\ResourceModel\Item\Collection\Grid + Magento\Wishlist\Model\ResourceModel\Item\Collection\Grid wishlistGrid true added_at diff --git a/lib/internal/Magento/Framework/View/Layout/Argument/Interpreter/DataObject.php b/lib/internal/Magento/Framework/View/Layout/Argument/Interpreter/DataObject.php index ea9fef369e312..fb528a0fd1c91 100644 --- a/lib/internal/Magento/Framework/View/Layout/Argument/Interpreter/DataObject.php +++ b/lib/internal/Magento/Framework/View/Layout/Argument/Interpreter/DataObject.php @@ -3,10 +3,14 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Framework\View\Layout\Argument\Interpreter; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Data\Argument\InterpreterInterface; use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Stdlib\BooleanUtils; /** * Interpreter that instantiates object by a class name @@ -14,23 +18,33 @@ class DataObject implements InterpreterInterface { /** - * @var ObjectManagerInterface + * @var \Magento\Framework\ObjectManagerInterface */ private $objectManager; + /** + * @var \Magento\Framework\Stdlib\BooleanUtils + */ + private $booleanUtils; + /** * @var string|null */ private $expectedClass; /** - * @param ObjectManagerInterface $objectManager + * @param \Magento\Framework\ObjectManagerInterface $objectManager * @param string|null $expectedClass + * @param \Magento\Framework\Stdlib\BooleanUtils|null $booleanUtils */ - public function __construct(ObjectManagerInterface $objectManager, $expectedClass = null) - { + public function __construct( + ObjectManagerInterface $objectManager, + ?string $expectedClass = null, + ?BooleanUtils $booleanUtils = null + ) { $this->objectManager = $objectManager; $this->expectedClass = $expectedClass; + $this->booleanUtils = $booleanUtils ?? ObjectManager::getInstance()->get(BooleanUtils::class); } /** @@ -44,13 +58,17 @@ public function evaluate(array $data) if (!isset($data['value'])) { throw new \InvalidArgumentException('Object class name is missing.'); } + + $shared = isset($data['shared']) ? $this->booleanUtils->toBoolean($data['shared']) : true; $className = $data['value']; - $result = $this->objectManager->create($className); + $result = $shared ? $this->objectManager->get($className) : $this->objectManager->create($className); + if ($this->expectedClass && !$result instanceof $this->expectedClass) { throw new \UnexpectedValueException( - sprintf("Instance of %s is expected, got %s instead.", $this->expectedClass, get_class($result)) + \sprintf('Instance of %s is expected, got %s instead.', $this->expectedClass, \get_class($result)) ); } + return $result; } } diff --git a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd index 39cdec05a65ea..f3967bb2fca45 100755 --- a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd +++ b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd @@ -14,6 +14,7 @@ + diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php index 7cc280a930d9c..180888bcc1d3e 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php @@ -5,7 +5,7 @@ */ namespace Magento\Framework\View\Test\Unit\Layout\Argument\Interpreter; -use \Magento\Framework\View\Layout\Argument\Interpreter\DataObject; +use Magento\Framework\View\Layout\Argument\Interpreter\DataObject; class ObjectTest extends \PHPUnit\Framework\TestCase { @@ -22,19 +22,55 @@ class ObjectTest extends \PHPUnit\Framework\TestCase protected $_interpreter; /** - * @var DataObject + * @var \Magento\Framework\Stdlib\BooleanUtils + */ + protected $_booleanUtils; + + /** + * @var \Magento\Framework\View\Layout\Argument\Interpreter\DataObject */ protected $_model; protected function setUp() { $this->_objectManager = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); - $this->_model = new DataObject($this->_objectManager, self::EXPECTED_CLASS); + $this->_booleanUtils = $this->createMock(\Magento\Framework\Stdlib\BooleanUtils::class); + $this->_model = new DataObject($this->_objectManager, self::EXPECTED_CLASS, $this->_booleanUtils); } public function testEvaluate() { $input = ['name' => 'dataSource', 'value' => self::EXPECTED_CLASS]; + $this->_objectManager->expects($this->once()) + ->method('get') + ->with(self::EXPECTED_CLASS) + ->willReturn($this); + + $actual = $this->_model->evaluate($input); + $this->assertSame($this, $actual); + } + + public function textEvaluateShareEnabled() + { + $input = ['name' => 'dataSource', 'value' => self::EXPECTED_CLASS, 'shared' => true]; + $this->_booleanUtils->expects($this->once()) + ->method('toBoolean') + ->willReturn(true); + $this->_objectManager->expects($this->once()) + ->method('get') + ->with(self::EXPECTED_CLASS) + ->willReturn($this); + + $actual = $this->_model->evaluate($input); + $this->assertSame($this, $actual); + } + + public function textEvaluateShareDisabled() + { + $input = ['name' => 'dataSource', 'value' => self::EXPECTED_CLASS, 'shared' => false]; + $this->_booleanUtils->expects($this->once()) + ->method('toBoolean') + ->willReturn(false); $this->_objectManager->expects($this->once()) ->method('create') ->with(self::EXPECTED_CLASS) @@ -52,12 +88,56 @@ public function testEvaluateWrongClass($input, $expectedException, $expectedExce $this->expectException($expectedException); $this->expectExceptionMessage($expectedExceptionMessage); $self = $this; + $this->_objectManager->expects($this->any())->method('get')->willReturnCallback( + function ($className) use ($self) { + return $self->createMock($className); + } + ); + + $this->_model->evaluate($input); + } + + /** + * @dataProvider evaluateWrongClassDataProvider + */ + public function testEvaluateShareEnabledWrongClass($input, $expectedException, $expectedExceptionMessage) + { + $this->expectException($expectedException); + $this->expectExceptionMessage($expectedExceptionMessage); + $self = $this; + $this->_booleanUtils->expects($this->any()) + ->method('toBoolean') + ->willReturn(true); + $this->_objectManager->expects($this->any())->method('get')->willReturnCallback( + function ($className) use ($self) { + return $self->createMock($className); + } + ); + + $input['shared'] = true; + + $this->_model->evaluate($input); + } + + /** + * @dataProvider evaluateWrongClassDataProvider + */ + public function testEvaluateShareDisabledWrongClass($input, $expectedException, $expectedExceptionMessage) + { + $this->expectException($expectedException); + $this->expectExceptionMessage($expectedExceptionMessage); + $self = $this; + $this->_booleanUtils->expects($this->any()) + ->method('toBoolean') + ->willReturn(false); $this->_objectManager->expects($this->any())->method('create')->willReturnCallback( function ($className) use ($self) { return $self->createMock($className); } ); + $input['shared'] = false; + $this->_model->evaluate($input); } From 415288f8b8bfc4dd3b700e25442b074c260ba30e Mon Sep 17 00:00:00 2001 From: nmalevanec Date: Thu, 20 Dec 2018 13:48:59 +0200 Subject: [PATCH 008/585] Fix static and integration test. --- .../Magento/Test/Integrity/Modular/LayoutFilesTest.php | 5 ++--- .../View/Layout/Argument/Interpreter/DataObject.php | 5 +---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/LayoutFilesTest.php b/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/LayoutFilesTest.php index a11cd4b73b5c7..32a58e285d762 100644 --- a/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/LayoutFilesTest.php +++ b/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/LayoutFilesTest.php @@ -77,9 +77,8 @@ public function layoutArgumentsDataProvider() */ protected function isSkippedArgument(array $argumentData) { - // Do not take into account argument name and parameters - unset($argumentData['name']); - unset($argumentData['param']); + // Do not take into account argument name, shared and parameters + unset($argumentData['name'], $argumentData['param'], $argumentData['shared']); $isUpdater = isset($argumentData['updater']); unset($argumentData['updater']); diff --git a/lib/internal/Magento/Framework/View/Layout/Argument/Interpreter/DataObject.php b/lib/internal/Magento/Framework/View/Layout/Argument/Interpreter/DataObject.php index fb528a0fd1c91..bf607672cae03 100644 --- a/lib/internal/Magento/Framework/View/Layout/Argument/Interpreter/DataObject.php +++ b/lib/internal/Magento/Framework/View/Layout/Argument/Interpreter/DataObject.php @@ -48,10 +48,7 @@ public function __construct( } /** - * {@inheritdoc} - * @return object - * @throws \InvalidArgumentException - * @throws \UnexpectedValueException + * @inheritdoc */ public function evaluate(array $data) { From 9699f1ead0daa81899167d0d66e13bf7a980a912 Mon Sep 17 00:00:00 2001 From: Daniel Renaud Date: Thu, 20 Dec 2018 11:28:13 -0600 Subject: [PATCH 009/585] MC-5588: When using MysqlMQ messages are always set to complete even if exception occurs --- .../Magento/MessageQueue/Model/Cron/ConsumersRunnerTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/MessageQueue/Model/Cron/ConsumersRunnerTest.php b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/Cron/ConsumersRunnerTest.php index 9b2495c5c67d9..3fa80a2dcda1a 100644 --- a/dev/tests/integration/testsuite/Magento/MessageQueue/Model/Cron/ConsumersRunnerTest.php +++ b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/Cron/ConsumersRunnerTest.php @@ -118,9 +118,6 @@ public function testCheckThatPidFilesWasCreated() { $this->markTestSkipped('MC-5904: Test Fails randomly,'); $this->consumersRunner->run(); - - sleep(20); - foreach ($this->consumerConfig->getConsumers() as $consumer) { $this->waitConsumerPidFile($consumer->getName()); } From 5abd3308539fd0449d9ffe22a2d826e1909cc074 Mon Sep 17 00:00:00 2001 From: Julian Wundrak Date: Thu, 20 Dec 2018 22:30:00 +0100 Subject: [PATCH 010/585] [#19908] locale in rest calls is always default locale --- .../Webapi/Controller/PathProcessor.php | 15 ++++++- .../Unit/Controller/PathProcessorTest.php | 44 +++++++++++++------ .../Webapi/Controller/PathProcessorTest.php | 22 ++++++++++ 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Webapi/Controller/PathProcessor.php b/app/code/Magento/Webapi/Controller/PathProcessor.php index c5748cc6e848e..20f1f02e38265 100644 --- a/app/code/Magento/Webapi/Controller/PathProcessor.php +++ b/app/code/Magento/Webapi/Controller/PathProcessor.php @@ -21,12 +21,21 @@ class PathProcessor */ private $storeManager; + /** + * @var \Magento\Framework\Locale\ResolverInterface + */ + private $localeResolver; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param \Magento\Framework\Locale\ResolverInterface $localeResolver */ - public function __construct(\Magento\Store\Model\StoreManagerInterface $storeManager) - { + public function __construct( + \Magento\Store\Model\StoreManagerInterface $storeManager, + \Magento\Framework\Locale\ResolverInterface $localeResolver + ) { $this->storeManager = $storeManager; + $this->localeResolver = $localeResolver; } /** @@ -57,9 +66,11 @@ public function process($pathInfo) $stores = $this->storeManager->getStores(false, true); if (isset($stores[$storeCode])) { $this->storeManager->setCurrentStore($storeCode); + $this->localeResolver->emulate($this->storeManager->getStore()->getId()); $path = '/' . (isset($pathParts[1]) ? $pathParts[1] : ''); } elseif ($storeCode === self::ALL_STORE_CODE) { $this->storeManager->setCurrentStore(\Magento\Store\Model\Store::ADMIN_CODE); + $this->localeResolver->emulate($this->storeManager->getStore()->getId()); $path = '/' . (isset($pathParts[1]) ? $pathParts[1] : ''); } else { $path = '/' . implode('/', $pathParts); diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php index c213c72b5185a..9a1eb249cd9b7 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php @@ -13,6 +13,9 @@ class PathProcessorTest extends \PHPUnit\Framework\TestCase /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\StoreManagerInterface */ private $storeManagerMock; + /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Locale\ResolverInterface */ + private $localeResolverMock; + /** @var \Magento\Webapi\Controller\PathProcessor */ private $model; @@ -24,13 +27,22 @@ class PathProcessorTest extends \PHPUnit\Framework\TestCase protected function setUp() { - $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->storeManagerMock->expects($this->once()) - ->method('getStores') - ->willReturn([$this->arbitraryStoreCode => 'store object', 'default' => 'default store object']); - $this->model = new \Magento\Webapi\Controller\PathProcessor($this->storeManagerMock); + $store = $this->createMock(\Magento\Store\Api\Data\StoreInterface::class); + $store->method('getId')->willReturn(2); + + $this->storeManagerMock = $this->createConfiguredMock( + \Magento\Store\Model\StoreManagerInterface::class, + [ + 'getStores' => [$this->arbitraryStoreCode => 'store object', 'default' => 'default store object'], + 'getStore' => $store, + ] + ); + $this->storeManagerMock->expects($this->once())->method('getStores'); + + $this->localeResolverMock = $this->createMock(\Magento\Framework\Locale\ResolverInterface::class); + $this->localeResolverMock->method('emulate')->with(2); + + $this->model = new \Magento\Webapi\Controller\PathProcessor($this->storeManagerMock, $this->localeResolverMock); } /** @@ -38,15 +50,19 @@ protected function setUp() * * @param string $storeCodeInPath * @param string $storeCodeSet - * @param int $setCurrentStoreCallCtr + * @param int $setCurrentStoreCallCtr */ public function testAllStoreCode($storeCodeInPath, $storeCodeSet, $setCurrentStoreCallCtr = 1) { - $storeCodeInPath = !$storeCodeInPath ?: '/' . $storeCodeInPath; // add leading slash if store code not empty - $inPath = 'rest' . $storeCodeInPath . $this->endpointPath; + $storeCodeInPath = !$storeCodeInPath ? : '/' . $storeCodeInPath; // add leading slash if store code not empty + $inPath = 'rest' . $storeCodeInPath . $this->endpointPath; $this->storeManagerMock->expects($this->exactly($setCurrentStoreCallCtr)) ->method('setCurrentStore') ->with($storeCodeSet); + if($setCurrentStoreCallCtr > 0) { + $this->localeResolverMock->expects($this->once()) + ->method('emulate'); + } $result = $this->model->process($inPath); $this->assertSame($this->endpointPath, $result); } @@ -57,10 +73,10 @@ public function testAllStoreCode($storeCodeInPath, $storeCodeSet, $setCurrentSto public function processPathDataProvider() { return [ - 'All store code' => ['all', Store::ADMIN_CODE], - 'Default store code' => ['', 'default', 0], - 'Arbitrary store code' => [$this->arbitraryStoreCode, $this->arbitraryStoreCode], - 'Explicit default store code' => ['default', 'default'] + 'All store code' => ['all', Store::ADMIN_CODE], + 'Default store code' => ['', 'default', 0], + 'Arbitrary store code' => [$this->arbitraryStoreCode, $this->arbitraryStoreCode], + 'Explicit default store code' => ['default', 'default'], ]; } } diff --git a/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php b/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php index 932ad03d691e4..4b8bfd32b4f70 100644 --- a/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php +++ b/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php @@ -15,6 +15,11 @@ class PathProcessorTest extends \PHPUnit\Framework\TestCase */ protected $storeManager; + /** + * @var \Magento\Framework\Locale\ResolverInterface::class + */ + protected $localeResolver; + /** * @var \Magento\Webapi\Controller\PathProcessor */ @@ -25,6 +30,7 @@ protected function setUp() $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $this->storeManager = $objectManager->get(\Magento\Store\Model\StoreManagerInterface::class); $this->storeManager->reinitStores(); + $this->localeResolver = $objectManager->get(\Magento\Framework\Locale\ResolverInterface::class); $this->pathProcessor = $objectManager->get(\Magento\Webapi\Controller\PathProcessor::class); } @@ -59,4 +65,20 @@ public function testProcessWithoutStoreCode() $this->assertEquals($path, $result); $this->assertEquals('default', $this->storeManager->getStore()->getCode()); } + + /** + * @magentoDataFixture Magento/Store/_files/core_fixturestore.php + * @magentoConfigFixture default_store general/locale/code en_US + * @magentoConfigFixture fixturestore_store general/locale/code de_DE + */ + public function testProcessWithValidStoreCodeApplyLocale() + { + $locale = 'de_DE'; + $storeCode = 'fixturestore'; + $basePath = "rest/{$storeCode}"; + $path = $basePath . '/V1/customerAccounts/createCustomer'; + $this->pathProcessor->process($path); + $this->assertEquals($locale, $this->localeResolver->getLocale()); + $this->assertNotEquals('en_US', $this->localeResolver->getLocale()); + } } From ef724a622b5a45cb8dbeb9ca5f5d5039af4affcf Mon Sep 17 00:00:00 2001 From: Julian Wundrak Date: Sat, 22 Dec 2018 11:36:34 +0100 Subject: [PATCH 011/585] [#19908] add requested code style changes --- app/code/Magento/Webapi/Controller/PathProcessor.php | 7 +++++-- .../Webapi/Test/Unit/Controller/PathProcessorTest.php | 10 +++++----- .../Magento/Webapi/Controller/PathProcessorTest.php | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Webapi/Controller/PathProcessor.php b/app/code/Magento/Webapi/Controller/PathProcessor.php index 20f1f02e38265..b5f0be97de2f2 100644 --- a/app/code/Magento/Webapi/Controller/PathProcessor.php +++ b/app/code/Magento/Webapi/Controller/PathProcessor.php @@ -6,6 +6,7 @@ */ namespace Magento\Webapi\Controller; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; /** @@ -32,10 +33,12 @@ class PathProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\Locale\ResolverInterface $localeResolver + \Magento\Framework\Locale\ResolverInterface $localeResolver = null ) { $this->storeManager = $storeManager; - $this->localeResolver = $localeResolver; + $this->localeResolver = $localeResolver ?: ObjectManager::getInstance()->get( + \Magento\Framework\Locale\ResolverInterface::class + ); } /** diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php index 9a1eb249cd9b7..e53d47d4b7238 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php @@ -54,8 +54,8 @@ protected function setUp() */ public function testAllStoreCode($storeCodeInPath, $storeCodeSet, $setCurrentStoreCallCtr = 1) { - $storeCodeInPath = !$storeCodeInPath ? : '/' . $storeCodeInPath; // add leading slash if store code not empty - $inPath = 'rest' . $storeCodeInPath . $this->endpointPath; + $storeCodeInPath = !$storeCodeInPath ?: '/' . $storeCodeInPath; // add leading slash if store code not empty + $inPath = 'rest' . $storeCodeInPath . $this->endpointPath; $this->storeManagerMock->expects($this->exactly($setCurrentStoreCallCtr)) ->method('setCurrentStore') ->with($storeCodeSet); @@ -73,9 +73,9 @@ public function testAllStoreCode($storeCodeInPath, $storeCodeSet, $setCurrentSto public function processPathDataProvider() { return [ - 'All store code' => ['all', Store::ADMIN_CODE], - 'Default store code' => ['', 'default', 0], - 'Arbitrary store code' => [$this->arbitraryStoreCode, $this->arbitraryStoreCode], + 'All store code' => ['all', Store::ADMIN_CODE], + 'Default store code' => ['', 'default', 0], + 'Arbitrary store code' => [$this->arbitraryStoreCode, $this->arbitraryStoreCode], 'Explicit default store code' => ['default', 'default'], ]; } diff --git a/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php b/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php index 4b8bfd32b4f70..43aa788dea3a8 100644 --- a/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php +++ b/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php @@ -18,7 +18,7 @@ class PathProcessorTest extends \PHPUnit\Framework\TestCase /** * @var \Magento\Framework\Locale\ResolverInterface::class */ - protected $localeResolver; + private $localeResolver; /** * @var \Magento\Webapi\Controller\PathProcessor From 29b4b3920d413c2571ef2d8fd2fb1dba55f63d43 Mon Sep 17 00:00:00 2001 From: Julian Wundrak Date: Thu, 27 Dec 2018 10:12:18 +0100 Subject: [PATCH 012/585] [#19908] Fix WebapiAyncTest --- .../Unit/Controller/PathProcessorTest.php | 2 +- .../Unit/Controller/PathProcessorTest.php | 29 ++++++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php index e53d47d4b7238..513e0cbafcbbd 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php @@ -50,7 +50,7 @@ protected function setUp() * * @param string $storeCodeInPath * @param string $storeCodeSet - * @param int $setCurrentStoreCallCtr + * @param int $setCurrentStoreCallCtr */ public function testAllStoreCode($storeCodeInPath, $storeCodeSet, $setCurrentStoreCallCtr = 1) { diff --git a/app/code/Magento/WebapiAsync/Test/Unit/Controller/PathProcessorTest.php b/app/code/Magento/WebapiAsync/Test/Unit/Controller/PathProcessorTest.php index e5453f7574540..cea7a4168ea4e 100644 --- a/app/code/Magento/WebapiAsync/Test/Unit/Controller/PathProcessorTest.php +++ b/app/code/Magento/WebapiAsync/Test/Unit/Controller/PathProcessorTest.php @@ -15,6 +15,9 @@ class PathProcessorTest extends \PHPUnit\Framework\TestCase /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\StoreManagerInterface */ private $storeManagerMock; + /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Locale\ResolverInterface */ + private $localeResolverMock; + /** @var \Magento\Webapi\Controller\PathProcessor */ private $model; @@ -26,16 +29,22 @@ class PathProcessorTest extends \PHPUnit\Framework\TestCase protected function setUp() { - $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->storeManagerMock->expects($this->once()) - ->method('getStores') - ->willReturn([ - $this->arbitraryStoreCode => 'store object', - 'default' => 'default store object', - ]); - $this->model = new \Magento\Webapi\Controller\PathProcessor($this->storeManagerMock); + $store = $this->createMock(\Magento\Store\Api\Data\StoreInterface::class); + $store->method('getId')->willReturn(2); + + $this->storeManagerMock = $this->createConfiguredMock( + \Magento\Store\Model\StoreManagerInterface::class, + [ + 'getStores' => [$this->arbitraryStoreCode => 'store object', 'default' => 'default store object'], + 'getStore' => $store, + ] + ); + $this->storeManagerMock->expects($this->once())->method('getStores'); + + $this->localeResolverMock = $this->createMock(\Magento\Framework\Locale\ResolverInterface::class); + $this->localeResolverMock->method('emulate')->with(2); + + $this->model = new \Magento\Webapi\Controller\PathProcessor($this->storeManagerMock, $this->localeResolverMock); } /** From 11af87753f43c38d95c373a046ed9490cc2f88e3 Mon Sep 17 00:00:00 2001 From: Arvinda kumar Date: Wed, 9 Jan 2019 15:47:57 +0530 Subject: [PATCH 013/585] issue fixed #20124 Sort By label is hidden by Shop By Menu on listing page in iphone5 device issue fixed #20124 Sort By label is hidden by Shop By Menu on listing page in iphone5 device --- .../luma/Magento_Catalog/web/css/source/module/_toolbar.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_toolbar.less b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_toolbar.less index 6bddc46003cbf..b587c169f67eb 100644 --- a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_toolbar.less +++ b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_toolbar.less @@ -84,7 +84,7 @@ .page-products & { position: absolute; - right: @indent__s; + right: 0; top: 0; z-index: 1; } From 3bcf0d8cbf0330f3a65b25f74f0193961607ebe4 Mon Sep 17 00:00:00 2001 From: James Dinsdale Date: Thu, 10 Jan 2019 13:36:44 +0000 Subject: [PATCH 014/585] Fix issues inserting Widgets with nested WYSIWYGs This PR is a potential fix for issues #19742 and #13409 (Thanks to @EduardTd for pointing me in the right direction). I've tested this briefly in my own install and it appears to resolve the issue. Submitting this PR so that the issue can be tested fully. --- lib/web/mage/adminhtml/wysiwyg/widget.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/web/mage/adminhtml/wysiwyg/widget.js b/lib/web/mage/adminhtml/wysiwyg/widget.js index 68206fdec6201..ea85185954d18 100644 --- a/lib/web/mage/adminhtml/wysiwyg/widget.js +++ b/lib/web/mage/adminhtml/wysiwyg/widget.js @@ -456,7 +456,7 @@ define([ parameters: params, onComplete: function (transport) { try { - editor = wysiwyg.activeEditor(); + editor = tinyMCE.get(this.widgetTargetId); widgetTools.onAjaxSuccess(transport); widgetTools.dialogWindow.modal('closeModal'); @@ -469,7 +469,7 @@ define([ editor.selection.select(activeNode); editor.selection.setContent(transport.responseText); } else if (this.bMark) { - wysiwyg.activeEditor().selection.moveToBookmark(this.bMark); + editor.selection.moveToBookmark(this.bMark); } } @@ -513,7 +513,7 @@ define([ * @return {null|wysiwyg.Editor|*} */ getWysiwyg: function () { - return wysiwyg.activeEditor(); + return tinyMCE.get(this.widgetTargetId); }, /** From 334d71368b2d7ad8b060051b7009c730825f9c4f Mon Sep 17 00:00:00 2001 From: Khodu Vaishnav Date: Sat, 8 Dec 2018 16:50:22 +0530 Subject: [PATCH 015/585] patch-9155 : set default qty for add to cart from wishlist. patch-9155 : set default qty for add to cart from wishlist. patch-9155 : set default qty for add to cart in wishlist. --- .../Customer/Wishlist/Item/Column/Cart.php | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php b/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php index fe0683a52fe97..3e0a611b2e7c7 100644 --- a/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php +++ b/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php @@ -16,6 +16,28 @@ */ class Cart extends \Magento\Wishlist\Block\Customer\Wishlist\Item\Column { + /** + * @var \Magento\Catalog\Block\Product\View + */ + protected $productView; + + /** + * + * @param \Magento\Catalog\Block\Product\Context $context + * @param \Magento\Framework\App\Http\Context $httpContext + * @param array $data + * @param \Magento\Catalog\Block\Product\View $productView + */ + public function __construct( + \Magento\Catalog\Block\Product\Context $context, + \Magento\Framework\App\Http\Context $httpContext, + \Magento\Catalog\Block\Product\View $productView = null, + array $data = [] + ) { + $this->productView = $productView ?: + \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Catalog\Block\Product\View::class); + parent::__construct($context, $httpContext, $data); + } /** * Returns qty to show visually to user * @@ -25,6 +47,8 @@ class Cart extends \Magento\Wishlist\Block\Customer\Wishlist\Item\Column public function getAddToCartQty(\Magento\Wishlist\Model\Item $item) { $qty = $item->getQty(); + $qty = $qty < $this->productView->getProductDefaultQty($this->getProductItem()) + ? $this->productView->getProductDefaultQty($this->getProductItem()) : $qty ; return $qty ? $qty : 1; } From b60600303cae70b32a36d6a830451a461bff5389 Mon Sep 17 00:00:00 2001 From: "v.sikailo" Date: Tue, 15 Jan 2019 11:24:38 +0200 Subject: [PATCH 016/585] - small phpDocs fixes --- .../Controller/Adminhtml/System/Design/Theme/UploadJs.php | 1 - app/code/Magento/Theme/Model/Design/Backend/File.php | 4 +++- .../Theme/Model/Design/Config/FileUploader/FileProcessor.php | 2 +- app/code/Magento/Theme/Model/ResourceModel/Design.php | 3 +-- app/code/Magento/Theme/Model/Wysiwyg/Storage.php | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php index e87e70e21b9de..ce88315b6225b 100644 --- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php +++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php @@ -16,7 +16,6 @@ class UploadJs extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme * Upload js file * * @return void - * @throws \Magento\Framework\Exception\LocalizedException */ public function execute() { diff --git a/app/code/Magento/Theme/Model/Design/Backend/File.php b/app/code/Magento/Theme/Model/Design/Backend/File.php index b37628e54aa30..14615f16c748d 100644 --- a/app/code/Magento/Theme/Model/Design/Backend/File.php +++ b/app/code/Magento/Theme/Model/Design/Backend/File.php @@ -117,7 +117,9 @@ public function beforeSave() } /** - * @return array + * @return File + * + * @throws LocalizedException */ public function afterLoad() { diff --git a/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php b/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php index ecf5bcbea6dfc..6da7cb74e6741 100644 --- a/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php +++ b/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php @@ -79,8 +79,8 @@ public function __construct( * Save file to temp media directory * * @param string $fileId + * * @return array - * @throws LocalizedException */ public function saveToTmp($fileId) { diff --git a/app/code/Magento/Theme/Model/ResourceModel/Design.php b/app/code/Magento/Theme/Model/ResourceModel/Design.php index c36640b98ef40..6711f4a2117be 100644 --- a/app/code/Magento/Theme/Model/ResourceModel/Design.php +++ b/app/code/Magento/Theme/Model/ResourceModel/Design.php @@ -46,7 +46,7 @@ protected function _construct() * Perform actions before object save * * @param \Magento\Framework\Model\AbstractModel $object - * @return $this + * @return void * @throws \Magento\Framework\Exception\LocalizedException */ public function _beforeSave(\Magento\Framework\Model\AbstractModel $object) @@ -152,7 +152,6 @@ protected function _checkIntersection($storeId, $dateFrom, $dateTo, $currentId) $dateConditions = []; } - $condition = ''; if (!empty($dateConditions)) { $condition = '(' . implode(') OR (', $dateConditions) . ')'; $select->where($condition); diff --git a/app/code/Magento/Theme/Model/Wysiwyg/Storage.php b/app/code/Magento/Theme/Model/Wysiwyg/Storage.php index 2c3350e695a85..f1a4b1ffc8d65 100644 --- a/app/code/Magento/Theme/Model/Wysiwyg/Storage.php +++ b/app/code/Magento/Theme/Model/Wysiwyg/Storage.php @@ -110,7 +110,7 @@ public function __construct( * Upload file * * @param string $targetPath - * @return bool + * @return array * @throws \Magento\Framework\Exception\LocalizedException */ public function uploadFile($targetPath) From 49be8059fc5acafb0750b95d9c9cb40a4fc60862 Mon Sep 17 00:00:00 2001 From: Vlad Veselov Date: Tue, 15 Jan 2019 13:26:37 +0200 Subject: [PATCH 017/585] Update app/code/Magento/Theme/Model/Design/Backend/File.php Co-Authored-By: SikailoISM <44577971+SikailoISM@users.noreply.github.com> --- app/code/Magento/Theme/Model/Design/Backend/File.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Theme/Model/Design/Backend/File.php b/app/code/Magento/Theme/Model/Design/Backend/File.php index 14615f16c748d..8c0b38375617c 100644 --- a/app/code/Magento/Theme/Model/Design/Backend/File.php +++ b/app/code/Magento/Theme/Model/Design/Backend/File.php @@ -117,7 +117,7 @@ public function beforeSave() } /** - * @return File + * @return $this * * @throws LocalizedException */ From 2eccce2ff17c7c061761273406ea828126756170 Mon Sep 17 00:00:00 2001 From: nmalevanec Date: Thu, 17 Jan 2019 17:46:11 +0200 Subject: [PATCH 018/585] 12386: Fix Order Status resets to default Status after Partial Refund. --- .../Magento/Sales/Model/Order/Payment.php | 145 +++++++++++------- app/code/Magento/Sales/Model/RefundOrder.php | 11 +- .../Test/Unit/Model/Order/PaymentTest.php | 2 +- .../Sales/Test/Unit/Model/RefundOrderTest.php | 6 +- .../Sales/Service/V1/RefundOrderTest.php | 67 ++++++++ .../Adminhtml/Order/Creditmemo/SaveTest.php | 106 +++++++++++++ .../order_with_invoice_and_custom_status.php | 23 +++ ...ith_invoice_and_custom_status_rollback.php | 16 ++ 8 files changed, 309 insertions(+), 67 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php index 97040c0a578c8..dcf6d86b44cae 100644 --- a/app/code/Magento/Sales/Model/Order/Payment.php +++ b/app/code/Magento/Sales/Model/Order/Payment.php @@ -264,6 +264,7 @@ public function getParentTransactionId() /** * Returns transaction parent * + * @param string $txnId * @return string * @since 100.1.0 */ @@ -299,6 +300,8 @@ public function canCapture() } /** + * Check refund availability. + * * @return bool */ public function canRefund() @@ -307,6 +310,8 @@ public function canRefund() } /** + * Check partial refund availability for invoice. + * * @return bool */ public function canRefundPartialPerInvoice() @@ -315,6 +320,8 @@ public function canRefundPartialPerInvoice() } /** + * Check partial capture availability. + * * @return bool */ public function canCapturePartial() @@ -324,6 +331,7 @@ public function canCapturePartial() /** * Authorize or authorize and capture payment on gateway, if applicable + * * This method is supposed to be called only when order is placed * * @return $this @@ -538,8 +546,7 @@ public function cancelInvoice($invoice) } /** - * Create new invoice with maximum qty for invoice for each item - * register this invoice and capture + * Create new invoice with maximum qty for invoice for each item register this invoice and capture * * @return Invoice */ @@ -723,10 +730,14 @@ public function refund($creditmemo) $message = $message = $this->prependMessage($message); $message = $this->_appendTransactionToMessage($transaction, $message); $orderState = $this->getOrderStateResolver()->getStateForOrder($this->getOrder()); + $statuses = $this->getOrder()->getConfig()->getStateStatuses($orderState, false); + $status = in_array($this->getOrder()->getStatus(), $statuses, true) + ? $this->getOrder()->getStatus() + : $this->getOrder()->getConfig()->getStateDefaultStatus($orderState); $this->getOrder() ->addStatusHistoryComment( $message, - $this->getOrder()->getConfig()->getStateDefaultStatus($orderState) + $status )->setIsCustomerNotified($creditmemo->getOrder()->getCustomerNoteNotify()); $this->_eventManager->dispatch( 'sales_order_payment_refund', @@ -849,6 +860,7 @@ public function cancelCreditmemo($creditmemo) /** * Order cancellation hook for payment method instance + * * Adds void transaction if needed * * @return $this @@ -884,6 +896,8 @@ public function canReviewPayment() } /** + * Check fetch transaction info availability + * * @return bool */ public function canFetchTransactionInfo() @@ -1191,6 +1205,11 @@ public function addTransaction($type, $salesDocument = null, $failSafe = false) } /** + * Add transaction comments to order. + * + * @param Transaction|null $transaction + * @param string $message + * @return void */ public function addTransactionCommentsToOrder($transaction, $message) { @@ -1227,6 +1246,7 @@ public function importTransactionInfo(Transaction $transactionTo) /** * Totals updater utility method + * * Updates self totals by keys in data array('key' => $delta) * * @param array $data @@ -1261,6 +1281,7 @@ protected function _appendTransactionToMessage($transaction, $message) /** * Prepend a "prepared_message" that may be set to the payment instance before, to the specified message + * * Prepends value to the specified string or to the comment of specified order status history item instance * * @param string|\Magento\Sales\Model\Order\Status\History $messagePrependTo @@ -1303,6 +1324,7 @@ public function formatAmount($amount, $asFloat = false) /** * Format price with currency sign + * * @param float $amount * @return string */ @@ -1313,6 +1335,7 @@ public function formatPrice($amount) /** * Lookup an authorization transaction using parent transaction id, if set + * * @return Transaction|false */ public function getAuthorizationTransaction() @@ -1384,8 +1407,8 @@ public function resetTransactionAdditionalInfo() /** * Prepare credit memo * - * @param $amount - * @param $baseGrandTotal + * @param float $amount + * @param float $baseGrandTotal * @param false|Invoice $invoice * @return mixed */ @@ -1454,6 +1477,8 @@ protected function _getInvoiceForTransactionId($transactionId) } /** + * Get order state resolver instance. + * * @deprecated 100.2.0 * @return OrderStateResolverInterface */ @@ -1992,7 +2017,7 @@ public function getShippingRefunded() } /** - * {@inheritdoc} + * @inheritdoc */ public function setParentId($id) { @@ -2000,7 +2025,7 @@ public function setParentId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseShippingCaptured($baseShippingCaptured) { @@ -2008,7 +2033,7 @@ public function setBaseShippingCaptured($baseShippingCaptured) } /** - * {@inheritdoc} + * @inheritdoc */ public function setShippingCaptured($shippingCaptured) { @@ -2016,7 +2041,7 @@ public function setShippingCaptured($shippingCaptured) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAmountRefunded($amountRefunded) { @@ -2024,7 +2049,7 @@ public function setAmountRefunded($amountRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseAmountPaid($baseAmountPaid) { @@ -2032,7 +2057,7 @@ public function setBaseAmountPaid($baseAmountPaid) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAmountCanceled($amountCanceled) { @@ -2040,7 +2065,7 @@ public function setAmountCanceled($amountCanceled) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseAmountAuthorized($baseAmountAuthorized) { @@ -2048,7 +2073,7 @@ public function setBaseAmountAuthorized($baseAmountAuthorized) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseAmountPaidOnline($baseAmountPaidOnline) { @@ -2056,7 +2081,7 @@ public function setBaseAmountPaidOnline($baseAmountPaidOnline) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseAmountRefundedOnline($baseAmountRefundedOnline) { @@ -2064,7 +2089,7 @@ public function setBaseAmountRefundedOnline($baseAmountRefundedOnline) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseShippingAmount($amount) { @@ -2072,7 +2097,7 @@ public function setBaseShippingAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setShippingAmount($amount) { @@ -2080,7 +2105,7 @@ public function setShippingAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAmountPaid($amountPaid) { @@ -2088,7 +2113,7 @@ public function setAmountPaid($amountPaid) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAmountAuthorized($amountAuthorized) { @@ -2096,7 +2121,7 @@ public function setAmountAuthorized($amountAuthorized) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseAmountOrdered($baseAmountOrdered) { @@ -2104,7 +2129,7 @@ public function setBaseAmountOrdered($baseAmountOrdered) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseShippingRefunded($baseShippingRefunded) { @@ -2112,7 +2137,7 @@ public function setBaseShippingRefunded($baseShippingRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setShippingRefunded($shippingRefunded) { @@ -2120,7 +2145,7 @@ public function setShippingRefunded($shippingRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseAmountRefunded($baseAmountRefunded) { @@ -2128,7 +2153,7 @@ public function setBaseAmountRefunded($baseAmountRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAmountOrdered($amountOrdered) { @@ -2136,7 +2161,7 @@ public function setAmountOrdered($amountOrdered) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseAmountCanceled($baseAmountCanceled) { @@ -2144,7 +2169,7 @@ public function setBaseAmountCanceled($baseAmountCanceled) } /** - * {@inheritdoc} + * @inheritdoc */ public function setQuotePaymentId($id) { @@ -2152,7 +2177,7 @@ public function setQuotePaymentId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAdditionalData($additionalData) { @@ -2160,7 +2185,7 @@ public function setAdditionalData($additionalData) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcExpMonth($ccExpMonth) { @@ -2168,7 +2193,7 @@ public function setCcExpMonth($ccExpMonth) } /** - * {@inheritdoc} + * @inheritdoc * @deprecated 100.1.0 unused */ public function setCcSsStartYear($ccSsStartYear) @@ -2177,7 +2202,7 @@ public function setCcSsStartYear($ccSsStartYear) } /** - * {@inheritdoc} + * @inheritdoc */ public function setEcheckBankName($echeckBankName) { @@ -2185,7 +2210,7 @@ public function setEcheckBankName($echeckBankName) } /** - * {@inheritdoc} + * @inheritdoc */ public function setMethod($method) { @@ -2193,7 +2218,7 @@ public function setMethod($method) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcDebugRequestBody($ccDebugRequestBody) { @@ -2201,7 +2226,7 @@ public function setCcDebugRequestBody($ccDebugRequestBody) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcSecureVerify($ccSecureVerify) { @@ -2209,7 +2234,7 @@ public function setCcSecureVerify($ccSecureVerify) } /** - * {@inheritdoc} + * @inheritdoc */ public function setProtectionEligibility($protectionEligibility) { @@ -2217,7 +2242,7 @@ public function setProtectionEligibility($protectionEligibility) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcApproval($ccApproval) { @@ -2225,7 +2250,7 @@ public function setCcApproval($ccApproval) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcLast4($ccLast4) { @@ -2233,7 +2258,7 @@ public function setCcLast4($ccLast4) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcStatusDescription($description) { @@ -2241,7 +2266,7 @@ public function setCcStatusDescription($description) } /** - * {@inheritdoc} + * @inheritdoc */ public function setEcheckType($echeckType) { @@ -2249,7 +2274,7 @@ public function setEcheckType($echeckType) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcDebugResponseSerialized($ccDebugResponseSerialized) { @@ -2257,7 +2282,7 @@ public function setCcDebugResponseSerialized($ccDebugResponseSerialized) } /** - * {@inheritdoc} + * @inheritdoc * @deprecated 100.1.0 unused */ public function setCcSsStartMonth($ccSsStartMonth) @@ -2266,7 +2291,7 @@ public function setCcSsStartMonth($ccSsStartMonth) } /** - * {@inheritdoc} + * @inheritdoc */ public function setEcheckAccountType($echeckAccountType) { @@ -2274,7 +2299,7 @@ public function setEcheckAccountType($echeckAccountType) } /** - * {@inheritdoc} + * @inheritdoc */ public function setLastTransId($id) { @@ -2282,7 +2307,7 @@ public function setLastTransId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcCidStatus($ccCidStatus) { @@ -2290,7 +2315,7 @@ public function setCcCidStatus($ccCidStatus) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcOwner($ccOwner) { @@ -2298,7 +2323,7 @@ public function setCcOwner($ccOwner) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcType($ccType) { @@ -2306,7 +2331,7 @@ public function setCcType($ccType) } /** - * {@inheritdoc} + * @inheritdoc */ public function setPoNumber($poNumber) { @@ -2314,7 +2339,7 @@ public function setPoNumber($poNumber) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcExpYear($ccExpYear) { @@ -2322,7 +2347,7 @@ public function setCcExpYear($ccExpYear) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcStatus($ccStatus) { @@ -2330,7 +2355,7 @@ public function setCcStatus($ccStatus) } /** - * {@inheritdoc} + * @inheritdoc */ public function setEcheckRoutingNumber($echeckRoutingNumber) { @@ -2338,7 +2363,7 @@ public function setEcheckRoutingNumber($echeckRoutingNumber) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAccountStatus($accountStatus) { @@ -2346,7 +2371,7 @@ public function setAccountStatus($accountStatus) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAnetTransMethod($anetTransMethod) { @@ -2354,7 +2379,7 @@ public function setAnetTransMethod($anetTransMethod) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcDebugResponseBody($ccDebugResponseBody) { @@ -2362,7 +2387,7 @@ public function setCcDebugResponseBody($ccDebugResponseBody) } /** - * {@inheritdoc} + * @inheritdoc * @deprecated 100.1.0 unused */ public function setCcSsIssue($ccSsIssue) @@ -2371,7 +2396,7 @@ public function setCcSsIssue($ccSsIssue) } /** - * {@inheritdoc} + * @inheritdoc */ public function setEcheckAccountName($echeckAccountName) { @@ -2379,7 +2404,7 @@ public function setEcheckAccountName($echeckAccountName) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcAvsStatus($ccAvsStatus) { @@ -2387,7 +2412,7 @@ public function setCcAvsStatus($ccAvsStatus) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcNumberEnc($ccNumberEnc) { @@ -2395,7 +2420,7 @@ public function setCcNumberEnc($ccNumberEnc) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCcTransId($id) { @@ -2403,7 +2428,7 @@ public function setCcTransId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAddressStatus($addressStatus) { @@ -2411,7 +2436,7 @@ public function setAddressStatus($addressStatus) } /** - * {@inheritdoc} + * @inheritdoc * * @return \Magento\Sales\Api\Data\OrderPaymentExtensionInterface|null */ @@ -2421,7 +2446,7 @@ public function getExtensionAttributes() } /** - * {@inheritdoc} + * @inheritdoc * * @param \Magento\Sales\Api\Data\OrderPaymentExtensionInterface $extensionAttributes * @return $this @@ -2505,6 +2530,7 @@ public function getShouldCloseParentTransaction() /** * Set payment parent transaction id and current transaction id if it not set + * * @param Transaction $transaction * @return void */ @@ -2526,6 +2552,7 @@ private function setTransactionIdsForRefund(Transaction $transaction) /** * Collects order invoices totals by provided keys. + * * Returns result as {key: amount}. * * @param Order $order diff --git a/app/code/Magento/Sales/Model/RefundOrder.php b/app/code/Magento/Sales/Model/RefundOrder.php index d79f5ecf857cb..97daab0615736 100644 --- a/app/code/Magento/Sales/Model/RefundOrder.php +++ b/app/code/Magento/Sales/Model/RefundOrder.php @@ -151,10 +151,13 @@ public function execute( $creditmemo->setState(\Magento\Sales\Model\Order\Creditmemo::STATE_REFUNDED); $order->setCustomerNoteNotify($notify); $order = $this->refundAdapter->refund($creditmemo, $order); - $order->setState( - $this->orderStateResolver->getStateForOrder($order, []) - ); - $order->setStatus($this->config->getStateDefaultStatus($order->getState())); + $orderState = $this->orderStateResolver->getStateForOrder($order, []); + $order->setState($orderState); + $statuses = $this->config->getStateStatuses($orderState, false); + $status = in_array($order->getStatus(), $statuses, true) + ? $order->getStatus() + : $this->config->getStateDefaultStatus($orderState); + $order->setStatus($status); $order = $this->orderRepository->save($order); $creditmemo = $this->creditmemoRepository->save($creditmemo); diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php index 30b584b8c4ebf..7798fdd2ce285 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php @@ -1526,7 +1526,7 @@ public function testRefund() $this->orderStateResolver->expects($this->once())->method('getStateForOrder') ->with($this->order) ->willReturn(Order::STATE_CLOSED); - $this->mockGetDefaultStatus(Order::STATE_CLOSED, $status); + $this->mockGetDefaultStatus(Order::STATE_CLOSED, $status, ['first, second']); $this->assertOrderUpdated(Order::STATE_PROCESSING, $status, $message); static::assertSame($this->payment, $this->payment->refund($this->creditMemoMock)); diff --git a/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php index c95b56d81d6f4..5962b11311e7d 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php @@ -245,9 +245,9 @@ public function testOrderCreditmemo($orderId, $notify, $appendComment) ->method('setState') ->with(Order::STATE_CLOSED) ->willReturnSelf(); - $this->orderMock->expects($this->once()) - ->method('getState') - ->willReturn(Order::STATE_CLOSED); + $this->configMock->expects($this->once()) + ->method('getStateStatuses') + ->willReturn(['first, second']); $this->configMock->expects($this->once()) ->method('getStateDefaultStatus') ->with(Order::STATE_CLOSED) diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php index 8e5373ea76576..37fa36f707ad4 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php @@ -201,6 +201,73 @@ public function testFullRequest() } } + /** + * Test order will keep same(custom) status after partial refund, if state has not been changed. + * + * @magentoApiDataFixture Magento/Sales/_files/order_with_invoice_and_custom_status.php + */ + public function testOrderStatusPartialRefund() + { + /** @var \Magento\Sales\Model\Order $existingOrder */ + $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) + ->loadByIncrementId('100000001'); + + $items = $this->getOrderItems($existingOrder); + $items[0]['qty'] -= 1; + $result = $this->_webApiCall( + $this->getServiceData($existingOrder), + [ + 'orderId' => $existingOrder->getEntityId(), + 'items' => $items, + ] + ); + + $this->assertNotEmpty( + $result, + 'Failed asserting that the received response is correct' + ); + + /** @var \Magento\Sales\Model\Order $updatedOrder */ + $updatedOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) + ->loadByIncrementId($existingOrder->getIncrementId()); + + $this->assertSame('custom_processing', $updatedOrder->getStatus()); + $this->assertSame('processing', $updatedOrder->getState()); + } + + /** + * Test order will change custom status after total refund, when state has been changed. + * + * @magentoApiDataFixture Magento/Sales/_files/order_with_invoice_and_custom_status.php + */ + public function testOrderStatusTotalRefund() + { + /** @var \Magento\Sales\Model\Order $existingOrder */ + $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) + ->loadByIncrementId('100000001'); + + $items = $this->getOrderItems($existingOrder); + $result = $this->_webApiCall( + $this->getServiceData($existingOrder), + [ + 'orderId' => $existingOrder->getEntityId(), + 'items' => $items, + ] + ); + + $this->assertNotEmpty( + $result, + 'Failed asserting that the received response is correct' + ); + + /** @var \Magento\Sales\Model\Order $updatedOrder */ + $updatedOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) + ->loadByIncrementId($existingOrder->getIncrementId()); + + $this->assertSame('complete', $updatedOrder->getStatus()); + $this->assertSame('complete', $updatedOrder->getState()); + } + /** * Prepares and returns info for API service. * diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php new file mode 100644 index 0000000000000..905fc541610b4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php @@ -0,0 +1,106 @@ +_objectManager->create(Order::class)->loadByIncrementId('100000001'); + $items = $this->getOrderItems($existingOrder, 1); + $requestParams = [ + 'creditmemo' => [ + 'items' => $items, + 'do_offline' => '1', + 'comment_text' => '', + 'shipping_amount' => '0', + 'adjustment_positive' => '0', + 'adjustment_negative' => '0', + ], + 'order_id' => $existingOrder->getId(), + ]; + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setParams($requestParams); + $this->dispatch('backend/sales/order_creditmemo/save'); + + /** @var Order $updatedOrder */ + $updatedOrder = $this->_objectManager->create(Order::class) + ->loadByIncrementId($existingOrder->getIncrementId()); + + $this->assertSame('custom_processing', $updatedOrder->getStatus()); + $this->assertSame('processing', $updatedOrder->getState()); + } + + /** + * Test order will change custom status after total refund, when state has been changed. + * + * @magentoDataFixture Magento/Sales/_files/order_with_invoice_and_custom_status.php + */ + public function testOrderStatusTotalRefund() + { + /** @var Order $existingOrder */ + $existingOrder = $this->_objectManager->create(Order::class)->loadByIncrementId('100000001'); + $requestParams = [ + 'creditmemo' => [ + 'items' => $this->getOrderItems($existingOrder), + 'do_offline' => '1', + 'comment_text' => '', + 'shipping_amount' => '0', + 'adjustment_positive' => '0', + 'adjustment_negative' => '0', + ], + 'order_id' => $existingOrder->getId(), + ]; + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setParams($requestParams); + $this->dispatch('backend/sales/order_creditmemo/save'); + + /** @var Order $updatedOrder */ + $updatedOrder = $this->_objectManager->create(Order::class) + ->loadByIncrementId($existingOrder->getIncrementId()); + + $this->assertSame('complete', $updatedOrder->getStatus()); + $this->assertSame('complete', $updatedOrder->getState()); + } + + /** + * Gets all items of given Order in proper format. + * + * @param Order $order + * @param int $subQty + * @return array + */ + private function getOrderItems(Order $order, int $subQty = 0) + { + $items = []; + /** @var OrderItemInterface $item */ + foreach ($order->getAllItems() as $item) { + $items[$item->getItemId()] = [ + 'qty' => $item->getQtyOrdered() - $subQty, + ]; + } + + return $items; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php new file mode 100644 index 0000000000000..0ee9e95a56b49 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php @@ -0,0 +1,23 @@ +create(Status::class); +$data = [ + 'status' => 'custom_processing', + 'label' => 'Custom Processing Status', +]; +$orderStatus->setData($data)->setStatus('custom_processing'); +$orderStatus->save(); +$orderStatus->assignState('processing'); + +$order->setStatus('custom_processing'); +$order->save(); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php new file mode 100644 index 0000000000000..af31c7b4f24a4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php @@ -0,0 +1,16 @@ +create(Status::class); +$orderStatus->load('custom_processing', 'status'); +$orderStatus->delete(); From d4e0c28cc3e9016d640f53e5fc27d56c6a1067ab Mon Sep 17 00:00:00 2001 From: James Dinsdale Date: Thu, 17 Jan 2019 15:58:34 +0000 Subject: [PATCH 019/585] Use wysiwygAdapter instead of global tinyMCE variable I realised that tinyMCE is already being required as the wysiwygAdapter, so I've updated the code to point to that dependency instead. Still works. --- lib/web/mage/adminhtml/wysiwyg/widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/web/mage/adminhtml/wysiwyg/widget.js b/lib/web/mage/adminhtml/wysiwyg/widget.js index ea85185954d18..aa38e2e1875f6 100644 --- a/lib/web/mage/adminhtml/wysiwyg/widget.js +++ b/lib/web/mage/adminhtml/wysiwyg/widget.js @@ -456,7 +456,7 @@ define([ parameters: params, onComplete: function (transport) { try { - editor = tinyMCE.get(this.widgetTargetId); + editor = wysiwyg.get(this.widgetTargetId); widgetTools.onAjaxSuccess(transport); widgetTools.dialogWindow.modal('closeModal'); @@ -513,7 +513,7 @@ define([ * @return {null|wysiwyg.Editor|*} */ getWysiwyg: function () { - return tinyMCE.get(this.widgetTargetId); + return wysiwyg.get(this.widgetTargetId); }, /** From 42b81c0d97d5948fb7f0c45970fab33cf2f9af99 Mon Sep 17 00:00:00 2001 From: Arvinda kumar Date: Tue, 29 Jan 2019 18:24:25 +0530 Subject: [PATCH 020/585] _module.less update _module.less update --- .../Magento_LayeredNavigation/web/css/source/_module.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/design/frontend/Magento/luma/Magento_LayeredNavigation/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_LayeredNavigation/web/css/source/_module.less index 48461892fa631..5d752a5e04954 100644 --- a/app/design/frontend/Magento/luma/Magento_LayeredNavigation/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_LayeredNavigation/web/css/source/_module.less @@ -364,10 +364,10 @@ content: ''; display: block; height: 40px; - left: -15px; + left: 0; margin-top: -60px; position: relative; - width: 100px; + width: 75px; z-index: 99; } } From 4c71a227680c0ff48e3f2a02e7567e46de3664d8 Mon Sep 17 00:00:00 2001 From: Pratik Oza Date: Tue, 29 Jan 2019 22:18:33 +0530 Subject: [PATCH 021/585] Fixed inactive admin user token --- app/code/Magento/Integration/Model/AdminTokenService.php | 2 +- .../Integration/Test/Unit/Model/AdminTokenServiceTest.php | 4 ---- .../Controller/Adminhtml/User/InvalidateTokenTest.php | 8 -------- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/app/code/Magento/Integration/Model/AdminTokenService.php b/app/code/Magento/Integration/Model/AdminTokenService.php index 5a030325e9fbd..084d111a93f85 100644 --- a/app/code/Magento/Integration/Model/AdminTokenService.php +++ b/app/code/Magento/Integration/Model/AdminTokenService.php @@ -110,7 +110,7 @@ public function revokeAdminAccessToken($adminId) { $tokenCollection = $this->tokenModelCollectionFactory->create()->addFilterByAdminId($adminId); if ($tokenCollection->getSize() == 0) { - throw new LocalizedException(__('This user has no tokens.')); + return true; } try { foreach ($tokenCollection as $token) { diff --git a/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php index e0b1113e80d8d..ef7cb549cab2b 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php @@ -99,10 +99,6 @@ public function testRevokeAdminAccessToken() $this->assertTrue($this->_tokenService->revokeAdminAccessToken($adminId)); } - /** - * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage This user has no tokens. - */ public function testRevokeAdminAccessTokenWithoutAdminId() { $this->_tokenModelCollectionMock->expects($this->once()) diff --git a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/User/InvalidateTokenTest.php b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/User/InvalidateTokenTest.php index 672cbd7a586ec..937a26fdf0a89 100644 --- a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/User/InvalidateTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/User/InvalidateTokenTest.php @@ -89,10 +89,6 @@ public function testInvalidateTokenNoTokens() // invalidate token $this->getRequest()->setParam('user_id', $adminUserId); $this->dispatch('backend/admin/user/invalidateToken'); - $this->assertSessionMessages( - $this->equalTo(['This user has no tokens.']), - MessageInterface::TYPE_ERROR - ); } public function testInvalidateTokenNoUser() @@ -110,9 +106,5 @@ public function testInvalidateTokenInvalidUser() // invalidate token $this->getRequest()->setParam('user_id', $adminUserId); $this->dispatch('backend/admin/user/invalidateToken'); - $this->assertSessionMessages( - $this->equalTo(['This user has no tokens.']), - MessageInterface::TYPE_ERROR - ); } } From 9dc3a19d2cb37f4d0a4cddbab7334d0c579c45b9 Mon Sep 17 00:00:00 2001 From: Iaroslav Gyryn Date: Thu, 31 Jan 2019 09:42:59 +0200 Subject: [PATCH 022/585] magento/magento2#20481 REST products update category_ids cannot be removed --- .../Catalog/Model/ProductRepository.php | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index d124bf5e42639..217454b2eb729 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -11,6 +11,7 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product\Gallery\MimeTypeExtensionMap; use Magento\Catalog\Model\ResourceModel\Product\Collection; +use Magento\Catalog\Api\CategoryLinkManagementInterface; use Magento\Eav\Model\Entity\Attribute\Exception as AttributeException; use Magento\Framework\Api\Data\ImageContentInterface; use Magento\Framework\Api\Data\ImageContentInterfaceFactory; @@ -161,6 +162,16 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa */ private $readExtensions; + /** + * @var CategoryLinkManagementInterface + */ + private $categoryLinkManagement; + + /** + * @var AssignProductToCategories + */ + private $assignProductToCategories = false; + /** * ProductRepository constructor. * @param ProductFactory $productFactory @@ -187,6 +198,7 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer * @param int $cacheLimit [optional] * @param ReadExtensions|null $readExtensions + * @param Magento\Catalog\Api\CategoryLinkManagementInterface|null $categoryLinkManagement * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ @@ -214,7 +226,8 @@ public function __construct( CollectionProcessorInterface $collectionProcessor = null, \Magento\Framework\Serialize\Serializer\Json $serializer = null, $cacheLimit = 1000, - ReadExtensions $readExtensions = null + ReadExtensions $readExtensions = null, + CategoryLinkManagementInterface $categoryLinkManagement = null ) { $this->productFactory = $productFactory; $this->collectionFactory = $collectionFactory; @@ -239,6 +252,8 @@ public function __construct( $this->cacheLimit = (int)$cacheLimit; $this->readExtensions = $readExtensions ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(ReadExtensions::class); + $this->categoryLinkManagement = $categoryLinkManagement ?:\Magento\Framework\App\ObjectManager::getInstance() + ->get(CategoryLinkManagementInterface::class); } /** @@ -589,6 +604,7 @@ public function save(ProductInterface $product, $saveOptions = false) $extensionAttributes = $product->getExtensionAttributes(); if (empty($extensionAttributes->__toArray())) { $product->setExtensionAttributes($existingProduct->getExtensionAttributes()); + $this->assignProductToCategories = true; } } catch (NoSuchEntityException $e) { $existingProduct = null; @@ -626,6 +642,12 @@ public function save(ProductInterface $product, $saveOptions = false) } $this->saveProduct($product); + if ($this->assignProductToCategories === true) { + $this->categoryLinkManagement->assignProductToCategories( + $product->getSku(), + $product->getCategoryIds() + ); + } $this->removeProductFromLocalCache($product->getSku()); unset($this->instancesById[$product->getId()]); From b6020677c4fd3e99d59c67b953bfa53d70bed165 Mon Sep 17 00:00:00 2001 From: Iaroslav Gyryn Date: Thu, 31 Jan 2019 16:56:44 +0200 Subject: [PATCH 023/585] magento/magento2#20481 REST products update category_ids cannot be removed Code review --- .../Catalog/Model/ProductRepository.php | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index 217454b2eb729..518a17ff3f101 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -165,12 +165,7 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa /** * @var CategoryLinkManagementInterface */ - private $categoryLinkManagement; - - /** - * @var AssignProductToCategories - */ - private $assignProductToCategories = false; + private $linkManagement; /** * ProductRepository constructor. @@ -227,7 +222,7 @@ public function __construct( \Magento\Framework\Serialize\Serializer\Json $serializer = null, $cacheLimit = 1000, ReadExtensions $readExtensions = null, - CategoryLinkManagementInterface $categoryLinkManagement = null + CategoryLinkManagementInterface $linkManagement = null ) { $this->productFactory = $productFactory; $this->collectionFactory = $collectionFactory; @@ -252,7 +247,7 @@ public function __construct( $this->cacheLimit = (int)$cacheLimit; $this->readExtensions = $readExtensions ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(ReadExtensions::class); - $this->categoryLinkManagement = $categoryLinkManagement ?:\Magento\Framework\App\ObjectManager::getInstance() + $this->linkManagement = $linkManagement ?:\Magento\Framework\App\ObjectManager::getInstance() ->get(CategoryLinkManagementInterface::class); } @@ -587,6 +582,7 @@ protected function processMediaGallery(ProductInterface $product, $mediaGalleryE */ public function save(ProductInterface $product, $saveOptions = false) { + $assignToCategories = false; $tierPrices = $product->getData('tier_price'); try { @@ -604,7 +600,7 @@ public function save(ProductInterface $product, $saveOptions = false) $extensionAttributes = $product->getExtensionAttributes(); if (empty($extensionAttributes->__toArray())) { $product->setExtensionAttributes($existingProduct->getExtensionAttributes()); - $this->assignProductToCategories = true; + $assignToCategories = true; } } catch (NoSuchEntityException $e) { $existingProduct = null; @@ -642,8 +638,8 @@ public function save(ProductInterface $product, $saveOptions = false) } $this->saveProduct($product); - if ($this->assignProductToCategories === true) { - $this->categoryLinkManagement->assignProductToCategories( + if ($assignToCategories === true) { + $this->linkManagement->assignProductToCategories( $product->getSku(), $product->getCategoryIds() ); From 73859cd565ddf112ba003953efb523688acdfea2 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Wed, 30 Jan 2019 11:47:02 +0200 Subject: [PATCH 024/585] ENGCOM-3715: Static test fix. --- .../Customer/Wishlist/Item/Column/Cart.php | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php b/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php index 3e0a611b2e7c7..d2871efc1aab9 100644 --- a/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php +++ b/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php @@ -6,7 +6,11 @@ namespace Magento\Wishlist\Block\Customer\Wishlist\Item\Column; +use Magento\Catalog\Block\Product\View; use Magento\Catalog\Controller\Adminhtml\Product\Initialization\StockDataFilter; +use Magento\Catalog\Model\Product\Image\UrlBuilder; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\View\ConfigInterface; /** * Wishlist block customer item cart column @@ -17,27 +21,30 @@ class Cart extends \Magento\Wishlist\Block\Customer\Wishlist\Item\Column { /** - * @var \Magento\Catalog\Block\Product\View + * @var View */ protected $productView; /** - * * @param \Magento\Catalog\Block\Product\Context $context * @param \Magento\Framework\App\Http\Context $httpContext * @param array $data - * @param \Magento\Catalog\Block\Product\View $productView + * @param ConfigInterface|null $config + * @param UrlBuilder|null $urlBuilder + * @param View|null $productView */ public function __construct( \Magento\Catalog\Block\Product\Context $context, \Magento\Framework\App\Http\Context $httpContext, - \Magento\Catalog\Block\Product\View $productView = null, - array $data = [] + array $data = [], + ?ConfigInterface $config = null, + ?UrlBuilder $urlBuilder = null, + ?View $productView = null ) { - $this->productView = $productView ?: - \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Catalog\Block\Product\View::class); - parent::__construct($context, $httpContext, $data); + $this->productView = $productView ?: ObjectManager::getInstance()->get(View::class); + parent::__construct($context, $httpContext, $data, $config, $urlBuilder); } + /** * Returns qty to show visually to user * @@ -48,8 +55,8 @@ public function getAddToCartQty(\Magento\Wishlist\Model\Item $item) { $qty = $item->getQty(); $qty = $qty < $this->productView->getProductDefaultQty($this->getProductItem()) - ? $this->productView->getProductDefaultQty($this->getProductItem()) : $qty ; - return $qty ? $qty : 1; + ? $this->productView->getProductDefaultQty($this->getProductItem()) : $qty; + return $qty ?: 1; } /** From 8af727d6fffc7ffb3a09037e81bb92f6a933896c Mon Sep 17 00:00:00 2001 From: Dominic Date: Mon, 4 Feb 2019 20:05:00 +0530 Subject: [PATCH 025/585] Remove direct server variable use --- app/code/Magento/Store/Model/Store.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index c1ad5bdcfc068..112561d8c1fe4 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -707,7 +707,8 @@ protected function _updatePathUseRewrites($url) if ($this->_isCustomEntryPoint()) { $indexFileName = 'index.php'; } else { - $indexFileName = basename($_SERVER['SCRIPT_FILENAME']); + $scriptFilename = $this->_request->getServer('SCRIPT_FILENAME'); + $indexFileName = basename($scriptFilename); } $url .= $indexFileName . '/'; } From d1b7097bc38e87669607cfac094d312d76ce7ab3 Mon Sep 17 00:00:00 2001 From: Iaroslav Gyryn Date: Thu, 7 Feb 2019 14:00:33 +0200 Subject: [PATCH 026/585] magento/magento2#20481 REST products update category_ids cannot be removed Code review, updated unit tests --- app/code/Magento/Catalog/Model/ProductRepository.php | 4 ++-- .../Test/Unit/Model/ProductRepositoryTest.php | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index 518a17ff3f101..d78d1ca2f216f 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -193,7 +193,7 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer * @param int $cacheLimit [optional] * @param ReadExtensions|null $readExtensions - * @param Magento\Catalog\Api\CategoryLinkManagementInterface|null $categoryLinkManagement + * @param Magento\Catalog\Api\CategoryLinkManagementInterface|null $linkManagement * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ @@ -638,7 +638,7 @@ public function save(ProductInterface $product, $saveOptions = false) } $this->saveProduct($product); - if ($assignToCategories === true) { + if ($assignToCategories === true && $product->getCategoryIds()) { $this->linkManagement->assignProductToCategories( $product->getSku(), $product->getCategoryIds() diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php index c729a0c58e1ec..6d3b4713b830d 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php @@ -200,7 +200,8 @@ protected function setUp() 'setData', 'getStoreId', 'getMediaGalleryEntries', - 'getExtensionAttributes' + 'getExtensionAttributes', + 'getCategoryIds' ] ); @@ -220,7 +221,8 @@ protected function setUp() 'validate', 'save', 'getMediaGalleryEntries', - 'getExtensionAttributes' + 'getExtensionAttributes', + 'getCategoryIds' ] ); $this->initializedProduct->expects($this->any()) @@ -269,6 +271,12 @@ protected function setUp() $this->initializedProduct ->method('getExtensionAttributes') ->willReturn($this->productExtension); + $this->product + ->method('getCategoryIds') + ->willReturn([1, 2, 3, 4]); + $this->initializedProduct + ->method('getCategoryIds') + ->willReturn([1, 2, 3, 4]); $storeMock = $this->getMockBuilder(StoreInterface::class) ->disableOriginalConstructor() ->setMethods([]) From 814947905ba35e2bbaca4f4124d1e0ac19225ce5 Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun Date: Thu, 7 Feb 2019 21:25:07 +0200 Subject: [PATCH 027/585] Minor code style fixes --- app/code/Magento/Catalog/Model/ProductRepository.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index d78d1ca2f216f..57584b116a3a4 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -7,11 +7,11 @@ namespace Magento\Catalog\Model; +use Magento\Catalog\Api\CategoryLinkManagementInterface; use Magento\Catalog\Api\Data\ProductExtension; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product\Gallery\MimeTypeExtensionMap; use Magento\Catalog\Model\ResourceModel\Product\Collection; -use Magento\Catalog\Api\CategoryLinkManagementInterface; use Magento\Eav\Model\Entity\Attribute\Exception as AttributeException; use Magento\Framework\Api\Data\ImageContentInterface; use Magento\Framework\Api\Data\ImageContentInterfaceFactory; @@ -247,7 +247,7 @@ public function __construct( $this->cacheLimit = (int)$cacheLimit; $this->readExtensions = $readExtensions ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(ReadExtensions::class); - $this->linkManagement = $linkManagement ?:\Magento\Framework\App\ObjectManager::getInstance() + $this->linkManagement = $linkManagement ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(CategoryLinkManagementInterface::class); } From 448e7e9d3f7d0ad386b8d653643d36be2735d282 Mon Sep 17 00:00:00 2001 From: Mikalai Shostka Date: Wed, 20 Feb 2019 18:59:43 +0300 Subject: [PATCH 028/585] MAGETWO-64260: [Optimize] Performance for grouped products with large # of options - Optimize list options; --- .../Model/Product/Type/Grouped.php | 2 +- .../Product/Form/Modifier/GroupedTest.php | 87 +++++++++++++++++-- .../Product/Form/Modifier/Grouped.php | 48 +++++++--- .../web/js/dynamic-rows/dynamic-rows-grid.js | 9 ++ 4 files changed, 125 insertions(+), 21 deletions(-) diff --git a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php index f67c9c57ee034..c362474e3cf68 100644 --- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php @@ -210,7 +210,7 @@ public function getAssociatedProducts($product) $collection = $this->getAssociatedProductCollection( $product )->addAttributeToSelect( - ['name', 'price', 'special_price', 'special_from_date', 'special_to_date', 'tax_class_id'] + ['name', 'price', 'special_price', 'special_from_date', 'special_to_date', 'tax_class_id', 'image'] )->addFilterByRequiredOptions()->setPositionOrder()->addStoreFilter( $this->getStoreFilter($product) )->addAttributeToFilter( diff --git a/app/code/Magento/GroupedProduct/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GroupedTest.php b/app/code/Magento/GroupedProduct/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GroupedTest.php index 327b47d4a75d8..ad4b86351a66c 100644 --- a/app/code/Magento/GroupedProduct/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GroupedTest.php +++ b/app/code/Magento/GroupedProduct/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GroupedTest.php @@ -21,6 +21,9 @@ use Magento\GroupedProduct\Model\Product\Type\Grouped as GroupedProductType; use Magento\GroupedProduct\Ui\DataProvider\Product\Form\Modifier\Grouped; use Magento\Store\Api\Data\StoreInterface; +use Magento\Catalog\Model\Product; +use Magento\GroupedProduct\Model\Product\Link\CollectionProvider\Grouped as GroupedProducts; +use Magento\Catalog\Api\Data\ProductLinkInterfaceFactory; /** * Class GroupedTest @@ -82,23 +85,38 @@ class GroupedTest extends AbstractModifierTest */ protected $storeMock; + /** + * @var GroupedProducts|\PHPUnit_Framework_MockObject_MockObject + */ + private $groupedProductsMock; + + /** + * @var ProductLinkInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $productLinkFactoryMock; + + /** + * @inheritdoc + */ protected function setUp() { $this->objectManager = new ObjectManager($this); $this->locatorMock = $this->getMockBuilder(LocatorInterface::class) ->getMockForAbstractClass(); - $this->productMock = $this->getMockBuilder(ProductInterface::class) + $this->productMock = $this->getMockBuilder(Product::class) ->setMethods(['getId', 'getTypeId']) - ->getMockForAbstractClass(); + ->disableOriginalConstructor() + ->getMock(); $this->productMock->expects($this->any()) ->method('getId') ->willReturn(self::PRODUCT_ID); $this->productMock->expects($this->any()) ->method('getTypeId') ->willReturn(GroupedProductType::TYPE_CODE); - $this->linkedProductMock = $this->getMockBuilder(ProductInterface::class) + $this->linkedProductMock = $this->getMockBuilder(Product::class) ->setMethods(['getId', 'getName', 'getPrice']) - ->getMockForAbstractClass(); + ->disableOriginalConstructor() + ->getMock(); $this->linkedProductMock->expects($this->any()) ->method('getId') ->willReturn(self::LINKED_PRODUCT_ID); @@ -135,7 +153,7 @@ protected function setUp() $this->linkRepositoryMock->expects($this->any()) ->method('getList') ->with($this->productMock) - ->willReturn([$this->linkMock]); + ->willReturn([$this->linkedProductMock]); $this->productRepositoryMock = $this->getMockBuilder(ProductRepositoryInterface::class) ->setMethods(['get']) ->getMockForAbstractClass(); @@ -155,7 +173,7 @@ protected function setUp() } /** - * {@inheritdoc} + * @inheritdoc */ protected function createModel() { @@ -169,6 +187,16 @@ protected function createModel() ->setMethods(['init', 'getUrl']) ->disableOriginalConstructor() ->getMock(); + + $this->groupedProductsMock = $this->getMockBuilder(GroupedProducts::class) + ->setMethods(['getLinkedProducts']) + ->disableOriginalConstructor() + ->getMock(); + $this->productLinkFactoryMock = $this->getMockBuilder(ProductLinkInterfaceFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->imageHelperMock->expects($this->any()) ->method('init') ->willReturn($this->imageHelperMock); @@ -189,16 +217,23 @@ protected function createModel() 'localeCurrency' => $this->currencyMock, 'imageHelper' => $this->imageHelperMock, 'attributeSetRepository' => $this->attributeSetRepositoryMock, + 'groupedProducts' => $this->groupedProductsMock, + 'productLinkFactory' => $this->productLinkFactoryMock, ]); } + /** + * Assert array has key + * + * @return void + */ public function testModifyMeta() { $this->assertArrayHasKey(Grouped::GROUP_GROUPED, $this->getModel()->modifyMeta([])); } /** - * {@inheritdoc} + * @inheritdoc */ public function testModifyData() { @@ -226,6 +261,42 @@ public function testModifyData() ], ], ]; - $this->assertSame($expectedData, $this->getModel()->modifyData([])); + $model = $this->getModel(); + $linkedProductMock = $this->getMockBuilder(Product::class) + ->setMethods(['getId', 'getName', 'getPrice', 'getSku', 'getImage', 'getPosition', 'getQty']) + ->disableOriginalConstructor() + ->getMock(); + $linkedProductMock->expects($this->once()) + ->method('getId') + ->willReturn(self::LINKED_PRODUCT_ID); + $linkedProductMock->expects($this->once()) + ->method('getName') + ->willReturn(self::LINKED_PRODUCT_NAME); + $linkedProductMock->expects($this->once()) + ->method('getPrice') + ->willReturn(self::LINKED_PRODUCT_PRICE); + $linkedProductMock->expects($this->once()) + ->method('getSku') + ->willReturn(self::LINKED_PRODUCT_SKU); + $linkedProductMock->expects($this->once()) + ->method('getImage') + ->willReturn(''); + $linkedProductMock->expects($this->exactly(2)) + ->method('getPosition') + ->willReturn(self::LINKED_PRODUCT_POSITION); + $linkedProductMock->expects($this->once()) + ->method('getQty') + ->willReturn(self::LINKED_PRODUCT_QTY); + $this->groupedProductsMock->expects($this->once()) + ->method('getLinkedProducts') + ->willReturn([$linkedProductMock]); + $linkMock = $this->getMockBuilder(ProductLinkInterface::class) + ->getMockForAbstractClass(); + + $this->productLinkFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($linkMock); + + $this->assertSame($expectedData, $model->modifyData([])); } } diff --git a/app/code/Magento/GroupedProduct/Ui/DataProvider/Product/Form/Modifier/Grouped.php b/app/code/Magento/GroupedProduct/Ui/DataProvider/Product/Form/Modifier/Grouped.php index 57d9bc78aaf28..19f11df406ff8 100644 --- a/app/code/Magento/GroupedProduct/Ui/DataProvider/Product/Form/Modifier/Grouped.php +++ b/app/code/Magento/GroupedProduct/Ui/DataProvider/Product/Form/Modifier/Grouped.php @@ -21,6 +21,9 @@ use Magento\Eav\Api\AttributeSetRepositoryInterface; use Magento\Catalog\Model\Product\Attribute\Source\Status; use Magento\Framework\Locale\CurrencyInterface; +use Magento\GroupedProduct\Model\Product\Link\CollectionProvider\Grouped as GroupedProducts; +use Magento\Framework\App\ObjectManager; +use Magento\Catalog\Api\Data\ProductLinkInterfaceFactory; /** * Data provider for Grouped products @@ -99,6 +102,16 @@ class Grouped extends AbstractModifier */ private static $codeQty = 'qty'; + /** + * @var GroupedProducts + */ + private $groupedProducts; + + /** + * @var ProductLinkInterfaceFactory + */ + private $productLinkFactory; + /** * @param LocatorInterface $locator * @param UrlInterface $urlBuilder @@ -109,6 +122,9 @@ class Grouped extends AbstractModifier * @param AttributeSetRepositoryInterface $attributeSetRepository * @param CurrencyInterface $localeCurrency * @param array $uiComponentsConfig + * @param GroupedProducts $groupedProducts + * @param \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory|null $productLinkFactory + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( LocatorInterface $locator, @@ -119,7 +135,9 @@ public function __construct( Status $status, AttributeSetRepositoryInterface $attributeSetRepository, CurrencyInterface $localeCurrency, - array $uiComponentsConfig = [] + array $uiComponentsConfig = [], + GroupedProducts $groupedProducts = null, + \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory $productLinkFactory = null ) { $this->locator = $locator; $this->urlBuilder = $urlBuilder; @@ -130,6 +148,11 @@ public function __construct( $this->status = $status; $this->localeCurrency = $localeCurrency; $this->uiComponentsConfig = array_replace_recursive($this->uiComponentsConfig, $uiComponentsConfig); + $this->groupedProducts = $groupedProducts ?: ObjectManager::getInstance()->get( + \Magento\GroupedProduct\Model\Product\Link\CollectionProvider\Grouped::class + ); + $this->productLinkFactory = $productLinkFactory ?: ObjectManager::getInstance() + ->get(\Magento\Catalog\Api\Data\ProductLinkInterfaceFactory::class); } /** @@ -143,18 +166,15 @@ public function modifyData(array $data) if ($modelId) { $storeId = $this->locator->getStore()->getId(); $data[$product->getId()]['links'][self::LINK_TYPE] = []; - $linkedItems = $this->productLinkRepository->getList($product); + $linkedItems = $this->groupedProducts->getLinkedProducts($product); usort($linkedItems, function ($a, $b) { return $a->getPosition() <=> $b->getPosition(); }); + $productLink = $this->productLinkFactory->create(); foreach ($linkedItems as $index => $linkItem) { - if ($linkItem->getLinkType() !== self::LINK_TYPE) { - continue; - } /** @var \Magento\Catalog\Api\Data\ProductInterface $linkedProduct */ - $linkedProduct = $this->productRepository->get($linkItem->getLinkedProductSku(), false, $storeId); $linkItem->setPosition($index); - $data[$modelId]['links'][self::LINK_TYPE][] = $this->fillData($linkedProduct, $linkItem); + $data[$modelId]['links'][self::LINK_TYPE][] = $this->fillData($linkItem, $productLink); } $data[$modelId][self::DATA_SOURCE_DEFAULT]['current_store_id'] = $storeId; } @@ -167,6 +187,7 @@ public function modifyData(array $data) * @param ProductInterface $linkedProduct * @param ProductLinkInterface $linkItem * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function fillData(ProductInterface $linkedProduct, ProductLinkInterface $linkItem) { @@ -176,12 +197,15 @@ protected function fillData(ProductInterface $linkedProduct, ProductLinkInterfac return [ 'id' => $linkedProduct->getId(), 'name' => $linkedProduct->getName(), - 'sku' => $linkItem->getLinkedProductSku(), + 'sku' => $linkedProduct->getSku(), 'price' => $currency->toCurrency(sprintf("%f", $linkedProduct->getPrice())), - 'qty' => $linkItem->getExtensionAttributes()->getQty(), - 'position' => $linkItem->getPosition(), - 'positionCalculated' => $linkItem->getPosition(), - 'thumbnail' => $this->imageHelper->init($linkedProduct, 'product_listing_thumbnail')->getUrl(), + 'qty' => $linkedProduct->getQty(), + 'position' => $linkedProduct->getPosition(), + 'positionCalculated' => $linkedProduct->getPosition(), + 'thumbnail' => $this->imageHelper + ->init($linkedProduct, 'product_listing_thumbnail') + ->setImageFile($linkedProduct->getImage()) + ->getUrl(), 'type_id' => $linkedProduct->getTypeId(), 'status' => $this->status->getOptionText($linkedProduct->getStatus()), 'attribute_set' => $this->attributeSetRepository diff --git a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js index dc6f8d930a144..17b2d1db4eb1b 100644 --- a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js +++ b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js @@ -33,6 +33,15 @@ define([ } }, + /** + * @inheritdoc + */ + initialize: function () { + this.setToInsertData = _.debounce(this.setToInsertData, 200); + + return this._super(); + }, + /** * Calls 'initObservable' of parent * From 46191d82d04e2392cb58a2c03121987a14052043 Mon Sep 17 00:00:00 2001 From: Matti Vapa Date: Thu, 21 Feb 2019 08:56:26 +0200 Subject: [PATCH 029/585] Fix for issue #21299. Changed the built-in cache to not cache 404 responses to HEAD requests. --- .../Framework/App/PageCache/Kernel.php | 22 ++++++++++++++++--- .../App/Test/Unit/PageCache/KernelTest.php | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/App/PageCache/Kernel.php b/lib/internal/Magento/Framework/App/PageCache/Kernel.php index 13e18ed28fd67..bb24c84d03e57 100644 --- a/lib/internal/Magento/Framework/App/PageCache/Kernel.php +++ b/lib/internal/Magento/Framework/App/PageCache/Kernel.php @@ -137,9 +137,7 @@ public function process(\Magento\Framework\App\Response\Http $response) if (preg_match('/public.*s-maxage=(\d+)/', $response->getHeader('Cache-Control')->getFieldValue(), $matches)) { $maxAge = $matches[1]; $response->setNoCacheHeaders(); - if (($response->getHttpResponseCode() == 200 || $response->getHttpResponseCode() == 404) - && ($this->request->isGet() || $this->request->isHead()) - ) { + if ($this->shouldCacheResponse($response)) { $tagsHeader = $response->getHeader('X-Magento-Tags'); $tags = $tagsHeader ? explode(',', $tagsHeader->getFieldValue()) : []; @@ -218,4 +216,22 @@ private function getCache() } return $this->fullPageCache; } + + /** + * Check if the response should be cached. For GET requests both 200 and 404 responses should be + * cached. For HEAD requests only 200 responses should be cached. + * + * @param \Magento\Framework\App\Response\Http $response + * @return bool + */ + private function shouldCacheResponse(\Magento\Framework\App\Response\Http $response) + { + $responseCode = $response->getHttpResponseCode(); + if ($this->request->isGet()) { + return $responseCode == 200 || $responseCode == 404; + } elseif ($this->request->isHead()) { + return $responseCode == 200; + } + return false; + } } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/PageCache/KernelTest.php b/lib/internal/Magento/Framework/App/Test/Unit/PageCache/KernelTest.php index db200f962f5b5..74201a15d695d 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/PageCache/KernelTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/PageCache/KernelTest.php @@ -248,7 +248,7 @@ public function testProcessSaveCacheDataProvider() { return [ [200, [3, 4, 5]], - [404, [4, 5, 6]] + [404, [3, 4, 5]] ]; } From 0510379aa8668ae6b52e1c46f8acd9b17e291c18 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Tue, 26 Feb 2019 13:17:41 -0600 Subject: [PATCH 030/585] MC-15033: Configurable product gallery does not prepend images with multiple attributes - add functional test --- .../Catalog/Test/Mftf/Data/ProductData.xml | 9 ++++ .../AdminAddDefaultImageSimpleProductTest.xml | 4 +- .../AdminConfigurableProductActionGroup.xml | 16 +++++++ ...reateProductConfigurationsPanelSection.xml | 6 +++ .../StorefrontProductInfoMainSection.xml | 2 +- .../StorefrontFilterByImageSwatchTest.xml | 43 +++++++++++++++++-- 6 files changed, 74 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index d136661e917cb..10f70a7094fbe 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -222,6 +222,15 @@ magento-again jpg + + magento-adobe + 1.00 + Upload File + Yes + adobe-base.jpg + adobe-base + jpg + 霁产品 simple diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddDefaultImageSimpleProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddDefaultImageSimpleProductTest.xml index 88a39a9087bb3..117f094ee0607 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddDefaultImageSimpleProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddDefaultImageSimpleProductTest.xml @@ -43,7 +43,9 @@ - + + + diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml index d2abfc7977519..503a8ffd4e1d8 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml @@ -131,6 +131,22 @@ + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminCreateProductConfigurationsPanelSection.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminCreateProductConfigurationsPanelSection.xml index 9b4798c95ec72..242eb3b4ca79c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminCreateProductConfigurationsPanelSection.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminCreateProductConfigurationsPanelSection.xml @@ -26,6 +26,12 @@ + + + + + + diff --git a/app/code/Magento/Swatches/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/Swatches/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index e40a04080285a..4290ddbbd8dd4 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -9,7 +9,7 @@
- + diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByImageSwatchTest.xml index e4c96ab3a2ba7..5347a1a1f870f 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByImageSwatchTest.xml @@ -79,16 +79,25 @@ - + + + + + + + + + - + - + + @@ -111,7 +120,33 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3a772bc0fba518ab0328cd6a881955ac719aef16 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Tue, 26 Feb 2019 13:36:53 -0600 Subject: [PATCH 031/585] MC-15033: Configurable product gallery does not prepend images with multiple attributes - add after clicks --- .../Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml index 503a8ffd4e1d8..c7af58212b5f5 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml @@ -143,8 +143,8 @@ - - + + From ce441c69dd37859fc4ddbd400ab7209ac021b6f2 Mon Sep 17 00:00:00 2001 From: Danny Verkade Date: Wed, 27 Feb 2019 20:04:26 +0100 Subject: [PATCH 032/585] Fix for issue #21477 sets CURRENT_TIMESTAMP and updated_at fields in the DB Schema. --- app/code/Magento/Integration/etc/db_schema.xml | 2 +- app/code/Magento/Quote/etc/db_schema.xml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Integration/etc/db_schema.xml b/app/code/Magento/Integration/etc/db_schema.xml index f1824fadb97fd..cbf43d79b2cf6 100644 --- a/app/code/Magento/Integration/etc/db_schema.xml +++ b/app/code/Magento/Integration/etc/db_schema.xml @@ -107,7 +107,7 @@ comment="Oauth consumer"/> - diff --git a/app/code/Magento/Quote/etc/db_schema.xml b/app/code/Magento/Quote/etc/db_schema.xml index 6f9f81ba6b3fa..82d468547c479 100644 --- a/app/code/Magento/Quote/etc/db_schema.xml +++ b/app/code/Magento/Quote/etc/db_schema.xml @@ -108,7 +108,7 @@ default="0" comment="Quote Id"/> - @@ -218,7 +218,7 @@ default="0" comment="Quote Id"/> - @@ -322,7 +322,7 @@ default="0" comment="Quote Item Id"/> - @@ -434,7 +434,7 @@ default="0" comment="Quote Id"/> - @@ -470,7 +470,7 @@ default="0" comment="Address Id"/> - From b57dab0c754144cb94584523747bf2b40148d4c0 Mon Sep 17 00:00:00 2001 From: David Alger Date: Fri, 1 Mar 2019 15:43:20 -0600 Subject: [PATCH 033/585] Fixed curl adapter to properly set http version as passed in arguments to prevent failure when requesting from http2 capable endpoint --- lib/internal/Magento/Framework/HTTP/Adapter/Curl.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php index bc833bf3bb2d4..96af9be49f340 100644 --- a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php +++ b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php @@ -183,6 +183,12 @@ public function write($method, $url, $http_ver = '1.1', $headers = [], $body = ' curl_setopt($this->_getResource(), CURLOPT_CUSTOMREQUEST, 'GET'); } + if ($http_ver === \Zend_Http_Client::HTTP_1) { + curl_setopt($this->_getResource(), CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + } elseif ($http_ver === \Zend_Http_Client::HTTP_0) { + curl_setopt($this->_getResource(), CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + } + if (is_array($headers)) { curl_setopt($this->_getResource(), CURLOPT_HTTPHEADER, $headers); } From d8eb1608e5a5377bdf2fb723413402220c7b9965 Mon Sep 17 00:00:00 2001 From: Matti Vapa Date: Tue, 5 Mar 2019 17:55:29 +0200 Subject: [PATCH 034/585] Fix for issue #21299. HEAD requests map to GET request interface and are sent without body attached. --- app/etc/di.xml | 2 +- .../App/Action/HttpHeadActionInterface.php | 2 + lib/internal/Magento/Framework/App/Http.php | 14 ++++++ .../Framework/App/Test/Unit/HttpTest.php | 31 ++++++++++++- .../Test/Unit/Transfer/Adapter/HttpTest.php | 45 ++++++++++++++++++- .../Framework/File/Transfer/Adapter/Http.php | 13 ++++++ 6 files changed, 104 insertions(+), 3 deletions(-) diff --git a/app/etc/di.xml b/app/etc/di.xml index 19543375aad58..66843198a09e0 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -1739,7 +1739,7 @@ \Magento\Framework\App\Action\HttpOptionsActionInterface \Magento\Framework\App\Action\HttpGetActionInterface - \Magento\Framework\App\Action\HttpHeadActionInterface + \Magento\Framework\App\Action\HttpGetActionInterface \Magento\Framework\App\Action\HttpPostActionInterface \Magento\Framework\App\Action\HttpPutActionInterface \Magento\Framework\App\Action\HttpPatchActionInterface diff --git a/lib/internal/Magento/Framework/App/Action/HttpHeadActionInterface.php b/lib/internal/Magento/Framework/App/Action/HttpHeadActionInterface.php index d2f9b70913c1f..389bd8089967b 100644 --- a/lib/internal/Magento/Framework/App/Action/HttpHeadActionInterface.php +++ b/lib/internal/Magento/Framework/App/Action/HttpHeadActionInterface.php @@ -12,6 +12,8 @@ /** * Marker for actions processing HEAD requests. + * + * @deprecated Both GET and HEAD requests map to HttpGetActionInterface */ interface HttpHeadActionInterface extends ActionInterface { diff --git a/lib/internal/Magento/Framework/App/Http.php b/lib/internal/Magento/Framework/App/Http.php index 3c6dee49f97b4..a2d7d136e12d7 100644 --- a/lib/internal/Magento/Framework/App/Http.php +++ b/lib/internal/Magento/Framework/App/Http.php @@ -142,12 +142,26 @@ public function launch() } else { throw new \InvalidArgumentException('Invalid return type'); } + if ($this->_request->isHead() && $this->_response->getHttpResponseCode() == 200) { + $this->handleHeadRequest(); + } // This event gives possibility to launch something before sending output (allow cookie setting) $eventParams = ['request' => $this->_request, 'response' => $this->_response]; $this->_eventManager->dispatch('controller_front_send_response_before', $eventParams); return $this->_response; } + /** + * Handle HEAD requests by adding the Content-Length header and removing the body from the response. + * @return void + */ + private function handleHeadRequest() + { + $contentLength = strlen($this->_response->getContent()); + $this->_response->clearBody(); + $this->_response->setHeader('Content-Length', $contentLength); + } + /** * {@inheritdoc} */ diff --git a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php index a299e04e152cc..6606dce5b2ab1 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php @@ -92,7 +92,7 @@ protected function setUp() 'pathInfoProcessor' => $pathInfoProcessorMock, 'objectManager' => $objectManagerMock ]) - ->setMethods(['getFrontName']) + ->setMethods(['getFrontName', 'isHead']) ->getMock(); $this->areaListMock = $this->getMockBuilder(\Magento\Framework\App\AreaList::class) ->disableOriginalConstructor() @@ -155,6 +155,7 @@ private function setUpLaunch() public function testLaunchSuccess() { $this->setUpLaunch(); + $this->requestMock->expects($this->once())->method('isHead')->will($this->returnValue(false)); $this->eventManagerMock->expects($this->once()) ->method('dispatch') ->with( @@ -181,6 +182,34 @@ function () { $this->http->launch(); } + public function testLaunchHeadRequest() + { + $body = "Test"; + $contentLength = strlen($body); + $this->setUpLaunch(); + $this->requestMock->expects($this->once())->method('isHead')->will($this->returnValue(true)); + $this->responseMock->expects($this->once()) + ->method('getHttpResponseCode') + ->will($this->returnValue(200)); + $this->responseMock->expects($this->once()) + ->method('getContent') + ->will($this->returnValue($body)); + $this->responseMock->expects($this->once()) + ->method('clearBody') + ->will($this->returnValue($this->responseMock)); + $this->responseMock->expects($this->once()) + ->method('setHeader') + ->with('Content-Length', $contentLength) + ->will($this->returnValue($this->responseMock)); + $this->eventManagerMock->expects($this->once()) + ->method('dispatch') + ->with( + 'controller_front_send_response_before', + ['request' => $this->requestMock, 'response' => $this->responseMock] + ); + $this->assertSame($this->responseMock, $this->http->launch()); + } + public function testHandleDeveloperModeNotInstalled() { $dir = $this->getMockForAbstractClass(\Magento\Framework\Filesystem\Directory\ReadInterface::class); diff --git a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php index d945791282a2d..1ea47991d6df6 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php @@ -9,6 +9,11 @@ class HttpTest extends \PHPUnit\Framework\TestCase { + /** + * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + */ + private $request; + /** * @var \Magento\Framework\HTTP\PhpEnvironment\Response|\PHPUnit_Framework_MockObject_MockObject */ @@ -29,12 +34,16 @@ class HttpTest extends \PHPUnit\Framework\TestCase */ protected function setUp() { + $this->request = $this->createPartialMock( + \Magento\Framework\App\Request\Http::class, + ['isHead'] + ); $this->response = $this->createPartialMock( \Magento\Framework\HTTP\PhpEnvironment\Response::class, ['setHeader', 'sendHeaders', 'setHeaders'] ); $this->mime = $this->createMock(\Magento\Framework\File\Mime::class); - $this->object = new Http($this->response, $this->mime); + $this->object = new Http($this->request, $this->response, $this->mime); } /** @@ -57,6 +66,9 @@ public function testSend(): void ->method('getMimeType') ->with($file) ->will($this->returnValue($contentType)); + $this->request->expects($this->once()) + ->method('isHead') + ->will($this->returnValue(false)); $this->expectOutputString(file_get_contents($file)); $this->object->send($file); @@ -83,6 +95,9 @@ public function testSendWithOptions(): void ->method('getMimeType') ->with($file) ->will($this->returnValue($contentType)); + $this->request->expects($this->once()) + ->method('isHead') + ->will($this->returnValue(false)); $this->expectOutputString(file_get_contents($file)); $this->object->send(['filepath' => $file, 'headers' => $headers]); @@ -106,4 +121,32 @@ public function testSendNoFileExistException(): void { $this->object->send('nonexistent.file'); } + + /** + * @return void + */ + public function testSendHeadRequest(): void + { + $file = __DIR__ . '/../../_files/javascript.js'; + $contentType = 'content/type'; + + $this->response->expects($this->at(0)) + ->method('setHeader') + ->with('Content-length', filesize($file)); + $this->response->expects($this->at(1)) + ->method('setHeader') + ->with('Content-Type', $contentType); + $this->response->expects($this->once()) + ->method('sendHeaders'); + $this->mime->expects($this->once()) + ->method('getMimeType') + ->with($file) + ->will($this->returnValue($contentType)); + $this->request->expects($this->once()) + ->method('isHead') + ->will($this->returnValue(true)); + + $this->object->send($file); + $this->assertEquals(false, $this->hasOutput()); + } } diff --git a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php index aa527866eff55..74cc347fd2fa2 100644 --- a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php +++ b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php @@ -8,6 +8,11 @@ class Http { + /** + * @var \Magento\Framework\App\Request\Http + */ + private $request; + /** * @var \Magento\Framework\HTTP\PhpEnvironment\Response */ @@ -19,13 +24,16 @@ class Http private $mime; /** + * @param \Magento\Framework\App\Request\Http $request * @param \Magento\Framework\App\Response\Http $response * @param \Magento\Framework\File\Mime $mime */ public function __construct( + \Magento\Framework\App\Request\Http $request, \Magento\Framework\HTTP\PhpEnvironment\Response $response, \Magento\Framework\File\Mime $mime ) { + $this->request = $request; $this->response = $response; $this->mime = $mime; } @@ -55,6 +63,11 @@ public function send($options = null) $this->response->sendHeaders(); + if ($this->request->isHead()) { + // Do not send the body on HEAD requests. + return; + } + $handle = fopen($filepath, 'r'); if ($handle) { while (($buffer = fgets($handle, 4096)) !== false) { From 4f7db3a20848947424f1013d7102c443278d692d Mon Sep 17 00:00:00 2001 From: Matti Vapa Date: Tue, 5 Mar 2019 17:58:22 +0200 Subject: [PATCH 035/585] Revert "Fix for issue #21299. Changed the built-in cache to not cache 404 responses to HEAD requests." This reverts commit 46191d82d04e2392cb58a2c03121987a14052043. --- .../Framework/App/PageCache/Kernel.php | 22 +++---------------- .../App/Test/Unit/PageCache/KernelTest.php | 2 +- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/lib/internal/Magento/Framework/App/PageCache/Kernel.php b/lib/internal/Magento/Framework/App/PageCache/Kernel.php index bb24c84d03e57..13e18ed28fd67 100644 --- a/lib/internal/Magento/Framework/App/PageCache/Kernel.php +++ b/lib/internal/Magento/Framework/App/PageCache/Kernel.php @@ -137,7 +137,9 @@ public function process(\Magento\Framework\App\Response\Http $response) if (preg_match('/public.*s-maxage=(\d+)/', $response->getHeader('Cache-Control')->getFieldValue(), $matches)) { $maxAge = $matches[1]; $response->setNoCacheHeaders(); - if ($this->shouldCacheResponse($response)) { + if (($response->getHttpResponseCode() == 200 || $response->getHttpResponseCode() == 404) + && ($this->request->isGet() || $this->request->isHead()) + ) { $tagsHeader = $response->getHeader('X-Magento-Tags'); $tags = $tagsHeader ? explode(',', $tagsHeader->getFieldValue()) : []; @@ -216,22 +218,4 @@ private function getCache() } return $this->fullPageCache; } - - /** - * Check if the response should be cached. For GET requests both 200 and 404 responses should be - * cached. For HEAD requests only 200 responses should be cached. - * - * @param \Magento\Framework\App\Response\Http $response - * @return bool - */ - private function shouldCacheResponse(\Magento\Framework\App\Response\Http $response) - { - $responseCode = $response->getHttpResponseCode(); - if ($this->request->isGet()) { - return $responseCode == 200 || $responseCode == 404; - } elseif ($this->request->isHead()) { - return $responseCode == 200; - } - return false; - } } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/PageCache/KernelTest.php b/lib/internal/Magento/Framework/App/Test/Unit/PageCache/KernelTest.php index 74201a15d695d..db200f962f5b5 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/PageCache/KernelTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/PageCache/KernelTest.php @@ -248,7 +248,7 @@ public function testProcessSaveCacheDataProvider() { return [ [200, [3, 4, 5]], - [404, [3, 4, 5]] + [404, [4, 5, 6]] ]; } From bddb7dcc6282962c0e4864d0ba522ded2e89b589 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh Date: Wed, 6 Mar 2019 09:04:55 -0600 Subject: [PATCH 036/585] MC-4432: Convert ApplyConfigurableProductCatalogPriceRulesTest to MFTF --- .../Catalog/Test/Mftf/Data/ProductData.xml | 4 + .../Test/Mftf/Data/ProductOptionData.xml | 9 + .../Test/Mftf/Data/ProductOptionValueData.xml | 6 + .../CatalogPriceRuleActionGroup.xml | 23 ++ .../Test/Mftf/Data/CatalogRuleData.xml | 14 + .../AdminNewCatalogPriceRuleSection.xml | 2 + .../StorefrontCatalogPriceRuleActionGroup.xml | 30 ++ ...eProductWithAssignedSimpleProductsTest.xml | 277 ++++++++++++++++++ ...eForConfigurableProductWithOptionsTest.xml | 221 ++++++++++++++ .../StorefrontProductCartActionGroup.xml | 28 ++ .../Section/CheckoutCartProductSection.xml | 1 + .../StorefrontCategoryActionGroup.xml | 11 + .../StorefrontProductInfoMainSection.xml | 1 + 13 files changed, 627 insertions(+) create mode 100644 app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontCatalogPriceRuleActionGroup.xml create mode 100644 app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml create mode 100644 app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index c011dd2dc5faa..94ccecfb0a2d8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -382,6 +382,10 @@ ProductOptionDateTime ProductOptionTime + + + ProductOptionRadiobuttonWithTwoFixedOptions + ProductOptionDropDownWithLongValuesTitle diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml index ca5024920ad40..36ec649fdde70 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml @@ -77,6 +77,15 @@ ProductOptionValueRadioButtons1 ProductOptionValueRadioButtons2 + + + OptionRadioButtons + radio + 5 + true + ProductOptionValueRadioButtons1 + ProductOptionValueRadioButtons3 + OptionCheckbox diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml index d16a201cd9ecc..8e9c0f86b38c7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml @@ -32,6 +32,12 @@ 99.99 percent + + OptionValueRadioButtons3 + 3 + 10 + fixed + OptionValueCheckbox 1 diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml index b0c4f2d8a609f..fd300dc90c7ec 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml @@ -71,6 +71,22 @@ + + + + + + + + + + + + + + + + @@ -116,4 +132,11 @@ + + + + + + + diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml b/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml index 5b75708d1ae0a..688247f5b3a23 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml @@ -94,4 +94,18 @@ by_percent 10 + + + CatalogPriceRuleWithoutDiscount + Catalog Price Rule Description + 1 + + 0 + + + 1 + + by_percent + 0 + diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml b/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml index 635260888e7fb..16b7acb6e6568 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml @@ -42,6 +42,8 @@ + + diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontCatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontCatalogPriceRuleActionGroup.xml new file mode 100644 index 0000000000000..5eb6cf45f1e79 --- /dev/null +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontCatalogPriceRuleActionGroup.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml new file mode 100644 index 0000000000000..5409d2fe04c59 --- /dev/null +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml @@ -0,0 +1,277 @@ + + + + + + + + + + <description value="Admin should be able to apply catalog rule for configurable product with assigned simple products"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14063"/> + <group value="catalogRuleConfigurable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category for first configurable product --> + <createData entity="SimpleSubCategory" stepKey="firstSimpleCategory"/> + + <!-- Create first configurable product with two options --> + <createData entity="ApiConfigurableProduct" stepKey="createFirstConfigProduct"> + <requiredEntity createDataKey="firstSimpleCategory"/> + </createData> + + <createData entity="productAttributeWithTwoOptions" stepKey="createFirstConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createFirstConfigProductAttributeFirstOption"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption2" stepKey="createFirstConfigProductAttributeSecondOption"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + </createData> + + <createData entity="AddToDefaultSet" stepKey="addFirstProductToAttributeSet"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + </createData> + + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getFirstConfigAttributeFirstOption"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getFirstConfigAttributeSecondOption"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + </getData> + + <!-- Create two child products for first configurable product --> + <createData entity="ApiSimpleOne" stepKey="createFirstConfigFirstChildProduct"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + <requiredEntity createDataKey="getFirstConfigAttributeFirstOption"/> + </createData> + + <createData entity="ApiSimpleOne" stepKey="createFirstConfigSecondChildProduct"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + <requiredEntity createDataKey="getFirstConfigAttributeSecondOption"/> + </createData> + + <createData entity="ConfigurableProductTwoOptions" stepKey="createFirstConfigProductOption"> + <requiredEntity createDataKey="createFirstConfigProduct"/> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + <requiredEntity createDataKey="getFirstConfigAttributeFirstOption"/> + <requiredEntity createDataKey="getFirstConfigAttributeSecondOption"/> + </createData> + + <createData entity="ConfigurableProductAddChild" stepKey="createFirstConfigProductAddFirstChild"> + <requiredEntity createDataKey="createFirstConfigProduct"/> + <requiredEntity createDataKey="createFirstConfigFirstChildProduct"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createFirstConfigProductAddSecondChild"> + <requiredEntity createDataKey="createFirstConfigProduct"/> + <requiredEntity createDataKey="createFirstConfigSecondChildProduct"/> + </createData> + + <!-- Add customizable options to first product --> + <updateData createDataKey="createFirstConfigProduct" entity="productWithOptionRadiobutton" stepKey="updateFirstProductWithOption"/> + + <!-- Create category for second configurable product --> + <createData entity="SimpleSubCategory" stepKey="secondSimpleCategory"/> + + <!-- Create second configurable product with two options --> + <createData entity="ApiConfigurableProduct" stepKey="createSecondConfigProduct"> + <requiredEntity createDataKey="secondSimpleCategory"/> + </createData> + + <createData entity="productAttributeWithTwoOptions" stepKey="createSecondConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createSecondConfigProductAttributeFirstOption"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption2" stepKey="createSecondConfigProductAttributeSecondOption"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + </createData> + + <createData entity="AddToDefaultSet" stepKey="addSecondProductToAttributeSet"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + </createData> + + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getSecondConfigAttributeFirstOption"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getSecondConfigAttributeSecondOption"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + </getData> + + <!-- Create two child products for second configurable product --> + <createData entity="ApiSimpleOne" stepKey="createSecondConfigFirstChildProduct"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + <requiredEntity createDataKey="getSecondConfigAttributeFirstOption"/> + </createData> + + <createData entity="ApiSimpleOne" stepKey="createSecondConfigSecondChildProduct"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + <requiredEntity createDataKey="getSecondConfigAttributeSecondOption"/> + </createData> + + <createData entity="ConfigurableProductTwoOptions" stepKey="createSecondConfigProductOption"> + <requiredEntity createDataKey="createSecondConfigProduct"/> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + <requiredEntity createDataKey="getSecondConfigAttributeFirstOption"/> + <requiredEntity createDataKey="getSecondConfigAttributeSecondOption"/> + </createData> + + <createData entity="ConfigurableProductAddChild" stepKey="createSecondConfigProductAddFirstChild"> + <requiredEntity createDataKey="createSecondConfigProduct"/> + <requiredEntity createDataKey="createSecondConfigFirstChildProduct"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createSecondConfigProductAddSecondChild"> + <requiredEntity createDataKey="createSecondConfigProduct"/> + <requiredEntity createDataKey="createSecondConfigSecondChildProduct"/> + </createData> + + <!-- Add customizable options to second product --> + <updateData createDataKey="createSecondConfigProduct" entity="productWithOptionRadiobutton" stepKey="updateSecondProductWithOption"/> + + <!--Create customer group --> + <createData entity="CustomCustomerGroup" stepKey="customerGroup"/> + + <!-- Create Customer --> + <createData entity="CustomerEntityOne" stepKey="createCustomer"/> + + <!-- Login as Admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + </before> + <after> + <!-- Customer log out --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> + + <!-- Delete created data --> + <deleteData createDataKey="createFirstConfigProduct" stepKey="deleteFirstConfigProduct"/> + <deleteData createDataKey="createFirstConfigFirstChildProduct" stepKey="deleteFirstConfigFirstChildProduct"/> + <deleteData createDataKey="createFirstConfigSecondChildProduct" stepKey="deleteFirstConfigSecondChildProduct"/> + <deleteData createDataKey="createFirstConfigProductAttribute" stepKey="deleteFirstConfigProductAttribute"/> + <deleteData createDataKey="firstSimpleCategory" stepKey="deleteFirstSimpleCategory"/> + + <deleteData createDataKey="createSecondConfigProduct" stepKey="deleteSecondConfigProduct"/> + <deleteData createDataKey="createSecondConfigFirstChildProduct" stepKey="deleteSecondConfigFirstChildProduct"/> + <deleteData createDataKey="createSecondConfigSecondChildProduct" stepKey="deleteSecondConfigSecondChildProduct"/> + <deleteData createDataKey="createSecondConfigProductAttribute" stepKey="deleteSecondConfigProductAttribute"/> + <deleteData createDataKey="secondSimpleCategory" stepKey="deleteSimpleCategory"/> + + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="customerGroup" stepKey="deleteCustomerGroup"/> + + <!-- Delete created price rules --> + <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage"/> + <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRuleForFirstOption"> + <argument name="name" value="{{CatalogRuleToFixed.name}}"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> + </actionGroup> + + <!-- Admin log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Go to the Customer page and find created customer --> + <actionGroup ref="AdminFilterCustomerByEmail" stepKey="findCreatedCustomerByEmail"> + <argument name="email" value="$$createCustomer.email$$"/> + </actionGroup> + <actionGroup ref="AdminSelectAllCustomers" stepKey="selectCustomer"/> + + <!-- Change customer group to created below --> + <actionGroup ref="SetCustomerGroupForSelectedCustomersViaGrid" stepKey="setCustomerGroup"> + <argument name="groupName" value="$$customerGroup.code$$"/> + </actionGroup> + + <!-- Create price rule --> + <actionGroup ref="newCatalogPriceRuleByUI" stepKey="createFirstPriceRule"> + <argument name="catalogRule" value="CatalogRuleToFixed"/> + </actionGroup> + <actionGroup ref="selectNewCustomerGroupActionGroup" stepKey="adFirstCustomerGroup"> + <argument name="customerGroup" value="$$customerGroup.code$$"/> + </actionGroup> + <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="clickSaveAndApplyRulesForFirst"/> + <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccessForFirst"/> + + <!-- Run full reindex and clear caches --> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + + <!-- Login to storefront from customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Assert first product in category --> + <amOnPage url="$$firstSimpleCategory.name$$.html" stepKey="goToFirstCategoryPageStorefront"/> + <waitForPageLoad stepKey="waitForFirstCategoryPageLoad"/> + <actionGroup ref="StorefrontCheckCategoryConfigurableProductWithUpdatedPrice" stepKey="checkFirstProductPriceInCategory"> + <argument name="product" value="$$createFirstConfigProduct$$"/> + <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> + </actionGroup> + + <!-- Assert second product in category --> + <amOnPage url="$$secondSimpleCategory.name$$.html" stepKey="goToSecondCategoryPageStorefront"/> + <waitForPageLoad stepKey="waitForSecondCategoryPageLoad"/> + <actionGroup ref="StorefrontCheckCategoryConfigurableProductWithUpdatedPrice" stepKey="checkSecondProductPriceInCategory"> + <argument name="product" value="$$createSecondConfigProduct$$"/> + <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> + </actionGroup> + + <!-- Assert first product in storefront product page --> + <amOnPage url="$$createFirstConfigProduct.custom_attributes[url_key]$$.html" stepKey="amOnFirstProductPage"/> + <waitForPageLoad stepKey="waitForFirstProductPageLoad"/> + <actionGroup ref="assertUpdatedProductPriceInStorefrontProductPage" stepKey="checkFirstProductPriceInStorefrontProductPage"> + <argument name="product" value="$$createFirstConfigProduct$$"/> + <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> + </actionGroup> + + <!-- Add first product with selected options to the cart --> + <actionGroup ref="StorefrontAddProductWithSelectedOptionsToCartActionGroup" stepKey="addFirstProductWithSelectedOptionsToCart1"> + <argument name="product" value="$$createFirstConfigProduct$$"/> + <argument name="productCount" value="1"/> + <argument name="option" value="$$createFirstConfigProductAttributeFirstOption.option[store_labels][1][label]$$"/> + <argument name="customizableOption" value="{{ProductOptionValueRadioButtons1.title}}"/> + </actionGroup> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.updatedPrice}}" stepKey="grabForthProductUpdatedPrice1"/> + + <actionGroup ref="StorefrontAddProductWithSelectedOptionsToCartActionGroup" stepKey="addFirstProductWithSelectedOptionsToCart2"> + <argument name="product" value="$$createFirstConfigProduct$$"/> + <argument name="productCount" value="1"/> + <argument name="option" value="$$createFirstConfigProductAttributeSecondOption.option[store_labels][1][label]$$"/> + <argument name="customizableOption" value="{{ProductOptionValueRadioButtons3.title}}"/> + </actionGroup> + + <!-- Assert second product in storefront product page --> + <amOnPage url="$$createSecondConfigProduct.custom_attributes[url_key]$$.html" stepKey="amOnSecondProductPage"/> + <waitForPageLoad stepKey="waitForSecondProductPageLoad"/> + <actionGroup ref="assertUpdatedProductPriceInStorefrontProductPage" stepKey="checkSecondProductPriceInStorefrontProductPage"> + <argument name="product" value="$$createSecondConfigProduct$$"/> + <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> + </actionGroup> + + <!-- Add second product with selected options to the cart --> + <actionGroup ref="StorefrontAddProductWithSelectedOptionsToCartActionGroup" stepKey="addSecondProductWithSelectedOptionsToCart1"> + <argument name="product" value="$$createSecondConfigProduct$$"/> + <argument name="productCount" value="1"/> + <argument name="option" value="$$createSecondConfigProductAttributeFirstOption.option[store_labels][1][label]$$"/> + <argument name="customizableOption" value="{{ProductOptionValueRadioButtons1.title}}"/> + </actionGroup> + + <actionGroup ref="StorefrontAddProductWithSelectedOptionsToCartActionGroup" stepKey="addSecondProductWithSelectedOptionsToCart2"> + <argument name="product" value="$$createSecondConfigProduct$$"/> + <argument name="productCount" value="1"/> + <argument name="option" value="$$createSecondConfigProductAttributeSecondOption.option[store_labels][1][label]$$"/> + <argument name="customizableOption" value="{{ProductOptionValueRadioButtons3.title}}"/> + </actionGroup> + + <!--Assert products prices in the cart --> + <amOnPage url="/checkout/cart/" stepKey="amOnShoppingCartPage"/> + <waitForPageLoad stepKey="waitForShoppingCartPageLoad"/> + <see userInput="$210.69" selector="{{CheckoutCartProductSection.ProductPriceByOption($$createFirstConfigProductAttributeFirstOption.option[store_labels][1][label]$$)}}" stepKey="assertFirstProductPriceForFirstProductOption"/> + <see userInput="$120.70" selector="{{CheckoutCartProductSection.ProductPriceByOption($$createFirstConfigProductAttributeSecondOption.option[store_labels][1][label]$$)}}" stepKey="assertFirstProductPriceForSecondProductOption"/> + <see userInput="$210.69" selector="{{CheckoutCartProductSection.ProductPriceByOption($$createSecondConfigProductAttributeFirstOption.option[store_labels][1][label]$$)}}" stepKey="assertSecondProductPriceForFirstProductOption"/> + <see userInput="$120.70" selector="{{CheckoutCartProductSection.ProductPriceByOption($$createSecondConfigProductAttributeSecondOption.option[store_labels][1][label]$$)}}" stepKey="assertSecondProductPriceForSecondProductOption"/> + </test> +</tests> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml new file mode 100644 index 0000000000000..bf5a9b4c6c8dd --- /dev/null +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml @@ -0,0 +1,221 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminApplyCatalogRuleForConfigurableProductWithOptionsTest"> + <annotations> + <features value="CatalogRuleConfigurable"/> + <stories value="Apply catalog price rule"/> + <title value="Apply catalog price rule for configurable product with options"/> + <description value="Admin should be able to apply the catalog rule for configurable product with options"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14062"/> + <group value="catalogRuleConfigurable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="simpleCategory"/> + + <!-- Create configurable product with three options --> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="simpleCategory"/> + </createData> + + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeFirstOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeSecondOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption3" stepKey="createConfigProductAttributeThirdOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeFirstOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeSecondOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="3" stepKey="getConfigAttributeThirdOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + + <!-- Create three child products --> + <createData entity="ApiSimpleOne" stepKey="createConfigFirstChildProduct"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeFirstOption"/> + </createData> + + <createData entity="ApiSimpleOne" stepKey="createConfigSecondChildProduct"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeSecondOption"/> + </createData> + + <createData entity="ApiSimpleOne" stepKey="createConfigThirdChildProduct"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeThirdOption"/> + </createData> + + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeFirstOption"/> + <requiredEntity createDataKey="getConfigAttributeSecondOption"/> + <requiredEntity createDataKey="getConfigAttributeThirdOption"/> + </createData> + + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddFirstChild"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigFirstChildProduct"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddSecondChild"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigSecondChildProduct"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddThirdChild"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigThirdChildProduct"/> + </createData> + + <!-- Login as Admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + </before> + <after> + <!-- Delete created data --> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigFirstChildProduct" stepKey="deleteFirstSimpleProduct"/> + <deleteData createDataKey="createConfigSecondChildProduct" stepKey="deleteSecondSimpleProduct"/> + <deleteData createDataKey="createConfigThirdChildProduct" stepKey="deleteThirdSimpleProduct"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="simpleCategory" stepKey="deleteCategory"/> + + <!-- Delete created price rules --> + <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage"/> + <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRuleForFirstOption"> + <argument name="name" value="{{CatalogRuleToFixed.name}}"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> + </actionGroup> + + <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRuleForSecondOption"> + <argument name="name" value="{{_defaultCatalogRule.name}}"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> + </actionGroup> + + <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRuleForThirdOption"> + <argument name="name" value="{{CatalogRuleWithoutDiscount.name}}"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> + </actionGroup> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create price rule for first configurable product option --> + <actionGroup ref="newCatalogPriceRuleByUI" stepKey="createFirstPriceRule"> + <argument name="catalogRule" value="CatalogRuleToFixed"/> + </actionGroup> + <actionGroup ref="selectNotLoggedInCustomerGroup" stepKey="selectNotLoggedInCustomerGroupForFirstPriceRule"/> + <actionGroup ref="CreateCatalogPriceRuleConditionWithAttributeAndOption" stepKey="createFirstCatalogPriceRuleCondition"> + <argument name="attributeName" value="$$createConfigProductAttribute.attribute[frontend_labels][0][label]$$"/> + <argument name="targetSelectValue" value="$$createConfigProductAttributeFirstOption.option[store_labels][1][label]$$"/> + <argument name="indexA" value="1"/> + <argument name="indexB" value="1"/> + </actionGroup> + <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="saveAndApplyFirstPriceRule"/> + <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccessMessageForFirstPriceRule"/> + + <!-- Create price rule for second configurable product option --> + <actionGroup ref="newCatalogPriceRuleByUI" stepKey="createSecondPriceRule"> + <argument name="catalogRule" value="_defaultCatalogRule"/> + </actionGroup> + <actionGroup ref="selectNotLoggedInCustomerGroup" stepKey="selectNotLoggedInCustomerGroupForSecondPriceRule"/> + <actionGroup ref="CreateCatalogPriceRuleConditionWithAttributeAndOption" stepKey="createSecondCatalogPriceRuleCondition"> + <argument name="attributeName" value="$$createConfigProductAttribute.attribute[frontend_labels][0][label]$$"/> + <argument name="targetSelectValue" value="$$createConfigProductAttributeSecondOption.option[store_labels][1][label]$$"/> + <argument name="indexA" value="1"/> + <argument name="indexB" value="1"/> + </actionGroup> + <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="saveAndApplySecondPriceRule"/> + <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccessMessageForSecondPriceRule"/> + + <!-- Create price rule for third configurable product option --> + <actionGroup ref="newCatalogPriceRuleByUI" stepKey="createThirdPriceRule"> + <argument name="catalogRule" value="CatalogRuleWithoutDiscount"/> + </actionGroup> + <actionGroup ref="selectNotLoggedInCustomerGroup" stepKey="selectNotLoggedInCustomerGroupForThirdPriceRule"/> + <actionGroup ref="CreateCatalogPriceRuleConditionWithAttributeAndOption" stepKey="createThirdCatalogPriceRuleCondition"> + <argument name="attributeName" value="$$createConfigProductAttribute.attribute[frontend_labels][0][label]$$"/> + <argument name="targetSelectValue" value="$$createConfigProductAttributeThirdOption.option[store_labels][1][label]$$"/> + <argument name="indexA" value="1"/> + <argument name="indexB" value="1"/> + </actionGroup> + <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="saveAndApplyThirdPriceRule"/> + <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccessMessageForThirdPriceRule"/> + + <!-- Run full reindex and clear caches --> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + + <!-- Assert product in storefront product page --> + <amOnPage url="$$createConfigProduct.custom_attributes[url_key]$$.html" stepKey="amOnProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <actionGroup ref="assertUpdatedProductPriceInStorefrontProductPage" stepKey="assertUpdatedProductPriceInStorefrontProductPage"> + <argument name="product" value="$$createConfigProduct$$"/> + <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> + </actionGroup> + + <!-- Assert product options price in storefront product page --> + <actionGroup ref="assertCatalogPriceRuleAppliedToProductOption" stepKey="assertCatalogPriceRuleAppliedToFirstProductOption"> + <argument name="option" value="$$createConfigProductAttributeFirstOption.option[store_labels][1][label]$$"/> + <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> + </actionGroup> + + <actionGroup ref="assertCatalogPriceRuleAppliedToProductOption" stepKey="assertCatalogPriceRuleAppliedToSecondProductOption"> + <argument name="option" value="$$createConfigProductAttributeSecondOption.option[store_labels][1][label]$$"/> + <argument name="expectedPrice" value="$110.70"/> + </actionGroup> + + <actionGroup ref="assertCatalogPriceRuleAppliedToProductOption" stepKey="assertCatalogPriceRuleAppliedToThirdProductOption"> + <argument name="option" value="$$createConfigProductAttributeThirdOption.option[store_labels][1][label]$$"/> + <argument name="expectedPrice" value="{{ApiConfigurableProduct.price}}"/> + </actionGroup> + + <!-- Add product with selected option to the cart --> + <actionGroup ref="StorefrontAddProductWithSelectedOptionToCartActionGroup" stepKey="addProductWithSelectedFirstOptionToCart"> + <argument name="product" value="$$createConfigProduct$$"/> + <argument name="productCount" value="1"/> + <argument name="option" value="$$createConfigProductAttributeFirstOption.option[store_labels][1][label]$$"/> + </actionGroup> + + <actionGroup ref="StorefrontAddProductWithSelectedOptionToCartActionGroup" stepKey="addProductWithSelectedSecondOptionToCart"> + <argument name="product" value="$$createConfigProduct$$"/> + <argument name="productCount" value="1"/> + <argument name="option" value="$$createConfigProductAttributeSecondOption.option[store_labels][1][label]$$"/> + </actionGroup> + + <actionGroup ref="StorefrontAddProductWithSelectedOptionToCartActionGroup" stepKey="addProductWithSelectedThirdOptionToCart"> + <argument name="product" value="$$createConfigProduct$$"/> + <argument name="productCount" value="1"/> + <argument name="option" value="$$createConfigProductAttributeThirdOption.option[store_labels][1][label]$$"/> + </actionGroup> + + <!--Assert product price in the cart --> + <amOnPage url="/checkout/cart/" stepKey="amOnShoppingCartPage"/> + <waitForPageLoad stepKey="waitForShoppingCartPageLoad"/> + <see userInput="{{CatalogRuleToFixed.discount_amount}}" selector="{{CheckoutCartProductSection.ProductPriceByOption($$createConfigProductAttributeFirstOption.option[store_labels][1][label]$$)}}" stepKey="assertProductPriceForFirstProductOption"/> + <see userInput="$110.70" selector="{{CheckoutCartProductSection.ProductPriceByOption($$createConfigProductAttributeSecondOption.option[store_labels][1][label]$$)}}" stepKey="assertProductPriceForSecondProductOption"/> + <see userInput="{{ApiConfigurableProduct.price}}" selector="{{CheckoutCartProductSection.ProductPriceByOption($$createConfigProductAttributeThirdOption.option[store_labels][1][label]$$)}}" stepKey="assertProductPriceForThirdProductOption"/> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontProductCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontProductCartActionGroup.xml index 24ed05583b6fb..371658748eec7 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontProductCartActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontProductCartActionGroup.xml @@ -54,6 +54,34 @@ <waitForText userInput="{{productCount}}" selector="{{StorefrontMinicartSection.productCount}}" time="30" stepKey="assertProductCount"/> </actionGroup> + <!-- Add product with selected option to Cart from the product page --> + <actionGroup name="StorefrontAddProductWithSelectedOptionToCartActionGroup"> + <arguments> + <argument name="product" type="entity"/> + <argument name="productCount" type="string"/> + <argument name="option" type="string"/> + </arguments> + <selectOption userInput="{{option}}" selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" stepKey="selectOption"/> + <click selector="{{StorefrontProductInfoMainSection.AddToCart}}" stepKey="clickAddToCart"/> + <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" stepKey="waitForSuccessMessage"/> + <see selector="{{StorefrontProductPageSection.messagesBlock}}" userInput="You added {{product.name}} to your shopping cart." stepKey="assertSuccessMessage"/> + </actionGroup> + + <!-- Add product with selected configurable option and customizable option to cart from the product page --> + <actionGroup name="StorefrontAddProductWithSelectedOptionsToCartActionGroup"> + <arguments> + <argument name="product" type="entity"/> + <argument name="productCount" type="string"/> + <argument name="option" type="string"/> + <argument name="customizableOption" type="string"/> + </arguments> + <selectOption userInput="{{option}}" selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" stepKey="selectOption"/> + <click selector="{{StorefrontProductInfoMainSection.selectCustomOptionByName(customizableOption)}}" stepKey="selectCustomOption"/> + <click selector="{{StorefrontProductInfoMainSection.AddToCart}}" stepKey="clickAddToCart"/> + <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" stepKey="waitForSuccessMessage"/> + <see selector="{{StorefrontProductPageSection.messagesBlock}}" userInput="You added {{product.name}} to your shopping cart." stepKey="assertSuccessMessage"/> + </actionGroup> + <!-- Open the Minicart and check Simple Product --> <actionGroup name="StorefrontOpenMinicartAndCheckSimpleProductActionGroup"> <arguments> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml index dcfb12fd4e965..1fdbf11d48f1d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml @@ -24,6 +24,7 @@ <element name="ProductOptionByNameAndAttribute" type="input" selector="//main//table[@id='shopping-cart-table']//tbody//tr[.//strong[contains(@class, 'product-item-name')]//a[contains(text(), '{{var1}}')]]//dl[@class='item-options']//dt[.='{{var2}}']/following-sibling::dd[1]" parameterized="true"/> + <element name="ProductPriceByOption" type="text" selector="//*[contains(@class, 'item-options')]/dd[normalize-space(.)='{{var1}}']/ancestor::tr//td[contains(@class, 'price')]//span[@class='price']" parameterized="true"/> <element name="RemoveItem" type="button" selector="//table[@id='shopping-cart-table']//tbody//tr[contains(@class,'item-actions')]//a[contains(@class,'action-delete')]"/> <element name="productName" type="text" selector="//tbody[@class='cart item']//strong[@class='product-item-name']"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml index e2759fc0fd23d..845fa64ad3d12 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml @@ -32,4 +32,15 @@ <seeElement selector="{{StorefrontCategoryProductSection.ProductStockUnavailable}}" stepKey="AssertOutOfStock"/> <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductAddToCartByName(product.name)}}" stepKey="AssertAddToCart" /> </actionGroup> + + <actionGroup name="StorefrontCheckCategoryConfigurableProductWithUpdatedPrice"> + <arguments> + <argument name="product" type="entity"/> + <argument name="expectedPrice" type="string"/> + </arguments> + <seeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName(product.name)}}" stepKey="assertProductName"/> + <see userInput="{{expectedPrice}}" selector="{{StorefrontCategoryProductSection.ProductPriceByName(product.name)}}" stepKey="AssertProductPrice"/> + <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName(product.name)}}" stepKey="moveMouseOverProduct" /> + <seeElement selector="{{StorefrontCategoryProductSection.ProductAddToCartByName(product.name)}}" stepKey="AssertAddToCart" /> + </actionGroup> </actionGroups> \ No newline at end of file diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index 09de3cc302903..98d2d76e64adb 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -15,6 +15,7 @@ <element name="productAttributeOptions1" type="select" selector="#product-options-wrapper div[tabindex='0'] option"/> <element name="productAttributeOptionsSelectButton" type="select" selector="#product-options-wrapper .super-attribute-select"/> <element name="productAttributeOptionsError" type="text" selector="//div[@class='mage-error']"/> + <element name="selectCustomOptionByName" type="radio" selector="//*[@class='options-list nested']//span[text()='{{value}}']/../../input" parameterized="true"/> <!-- Parameter is the order number of the attribute on the page (1 is the newest) --> <element name="nthAttributeOnPage" type="block" selector="tr:nth-of-type({{numElement}}) .data" parameterized="true"/> <element name="stockIndication" type="block" selector=".stock" /> From 22b9e56dbb429cf2877a41779e23528c7fce8f0d Mon Sep 17 00:00:00 2001 From: Matti Vapa <matti.vapa@piimega.fi> Date: Thu, 7 Mar 2019 13:16:59 +0200 Subject: [PATCH 037/585] Changed the strlen to mb_strl with 8bit encoding to ensure that the content length is calculated in bytes in all PHP installations. Added test cases to cover non-ascii content (multi-byte characters, null byte, LTR text). --- lib/internal/Magento/Framework/App/Http.php | 6 ++- .../Framework/App/Test/Unit/HttpTest.php | 39 +++++++++++++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Http.php b/lib/internal/Magento/Framework/App/Http.php index a2d7d136e12d7..809287102a4df 100644 --- a/lib/internal/Magento/Framework/App/Http.php +++ b/lib/internal/Magento/Framework/App/Http.php @@ -157,7 +157,11 @@ public function launch() */ private function handleHeadRequest() { - $contentLength = strlen($this->_response->getContent()); + // It is possible that some PHP installations have overloaded strlen to use mb_strlen instead. + // This means strlen might return the actual number of characters in a non-ascii string instead + // of the number of bytes. Use mb_strlen explicitly with a single byte character encoding to ensure + // that the content length is calculated in bytes. + $contentLength = mb_strlen($this->_response->getContent(), '8bit'); $this->_response->clearBody(); $this->_response->setHeader('Content-Length', $contentLength); } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php index 6606dce5b2ab1..6a6b7caf7bdf3 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php @@ -182,10 +182,15 @@ function () { $this->http->launch(); } - public function testLaunchHeadRequest() + + /** + * Test that HEAD requests lead to an empty body and a Content-Length header matching the original body size. + * @dataProvider dataProviderForTestLaunchHeadRequest + * @param string $body + * @param int $expectedLength + */ + public function testLaunchHeadRequest($body, $expectedLength) { - $body = "<html><head></head><body>Test</body></html>"; - $contentLength = strlen($body); $this->setUpLaunch(); $this->requestMock->expects($this->once())->method('isHead')->will($this->returnValue(true)); $this->responseMock->expects($this->once()) @@ -199,7 +204,7 @@ public function testLaunchHeadRequest() ->will($this->returnValue($this->responseMock)); $this->responseMock->expects($this->once()) ->method('setHeader') - ->with('Content-Length', $contentLength) + ->with('Content-Length', $expectedLength) ->will($this->returnValue($this->responseMock)); $this->eventManagerMock->expects($this->once()) ->method('dispatch') @@ -210,6 +215,32 @@ public function testLaunchHeadRequest() $this->assertSame($this->responseMock, $this->http->launch()); } + /** + * Different test content for responseMock with their expected lengths in bytes. + * @return array + */ + public function dataProviderForTestLaunchHeadRequest() + { + return [ + [ + '<html><head></head><body>Test</body></html>', // Ascii text + 43 // Expected Content-Length + ], + [ + '<html><head></head><body>部落格</body></html>', // Multi-byte characters + 48 // Expected Content-Length + ], + [ + '<html><head></head><body>'.chr(0).'</body></html>', // Null byte + 40 // Expected Content-Length + ], + [ + '<html><head></head>خرید<body></body></html>', // LTR text + 47 // Expected Content-Length + ] + ]; + } + public function testHandleDeveloperModeNotInstalled() { $dir = $this->getMockForAbstractClass(\Magento\Framework\Filesystem\Directory\ReadInterface::class); From 56d4cc2f94376d201e6c2a12a8f10ee553ea0f1e Mon Sep 17 00:00:00 2001 From: Matti Vapa <matti.vapa@piimega.fi> Date: Thu, 7 Mar 2019 17:53:04 +0200 Subject: [PATCH 038/585] Changed the test cases from single quotes to double quotes and the null byte from chr(0) to \0 (which is why the double quotes were needed). --- lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php index 6a6b7caf7bdf3..b2d041ac175f5 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php @@ -223,19 +223,19 @@ public function dataProviderForTestLaunchHeadRequest() { return [ [ - '<html><head></head><body>Test</body></html>', // Ascii text + "<html><head></head><body>Test</body></html>", // Ascii text 43 // Expected Content-Length ], [ - '<html><head></head><body>部落格</body></html>', // Multi-byte characters + "<html><head></head><body>部落格</body></html>", // Multi-byte characters 48 // Expected Content-Length ], [ - '<html><head></head><body>'.chr(0).'</body></html>', // Null byte + "<html><head></head><body>\0</body></html>", // Null byte 40 // Expected Content-Length ], [ - '<html><head></head>خرید<body></body></html>', // LTR text + "<html><head></head>خرید<body></body></html>", // LTR text 47 // Expected Content-Length ] ]; From bc8f90993c35b5c232a923ef126ba97d046a35c0 Mon Sep 17 00:00:00 2001 From: Matthew Muscat <matthew@mamis.com.au> Date: Thu, 19 Jul 2018 22:46:18 +1000 Subject: [PATCH 039/585] Resolve incorrect scope code selection when the requested scopeCode is null - resolves an issue whereby the incorrect scope could be returned when attempting to resolve a scope with a requested scopeCode of null - simplify the scope resolver logic to a avoid multiple if conditional checks - move scope interface class to an alias of the class - update docblock on the expected values available for scopeCode Signed-off-by: Matthew Muscat <matthew@mamis.com.au> --- .../Framework/App/Config/ScopeCodeResolver.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php b/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php index 321997afdba95..8876f751f7c3d 100644 --- a/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php +++ b/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\App\Config; +use Magento\Framework\App\ScopeInterface; use Magento\Framework\App\ScopeResolverPool; /** @@ -34,7 +35,7 @@ public function __construct(ScopeResolverPool $scopeResolverPool) * Resolve scope code * * @param string $scopeType - * @param string $scopeCode + * @param string|null $scopeCode * @return string */ public function resolve($scopeType, $scopeCode) @@ -42,20 +43,25 @@ public function resolve($scopeType, $scopeCode) if (isset($this->resolvedScopeCodes[$scopeType][$scopeCode])) { return $this->resolvedScopeCodes[$scopeType][$scopeCode]; } - if (($scopeCode === null || is_numeric($scopeCode)) - && $scopeType !== ScopeConfigInterface::SCOPE_TYPE_DEFAULT - ) { + + if ($scopeType !== ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { $scopeResolver = $this->scopeResolverPool->get($scopeType); $resolverScopeCode = $scopeResolver->getScope($scopeCode); - } else { + } + else { $resolverScopeCode = $scopeCode; } - if ($resolverScopeCode instanceof \Magento\Framework\App\ScopeInterface) { + if ($resolverScopeCode instanceof ScopeInterface) { $resolverScopeCode = $resolverScopeCode->getCode(); } + if ($scopeCode == null) { + $scopeCode = $resolverScopeCode; + } + $this->resolvedScopeCodes[$scopeType][$scopeCode] = $resolverScopeCode; + return $resolverScopeCode; } From ca168091922bc4d34e2347304abb12e9f08a81f9 Mon Sep 17 00:00:00 2001 From: Matthew Muscat <matthew@mamis.com.au> Date: Fri, 20 Jul 2018 11:56:16 +1000 Subject: [PATCH 040/585] update travis-ci for phpcs static test --- .../Magento/Framework/App/Config/ScopeCodeResolver.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php b/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php index 8876f751f7c3d..ea26b736eca98 100644 --- a/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php +++ b/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php @@ -47,8 +47,7 @@ public function resolve($scopeType, $scopeCode) if ($scopeType !== ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { $scopeResolver = $this->scopeResolverPool->get($scopeType); $resolverScopeCode = $scopeResolver->getScope($scopeCode); - } - else { + } else { $resolverScopeCode = $scopeCode; } From 9e5fdbbb0edbaceea6d5a17607dea1a21205286c Mon Sep 17 00:00:00 2001 From: Matthew Muscat <matthew@mamis.com.au> Date: Fri, 20 Jul 2018 18:49:11 +1000 Subject: [PATCH 041/585] Update null conditional check --- lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php b/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php index ea26b736eca98..681af35944695 100644 --- a/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php +++ b/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php @@ -55,7 +55,7 @@ public function resolve($scopeType, $scopeCode) $resolverScopeCode = $resolverScopeCode->getCode(); } - if ($scopeCode == null) { + if ($scopeCode === null) { $scopeCode = $resolverScopeCode; } From e9de16a3a4b02505f146839976bd95d830552ca4 Mon Sep 17 00:00:00 2001 From: Yuliya Labudova <Yuliya_Labudova@epam.com> Date: Mon, 11 Mar 2019 13:48:43 +0300 Subject: [PATCH 042/585] MAGETWO-98522: Adding out of stock items to comparison shows success message but fails - Delete button if product is not available for comparison. --- .../Checker/AddToCompareAvailability.php | 59 +++++++++++++++++++ .../frontend/layout/catalog_product_view.xml | 6 +- .../product/view/addto/compare.phtml | 4 ++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php diff --git a/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php b/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php new file mode 100644 index 0000000000000..24fd03f023be2 --- /dev/null +++ b/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\ViewModel\Product\Checker; + +use Magento\Framework\View\Element\Block\ArgumentInterface; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\CatalogInventory\Api\StockConfigurationInterface; + +/** + * Check is available add to compare. + */ +class AddToCompareAvailability implements ArgumentInterface +{ + /** + * @var StockConfigurationInterface + */ + private $stockConfiguration; + + /** + * @param StockConfigurationInterface $stockConfiguration + */ + public function __construct(StockConfigurationInterface $stockConfiguration) + { + $this->stockConfiguration = $stockConfiguration; + } + + /** + * Is product available for comparison. + * + * @return bool + */ + public function isAvailableForCompare(ProductInterface $product): bool + { + return $this->isInStock($product) || + !$this->isInStock($product) && $this->stockConfiguration->isShowOutOfStock(); + } + + /** + * Get is in stock status. + * + * @return bool + */ + private function isInStock(ProductInterface $product): bool + { + $quantityAndStockStatus = $product->getQuantityAndStockStatus(); + if (!$quantityAndStockStatus) { + return $product->isSalable(); + } + + return isset($quantityAndStockStatus['is_in_stock']) + ? $quantityAndStockStatus['is_in_stock'] + : false; + } +} diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml index 8d3248896b434..1739b6da1f1d5 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml @@ -91,7 +91,11 @@ <container name="product.info.social" label="Product social links container" htmlTag="div" htmlClass="product-social-links"> <block class="Magento\Catalog\Block\Product\View" name="product.info.addto" as="addto" template="Magento_Catalog::product/view/addto.phtml"> <block class="Magento\Catalog\Block\Product\View\AddTo\Compare" name="view.addto.compare" after="view.addto.wishlist" - template="Magento_Catalog::product/view/addto/compare.phtml" /> + template="Magento_Catalog::product/view/addto/compare.phtml" > + <arguments> + <argument name="addToCompareViewModel" xsi:type="object">Magento\Catalog\ViewModel\Product\Checker\AddToCompareAvailability</argument> + </arguments> + </block> </block> <block class="Magento\Catalog\Block\Product\View" name="product.info.mailto" template="Magento_Catalog::product/view/mailto.phtml"/> </container> diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml index adf0f44d0c831..194a472d81d58 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml @@ -9,6 +9,10 @@ /** @var $block \Magento\Catalog\Block\Product\View\Addto\Compare */ ?> +<?php $viewModel = $block->getData('addToCompareViewModel'); ?> +<?php if ($viewModel->isAvailableForCompare($block->getProduct())): ?> <a href="#" data-post='<?= /* @escapeNotVerified */ $block->getPostDataParams() ?>' data-role="add-to-links" class="action tocompare"><span><?= /* @escapeNotVerified */ __('Add to Compare') ?></span></a> +<?php endif; ?> + From 5b79a3083130aa2e1bd1277b9bddca8cf7015f84 Mon Sep 17 00:00:00 2001 From: Matti Vapa <matti.vapa@piimega.fi> Date: Mon, 11 Mar 2019 13:06:00 +0200 Subject: [PATCH 043/585] Changed the order of the constructor arguments for the HTTP adapter so that the new request parameter is the last one. Made the request parameter optional with fallback to the ObjectManager. Changed the relevant unit test accordingly. This is to make the change backwards compatible. --- .../Test/Unit/Transfer/Adapter/HttpTest.php | 10 +++++----- .../Framework/File/Transfer/Adapter/Http.php | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php index 1ea47991d6df6..56375d5178820 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php @@ -34,16 +34,16 @@ class HttpTest extends \PHPUnit\Framework\TestCase */ protected function setUp() { - $this->request = $this->createPartialMock( - \Magento\Framework\App\Request\Http::class, - ['isHead'] - ); $this->response = $this->createPartialMock( \Magento\Framework\HTTP\PhpEnvironment\Response::class, ['setHeader', 'sendHeaders', 'setHeaders'] ); $this->mime = $this->createMock(\Magento\Framework\File\Mime::class); - $this->object = new Http($this->request, $this->response, $this->mime); + $this->request = $this->createPartialMock( + \Magento\Framework\App\Request\Http::class, + ['isHead'] + ); + $this->object = new Http($this->response, $this->mime, $this->request); } /** diff --git a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php index 74cc347fd2fa2..386ee0e5bb940 100644 --- a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php +++ b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php @@ -8,10 +8,6 @@ class Http { - /** - * @var \Magento\Framework\App\Request\Http - */ - private $request; /** * @var \Magento\Framework\HTTP\PhpEnvironment\Response @@ -24,18 +20,24 @@ class Http private $mime; /** - * @param \Magento\Framework\App\Request\Http $request + * @var \Magento\Framework\App\Request\Http + */ + private $request; + + /** * @param \Magento\Framework\App\Response\Http $response * @param \Magento\Framework\File\Mime $mime + * @param \Magento\Framework\App\Request\Http|null $request */ public function __construct( - \Magento\Framework\App\Request\Http $request, \Magento\Framework\HTTP\PhpEnvironment\Response $response, - \Magento\Framework\File\Mime $mime + \Magento\Framework\File\Mime $mime, + \Magento\Framework\App\Request\Http $request = null ) { - $this->request = $request; $this->response = $response; $this->mime = $mime; + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + $this->request = $request ?: $objectManager->get(\Magento\Framework\App\Request\Http::class); } /** From fc1434b3465a855cb952aae8b63cc886d6c1cce0 Mon Sep 17 00:00:00 2001 From: Jitheesh <jitheeshvo@gmail.com> Date: Tue, 12 Mar 2019 15:50:21 +0530 Subject: [PATCH 044/585] #21702 Purchasing a downloadable product as guest then creating an account on the onepagesuccess step doesn't link product with account - added order save event for update link purchased data --- .../Observer/UpdateLinkPurchasedObserver.php | 86 +++++++++++++++++++ app/code/Magento/Downloadable/etc/events.xml | 1 + 2 files changed, 87 insertions(+) create mode 100644 app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php diff --git a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php new file mode 100644 index 0000000000000..d9d743a052446 --- /dev/null +++ b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Downloadable\Observer; + +use Magento\Framework\Event\ObserverInterface; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class UpdateLinkPurchasedObserver implements ObserverInterface +{ + /** + * Core store config + * @var \Magento\Framework\App\Config\ScopeConfigInterface + */ + protected $_scopeConfig; + + /** + * @var \Magento\Downloadable\Model\ResourceModel\Link\Purchased\CollectionFactory + */ + protected $_purchasedFactory; + + /** + * @var \Magento\Framework\DataObject\Copy + */ + protected $_objectCopyService; + + /** + * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + * @param \Magento\Downloadable\Model\ResourceModel\Link\Purchased\CollectionFactory $purchasedFactory + * @param \Magento\Framework\DataObject\Copy $objectCopyService + */ + public function __construct( + \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, + \Magento\Downloadable\Model\ResourceModel\Link\Purchased\CollectionFactory $purchasedFactory, + \Magento\Framework\DataObject\Copy $objectCopyService + ) { + $this->_scopeConfig = $scopeConfig; + $this->_purchasedFactory = $purchasedFactory; + $this->_objectCopyService = $objectCopyService; + } + + /** + * re-save order data after order update + * @param \Magento\Framework\Event\Observer $observer + * @return $this|void + */ + public function execute(\Magento\Framework\Event\Observer $observer) + { + $order = $observer->getEvent()->getOrder(); + + if (!$order->getId()) { + //order not saved in the database + return $this; + } + + $purchasedLinks = $this->_createPurchasedCollection()->addFieldToFilter( + 'order_id', + ['eq' => $order->getId()] + ); + + foreach ($purchasedLinks as $linkPurchased) { + $this->_objectCopyService->copyFieldsetToTarget( + \downloadable_sales_copy_order::class, + 'to_downloadable', + $order, + $linkPurchased + ); + $linkPurchased->save(); + } + + return $this; + } + + /** + * @return \Magento\Downloadable\Model\ResourceModel\Link\Purchased\Collection + */ + protected function _createPurchasedCollection() + { + return $this->_purchasedFactory->create(); + } +} diff --git a/app/code/Magento/Downloadable/etc/events.xml b/app/code/Magento/Downloadable/etc/events.xml index 5a985fc33802e..21cc50ddc9669 100644 --- a/app/code/Magento/Downloadable/etc/events.xml +++ b/app/code/Magento/Downloadable/etc/events.xml @@ -11,6 +11,7 @@ </event> <event name="sales_order_save_after"> <observer name="downloadable_observer" instance="Magento\Downloadable\Observer\SetLinkStatusObserver" /> + <observer name="downloadable_observer_assign_customer" instance="Magento\Downloadable\Observer\UpdateLinkPurchasedObserver" /> </event> <event name="sales_model_service_quote_submit_success"> <observer name="checkout_type_onepage_save_order_after" instance="Magento\Downloadable\Observer\SetHasDownloadableProductsObserver" /> From 99d0496c1537d7279ca80ee3b9fd01b170b1646e Mon Sep 17 00:00:00 2001 From: Lilit Sargsyan <Lilit_Sargsyan@epam.com> Date: Thu, 14 Mar 2019 13:01:19 +0400 Subject: [PATCH 045/585] MAGETWO-98522: Adding out of stock items to comparison shows success message but fails - Added automated test script. --- .../AddOutOfStockProductToCompareListTest.xml | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml new file mode 100644 index 0000000000000..cc894dcc178aa --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AddOutOfStockProductToCompareListTest"> + <annotations> + <features value="Catalog"/> + <title value="Adding to compare list if a product is out of stock"/> + <description value="Adding to compare list if a product is out of stock"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-98644"/> + <useCaseId value="MAGETWO-98522"/> + <group value="Catalog"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="ApiCategory" stepKey="category"/> + <createData entity="SimpleOutOfStockProduct" stepKey="product"> + <requiredEntity createDataKey="category"/> + </createData> + </before> + <after> + <deleteData createDataKey="product" stepKey="deleteProduct"/> + <deleteData createDataKey="category" stepKey="deleteCategory"/> + <amOnPage url="{{AdminLogoutPage.url}}" stepKey="amOnLogoutPage"/> + </after> + + <!--Check 'out of stock' is turned off by default--> + <actionGroup ref="noDisplayOutOfStockProduct" stepKey="noDisplayOutOfStockProduct"/> + + <!--Open product page--> + <amOnPage url="$$product.name$$.html" stepKey="goToSimpleProductPage"/> + <waitForPageLoad stepKey="waitForSimpleProductPage"/> + + <!--'Add to compare' link is not available--> + <dontSeeElement selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="dontSeeAddToCompareLink"/> + + <!--Turn on 'out of stock' config--> + <actionGroup ref="displayOutOfStockProduct" stepKey="displayOutOfStockProduct"/> + + <!--Clear cache--> + <actionGroup ref="ClearCacheActionGroup" stepKey="clearCache" /> + + <!--Open product page--> + <amOnPage url="$$product.name$$.html" stepKey="goToSimpleProductPage2"/> + <waitForPageLoad stepKey="waitForSimpleProductPage2"/> + + <!--Click on 'Add to Compare' link--> + <click selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="clickOnAddToCompare"/> + + <!--See product in the comparison list--> + <amOnPage url="{{StorefrontProductComparePage.url}}" stepKey="navigateToComparePage"/> + <seeElement selector="{{StorefrontProductCompareMainSection.ProductLinkByName($product.name$)}}" stepKey="seeProductInCompareList"/> + </test> +</tests> From c785ff85bdaae04b7c735f5b85961f5acd72b1ef Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Thu, 14 Mar 2019 14:35:32 -0500 Subject: [PATCH 046/585] MC-4432: Convert ApplyConfigurableProductCatalogPriceRulesTest to MFTF --- .../CatalogPriceRuleActionGroup.xml | 24 ------------ ...itionWithAttributeAndOptionActionGroup.xml | 26 +++++++++++++ .../SelectNewCustomerGroupActionGroup.xml | 17 +++++++++ ...eRuleAppliedToProductOptionActionGroup.xml | 19 ++++++++++ ...riceInStorefrontProductPageActionGroup.xml | 20 ++++++++++ .../StorefrontCatalogPriceRuleActionGroup.xml | 30 --------------- ...eProductWithAssignedSimpleProductsTest.xml | 38 +++++++++---------- ...eForConfigurableProductWithOptionsTest.xml | 25 ++++++------ ...rableAndCustomOptionsToCartActionGroup.xml | 24 ++++++++++++ ...uctWithSelectedOptionToCartActionGroup.xml | 22 +++++++++++ .../StorefrontProductCartActionGroup.xml | 29 -------------- .../StorefrontCategoryActionGroup.xml | 11 ------ ...ableProductWithUpdatedPriceActionGroup.xml | 21 ++++++++++ 13 files changed, 178 insertions(+), 128 deletions(-) create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CreateCatalogPriceRuleConditionWithAttributeAndOptionActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SelectNewCustomerGroupActionGroup.xml create mode 100644 app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontAssertCatalogPriceRuleAppliedToProductOptionActionGroup.xml create mode 100644 app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontAssertUpdatedProductPriceInStorefrontProductPageActionGroup.xml delete mode 100644 app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontCatalogPriceRuleActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddProductWithSelectedConfigurableAndCustomOptionsToCartActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddProductWithSelectedOptionToCartActionGroup.xml create mode 100644 app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCheckCategoryConfigurableProductWithUpdatedPriceActionGroup.xml diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml index fd300dc90c7ec..788355ebf4aaa 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml @@ -70,23 +70,6 @@ <click selector="{{AdminNewCatalogPriceRule.fromDateButton}}" stepKey="clickFromCalender"/> <click selector="{{AdminNewCatalogPriceRule.todayDate}}" stepKey="clickFromToday"/> </actionGroup> - - <actionGroup name="CreateCatalogPriceRuleConditionWithAttributeAndOption"> - <arguments> - <argument name="attributeName" type="string"/> - <argument name="targetSelectValue" type="string"/> - <argument name="indexA" type="string"/> - <argument name="indexB" type="string"/> - </arguments> - <click selector="{{AdminNewCatalogPriceRule.conditionsTab}}" stepKey="openConditionsTab"/> - <waitForPageLoad stepKey="waitForConditionTabOpened"/> - <click selector="{{AdminNewCatalogPriceRuleConditions.newCondition}}" stepKey="addNewCondition"/> - <selectOption selector="{{AdminNewCatalogPriceRuleConditions.conditionSelect(indexA)}}" userInput="{{attributeName}}" stepKey="selectTypeCondition"/> - <waitForElement selector="{{AdminNewCatalogPriceRuleConditions.ellipsisValue(indexA)}}" stepKey="waitForTarget"/> - <click selector="{{AdminNewCatalogPriceRuleConditions.ellipsisValue(indexA)}}" stepKey="clickOnEllipsis"/> - <selectOption selector="{{AdminNewCatalogPriceRuleConditions.targetEllipsisSelect(indexA, indexB)}}" userInput="{{targetSelectValue}}" stepKey="selectOption"/> - </actionGroup> - <!-- Apply all of the saved catalog price rules --> <actionGroup name="applyCatalogPriceRules"> <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> @@ -132,11 +115,4 @@ <actionGroup name="selectNotLoggedInCustomerGroupActionGroup"> <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="NOT LOGGED IN" stepKey="selectCustomerGroup"/> </actionGroup> - - <actionGroup name="selectNewCustomerGroupActionGroup"> - <arguments> - <argument name="customerGroup" type="entity"/> - </arguments> - <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="{{customerGroup}}" stepKey="selectCustomerGroup"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CreateCatalogPriceRuleConditionWithAttributeAndOptionActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CreateCatalogPriceRuleConditionWithAttributeAndOptionActionGroup.xml new file mode 100644 index 0000000000000..41323b8f3b4dc --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CreateCatalogPriceRuleConditionWithAttributeAndOptionActionGroup.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="CreateCatalogPriceRuleConditionWithAttributeAndOptionActionGroup"> + <arguments> + <argument name="attributeName" type="string"/> + <argument name="targetSelectValue" type="string"/> + <argument name="indexA" type="string"/> + <argument name="indexB" type="string"/> + </arguments> + <click selector="{{AdminNewCatalogPriceRule.conditionsTab}}" stepKey="openConditionsTab"/> + <waitForPageLoad stepKey="waitForConditionTabOpened"/> + <click selector="{{AdminNewCatalogPriceRuleConditions.newCondition}}" stepKey="addNewCondition"/> + <selectOption selector="{{AdminNewCatalogPriceRuleConditions.conditionSelect(indexA)}}" userInput="{{attributeName}}" stepKey="selectTypeCondition"/> + <waitForElement selector="{{AdminNewCatalogPriceRuleConditions.ellipsisValue(indexA)}}" stepKey="waitForTarget"/> + <click selector="{{AdminNewCatalogPriceRuleConditions.ellipsisValue(indexA)}}" stepKey="clickOnEllipsis"/> + <selectOption selector="{{AdminNewCatalogPriceRuleConditions.targetEllipsisSelect(indexA, indexB)}}" userInput="{{targetSelectValue}}" stepKey="selectOption"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SelectNewCustomerGroupActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SelectNewCustomerGroupActionGroup.xml new file mode 100644 index 0000000000000..debaad705b64f --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SelectNewCustomerGroupActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="SelectNewCustomerGroupActionGroup"> + <arguments> + <argument name="customerGroup" type="entity"/> + </arguments> + <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="{{customerGroup}}" stepKey="selectCustomerGroup"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontAssertCatalogPriceRuleAppliedToProductOptionActionGroup.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontAssertCatalogPriceRuleAppliedToProductOptionActionGroup.xml new file mode 100644 index 0000000000000..4345d575a3320 --- /dev/null +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontAssertCatalogPriceRuleAppliedToProductOptionActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertCatalogPriceRuleAppliedToProductOptionActionGroup"> + <arguments> + <argument name="option" type="string"/> + <argument name="expectedPrice" type="string"/> + </arguments> + <selectOption userInput="{{option}}" selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" stepKey="selectOption"/> + <see userInput="{{expectedPrice}}" selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="seeProductPrice"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontAssertUpdatedProductPriceInStorefrontProductPageActionGroup.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontAssertUpdatedProductPriceInStorefrontProductPageActionGroup.xml new file mode 100644 index 0000000000000..56480583af7b4 --- /dev/null +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontAssertUpdatedProductPriceInStorefrontProductPageActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertUpdatedProductPriceInStorefrontProductPageActionGroup"> + <arguments> + <argument name="productName" type="string"/> + <argument name="expectedPrice" type="string"/> + </arguments> + <seeInTitle userInput="{{productName}}" stepKey="assertProductNameTitle"/> + <see userInput="{{productName}}" selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="assertProductName"/> + <see userInput="{{expectedPrice}}" selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="assertProductPrice"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontCatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontCatalogPriceRuleActionGroup.xml deleted file mode 100644 index 5eb6cf45f1e79..0000000000000 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/ActionGroup/StorefrontCatalogPriceRuleActionGroup.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="assertUpdatedProductPriceInStorefrontProductPage"> - <arguments> - <argument name="product" type="entity"/> - <argument name="expectedPrice" type="string"/> - </arguments> - <seeInTitle userInput="{{product.name}}" stepKey="assertProductNameTitle"/> - <see userInput="{{product.name}}" selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="assertProductName"/> - <see userInput="{{expectedPrice}}" selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="assertProductPrice"/> - <see userInput="{{product.sku}}" selector="{{StorefrontProductInfoMainSection.productSku}}" stepKey="assertProductSku"/> - </actionGroup> - - <actionGroup name="assertCatalogPriceRuleAppliedToProductOption"> - <arguments> - <argument name="option" type="string"/> - <argument name="expectedPrice" type="string"/> - </arguments> - <selectOption userInput="{{option}}" selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" stepKey="selectOption"/> - <see userInput="{{expectedPrice}}" selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="seeProductPrice"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml index 5409d2fe04c59..d614af31339fa 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml @@ -185,14 +185,16 @@ </actionGroup> <!-- Create price rule --> - <actionGroup ref="newCatalogPriceRuleByUI" stepKey="createFirstPriceRule"> + <actionGroup ref="newCatalogPriceRuleByUI" stepKey="createPriceRule"> <argument name="catalogRule" value="CatalogRuleToFixed"/> </actionGroup> - <actionGroup ref="selectNewCustomerGroupActionGroup" stepKey="adFirstCustomerGroup"> + <actionGroup ref="SelectNewCustomerGroupActionGroup" stepKey="addCustomerGroup"> <argument name="customerGroup" value="$$customerGroup.code$$"/> </actionGroup> - <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="clickSaveAndApplyRulesForFirst"/> - <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccessForFirst"/> + + <!-- Save price rule --> + <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="clickSaveAndApplyRule"/> + <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccessMessage"/> <!-- Run full reindex and clear caches --> <magentoCLI command="indexer:reindex" stepKey="reindex"/> @@ -206,39 +208,37 @@ <!-- Assert first product in category --> <amOnPage url="$$firstSimpleCategory.name$$.html" stepKey="goToFirstCategoryPageStorefront"/> <waitForPageLoad stepKey="waitForFirstCategoryPageLoad"/> - <actionGroup ref="StorefrontCheckCategoryConfigurableProductWithUpdatedPrice" stepKey="checkFirstProductPriceInCategory"> - <argument name="product" value="$$createFirstConfigProduct$$"/> + <actionGroup ref="StorefrontCheckCategoryConfigurableProductWithUpdatedPriceActionGroup" stepKey="checkFirstProductPriceInCategory"> + <argument name="productName" value="$$createFirstConfigProduct.name$$"/> <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> </actionGroup> <!-- Assert second product in category --> <amOnPage url="$$secondSimpleCategory.name$$.html" stepKey="goToSecondCategoryPageStorefront"/> <waitForPageLoad stepKey="waitForSecondCategoryPageLoad"/> - <actionGroup ref="StorefrontCheckCategoryConfigurableProductWithUpdatedPrice" stepKey="checkSecondProductPriceInCategory"> - <argument name="product" value="$$createSecondConfigProduct$$"/> + <actionGroup ref="StorefrontCheckCategoryConfigurableProductWithUpdatedPriceActionGroup" stepKey="checkSecondProductPriceInCategory"> + <argument name="productName" value="$$createSecondConfigProduct.name$$"/> <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> </actionGroup> <!-- Assert first product in storefront product page --> <amOnPage url="$$createFirstConfigProduct.custom_attributes[url_key]$$.html" stepKey="amOnFirstProductPage"/> <waitForPageLoad stepKey="waitForFirstProductPageLoad"/> - <actionGroup ref="assertUpdatedProductPriceInStorefrontProductPage" stepKey="checkFirstProductPriceInStorefrontProductPage"> - <argument name="product" value="$$createFirstConfigProduct$$"/> + <actionGroup ref="StorefrontAssertUpdatedProductPriceInStorefrontProductPageActionGroup" stepKey="checkFirstProductPriceInStorefrontProductPage"> + <argument name="productName" value="$$createFirstConfigProduct.name$$"/> <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> </actionGroup> <!-- Add first product with selected options to the cart --> - <actionGroup ref="StorefrontAddProductWithSelectedOptionsToCartActionGroup" stepKey="addFirstProductWithSelectedOptionsToCart1"> + <actionGroup ref="StorefrontAddProductWithSelectedConfigurableAndCustomOptionsToCartActionGroup" stepKey="addFirstProductWithSelectedOptionToCart1"> <argument name="product" value="$$createFirstConfigProduct$$"/> - <argument name="productCount" value="1"/> <argument name="option" value="$$createFirstConfigProductAttributeFirstOption.option[store_labels][1][label]$$"/> <argument name="customizableOption" value="{{ProductOptionValueRadioButtons1.title}}"/> </actionGroup> <grabTextFrom selector="{{StorefrontProductInfoMainSection.updatedPrice}}" stepKey="grabForthProductUpdatedPrice1"/> - <actionGroup ref="StorefrontAddProductWithSelectedOptionsToCartActionGroup" stepKey="addFirstProductWithSelectedOptionsToCart2"> + <actionGroup ref="StorefrontAddProductWithSelectedConfigurableAndCustomOptionsToCartActionGroup" stepKey="addFirstProductWithSelectedOptionToCart2"> <argument name="product" value="$$createFirstConfigProduct$$"/> - <argument name="productCount" value="1"/> <argument name="option" value="$$createFirstConfigProductAttributeSecondOption.option[store_labels][1][label]$$"/> <argument name="customizableOption" value="{{ProductOptionValueRadioButtons3.title}}"/> </actionGroup> @@ -246,22 +246,20 @@ <!-- Assert second product in storefront product page --> <amOnPage url="$$createSecondConfigProduct.custom_attributes[url_key]$$.html" stepKey="amOnSecondProductPage"/> <waitForPageLoad stepKey="waitForSecondProductPageLoad"/> - <actionGroup ref="assertUpdatedProductPriceInStorefrontProductPage" stepKey="checkSecondProductPriceInStorefrontProductPage"> - <argument name="product" value="$$createSecondConfigProduct$$"/> + <actionGroup ref="StorefrontAssertUpdatedProductPriceInStorefrontProductPageActionGroup" stepKey="checkSecondProductPriceInStorefrontProductPage"> + <argument name="productName" value="$$createSecondConfigProduct.name$$"/> <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> </actionGroup> <!-- Add second product with selected options to the cart --> - <actionGroup ref="StorefrontAddProductWithSelectedOptionsToCartActionGroup" stepKey="addSecondProductWithSelectedOptionsToCart1"> + <actionGroup ref="StorefrontAddProductWithSelectedConfigurableAndCustomOptionsToCartActionGroup" stepKey="addSecondProductWithSelectedOptionToCart1"> <argument name="product" value="$$createSecondConfigProduct$$"/> - <argument name="productCount" value="1"/> <argument name="option" value="$$createSecondConfigProductAttributeFirstOption.option[store_labels][1][label]$$"/> <argument name="customizableOption" value="{{ProductOptionValueRadioButtons1.title}}"/> </actionGroup> - <actionGroup ref="StorefrontAddProductWithSelectedOptionsToCartActionGroup" stepKey="addSecondProductWithSelectedOptionsToCart2"> + <actionGroup ref="StorefrontAddProductWithSelectedConfigurableAndCustomOptionsToCartActionGroup" stepKey="addSecondProductWithSelectedOptionToCart2"> <argument name="product" value="$$createSecondConfigProduct$$"/> - <argument name="productCount" value="1"/> <argument name="option" value="$$createSecondConfigProductAttributeSecondOption.option[store_labels][1][label]$$"/> <argument name="customizableOption" value="{{ProductOptionValueRadioButtons3.title}}"/> </actionGroup> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml index bf5a9b4c6c8dd..408e181aa1c87 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml @@ -127,7 +127,7 @@ <argument name="catalogRule" value="CatalogRuleToFixed"/> </actionGroup> <actionGroup ref="selectNotLoggedInCustomerGroup" stepKey="selectNotLoggedInCustomerGroupForFirstPriceRule"/> - <actionGroup ref="CreateCatalogPriceRuleConditionWithAttributeAndOption" stepKey="createFirstCatalogPriceRuleCondition"> + <actionGroup ref="CreateCatalogPriceRuleConditionWithAttributeAndOptionActionGroup" stepKey="createFirstCatalogPriceRuleCondition"> <argument name="attributeName" value="$$createConfigProductAttribute.attribute[frontend_labels][0][label]$$"/> <argument name="targetSelectValue" value="$$createConfigProductAttributeFirstOption.option[store_labels][1][label]$$"/> <argument name="indexA" value="1"/> @@ -141,7 +141,7 @@ <argument name="catalogRule" value="_defaultCatalogRule"/> </actionGroup> <actionGroup ref="selectNotLoggedInCustomerGroup" stepKey="selectNotLoggedInCustomerGroupForSecondPriceRule"/> - <actionGroup ref="CreateCatalogPriceRuleConditionWithAttributeAndOption" stepKey="createSecondCatalogPriceRuleCondition"> + <actionGroup ref="CreateCatalogPriceRuleConditionWithAttributeAndOptionActionGroup" stepKey="createSecondCatalogPriceRuleCondition"> <argument name="attributeName" value="$$createConfigProductAttribute.attribute[frontend_labels][0][label]$$"/> <argument name="targetSelectValue" value="$$createConfigProductAttributeSecondOption.option[store_labels][1][label]$$"/> <argument name="indexA" value="1"/> @@ -155,7 +155,7 @@ <argument name="catalogRule" value="CatalogRuleWithoutDiscount"/> </actionGroup> <actionGroup ref="selectNotLoggedInCustomerGroup" stepKey="selectNotLoggedInCustomerGroupForThirdPriceRule"/> - <actionGroup ref="CreateCatalogPriceRuleConditionWithAttributeAndOption" stepKey="createThirdCatalogPriceRuleCondition"> + <actionGroup ref="CreateCatalogPriceRuleConditionWithAttributeAndOptionActionGroup" stepKey="createThirdCatalogPriceRuleCondition"> <argument name="attributeName" value="$$createConfigProductAttribute.attribute[frontend_labels][0][label]$$"/> <argument name="targetSelectValue" value="$$createConfigProductAttributeThirdOption.option[store_labels][1][label]$$"/> <argument name="indexA" value="1"/> @@ -171,43 +171,40 @@ <!-- Assert product in storefront product page --> <amOnPage url="$$createConfigProduct.custom_attributes[url_key]$$.html" stepKey="amOnProductPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> - <actionGroup ref="assertUpdatedProductPriceInStorefrontProductPage" stepKey="assertUpdatedProductPriceInStorefrontProductPage"> - <argument name="product" value="$$createConfigProduct$$"/> + <actionGroup ref="StorefrontAssertUpdatedProductPriceInStorefrontProductPageActionGroup" stepKey="assertUpdatedProductPriceInStorefrontProductPage"> + <argument name="productName" value="$$createConfigProduct.name$$"/> <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> </actionGroup> <!-- Assert product options price in storefront product page --> - <actionGroup ref="assertCatalogPriceRuleAppliedToProductOption" stepKey="assertCatalogPriceRuleAppliedToFirstProductOption"> + <actionGroup ref="StorefrontAssertCatalogPriceRuleAppliedToProductOptionActionGroup" stepKey="assertCatalogPriceRuleAppliedToFirstProductOption"> <argument name="option" value="$$createConfigProductAttributeFirstOption.option[store_labels][1][label]$$"/> <argument name="expectedPrice" value="{{CatalogRuleToFixed.discount_amount}}"/> </actionGroup> - <actionGroup ref="assertCatalogPriceRuleAppliedToProductOption" stepKey="assertCatalogPriceRuleAppliedToSecondProductOption"> + <actionGroup ref="StorefrontAssertCatalogPriceRuleAppliedToProductOptionActionGroup" stepKey="assertCatalogPriceRuleAppliedToSecondProductOption"> <argument name="option" value="$$createConfigProductAttributeSecondOption.option[store_labels][1][label]$$"/> <argument name="expectedPrice" value="$110.70"/> </actionGroup> - <actionGroup ref="assertCatalogPriceRuleAppliedToProductOption" stepKey="assertCatalogPriceRuleAppliedToThirdProductOption"> + <actionGroup ref="StorefrontAssertCatalogPriceRuleAppliedToProductOptionActionGroup" stepKey="assertCatalogPriceRuleAppliedToThirdProductOption"> <argument name="option" value="$$createConfigProductAttributeThirdOption.option[store_labels][1][label]$$"/> <argument name="expectedPrice" value="{{ApiConfigurableProduct.price}}"/> </actionGroup> <!-- Add product with selected option to the cart --> - <actionGroup ref="StorefrontAddProductWithSelectedOptionToCartActionGroup" stepKey="addProductWithSelectedFirstOptionToCart"> + <actionGroup ref="StorefrontAddProductWithSelectedConfigurableOptionToCartActionGroup" stepKey="addProductWithSelectedFirstOptionToCart"> <argument name="product" value="$$createConfigProduct$$"/> - <argument name="productCount" value="1"/> <argument name="option" value="$$createConfigProductAttributeFirstOption.option[store_labels][1][label]$$"/> </actionGroup> - <actionGroup ref="StorefrontAddProductWithSelectedOptionToCartActionGroup" stepKey="addProductWithSelectedSecondOptionToCart"> + <actionGroup ref="StorefrontAddProductWithSelectedConfigurableOptionToCartActionGroup" stepKey="addProductWithSelectedSecondOptionToCart"> <argument name="product" value="$$createConfigProduct$$"/> - <argument name="productCount" value="1"/> <argument name="option" value="$$createConfigProductAttributeSecondOption.option[store_labels][1][label]$$"/> </actionGroup> - <actionGroup ref="StorefrontAddProductWithSelectedOptionToCartActionGroup" stepKey="addProductWithSelectedThirdOptionToCart"> + <actionGroup ref="StorefrontAddProductWithSelectedConfigurableOptionToCartActionGroup" stepKey="addProductWithSelectedThirdOptionToCart"> <argument name="product" value="$$createConfigProduct$$"/> - <argument name="productCount" value="1"/> <argument name="option" value="$$createConfigProductAttributeThirdOption.option[store_labels][1][label]$$"/> </actionGroup> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddProductWithSelectedConfigurableAndCustomOptionsToCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddProductWithSelectedConfigurableAndCustomOptionsToCartActionGroup.xml new file mode 100644 index 0000000000000..8e13748d64e0e --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddProductWithSelectedConfigurableAndCustomOptionsToCartActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Add product with selected configurable option and customizable option to cart from the product page --> + <actionGroup name="StorefrontAddProductWithSelectedConfigurableAndCustomOptionsToCartActionGroup"> + <arguments> + <argument name="product" type="entity"/> + <argument name="option" type="string"/> + <argument name="customizableOption" type="string"/> + </arguments> + <selectOption userInput="{{option}}" selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" stepKey="selectOption"/> + <click selector="{{StorefrontProductInfoMainSection.selectCustomOptionByName(customizableOption)}}" stepKey="selectCustomOption"/> + <click selector="{{StorefrontProductInfoMainSection.AddToCart}}" stepKey="clickAddToCart"/> + <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" stepKey="waitForSuccessMessage"/> + <see selector="{{StorefrontProductPageSection.messagesBlock}}" userInput="You added {{product.name}} to your shopping cart." stepKey="assertSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddProductWithSelectedOptionToCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddProductWithSelectedOptionToCartActionGroup.xml new file mode 100644 index 0000000000000..5d844523d4454 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddProductWithSelectedOptionToCartActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Add product with selected option to Cart from the product page --> + <actionGroup name="StorefrontAddProductWithSelectedConfigurableOptionToCartActionGroup"> + <arguments> + <argument name="product" type="entity"/> + <argument name="option" type="string"/> + </arguments> + <selectOption userInput="{{option}}" selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" stepKey="selectOption"/> + <click selector="{{StorefrontProductInfoMainSection.AddToCart}}" stepKey="clickAddToCart"/> + <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" stepKey="waitForSuccessMessage"/> + <see selector="{{StorefrontProductPageSection.messagesBlock}}" userInput="You added {{product.name}} to your shopping cart." stepKey="assertSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontProductCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontProductCartActionGroup.xml index 371658748eec7..fb3f295836161 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontProductCartActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontProductCartActionGroup.xml @@ -53,35 +53,6 @@ <seeLink stepKey="assertLinkToShoppingCart" url="{{_ENV.MAGENTO_BASE_URL}}checkout/cart/" userInput="shopping cart" /> <waitForText userInput="{{productCount}}" selector="{{StorefrontMinicartSection.productCount}}" time="30" stepKey="assertProductCount"/> </actionGroup> - - <!-- Add product with selected option to Cart from the product page --> - <actionGroup name="StorefrontAddProductWithSelectedOptionToCartActionGroup"> - <arguments> - <argument name="product" type="entity"/> - <argument name="productCount" type="string"/> - <argument name="option" type="string"/> - </arguments> - <selectOption userInput="{{option}}" selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" stepKey="selectOption"/> - <click selector="{{StorefrontProductInfoMainSection.AddToCart}}" stepKey="clickAddToCart"/> - <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" stepKey="waitForSuccessMessage"/> - <see selector="{{StorefrontProductPageSection.messagesBlock}}" userInput="You added {{product.name}} to your shopping cart." stepKey="assertSuccessMessage"/> - </actionGroup> - - <!-- Add product with selected configurable option and customizable option to cart from the product page --> - <actionGroup name="StorefrontAddProductWithSelectedOptionsToCartActionGroup"> - <arguments> - <argument name="product" type="entity"/> - <argument name="productCount" type="string"/> - <argument name="option" type="string"/> - <argument name="customizableOption" type="string"/> - </arguments> - <selectOption userInput="{{option}}" selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" stepKey="selectOption"/> - <click selector="{{StorefrontProductInfoMainSection.selectCustomOptionByName(customizableOption)}}" stepKey="selectCustomOption"/> - <click selector="{{StorefrontProductInfoMainSection.AddToCart}}" stepKey="clickAddToCart"/> - <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" stepKey="waitForSuccessMessage"/> - <see selector="{{StorefrontProductPageSection.messagesBlock}}" userInput="You added {{product.name}} to your shopping cart." stepKey="assertSuccessMessage"/> - </actionGroup> - <!-- Open the Minicart and check Simple Product --> <actionGroup name="StorefrontOpenMinicartAndCheckSimpleProductActionGroup"> <arguments> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml index 845fa64ad3d12..e2759fc0fd23d 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml @@ -32,15 +32,4 @@ <seeElement selector="{{StorefrontCategoryProductSection.ProductStockUnavailable}}" stepKey="AssertOutOfStock"/> <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductAddToCartByName(product.name)}}" stepKey="AssertAddToCart" /> </actionGroup> - - <actionGroup name="StorefrontCheckCategoryConfigurableProductWithUpdatedPrice"> - <arguments> - <argument name="product" type="entity"/> - <argument name="expectedPrice" type="string"/> - </arguments> - <seeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName(product.name)}}" stepKey="assertProductName"/> - <see userInput="{{expectedPrice}}" selector="{{StorefrontCategoryProductSection.ProductPriceByName(product.name)}}" stepKey="AssertProductPrice"/> - <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName(product.name)}}" stepKey="moveMouseOverProduct" /> - <seeElement selector="{{StorefrontCategoryProductSection.ProductAddToCartByName(product.name)}}" stepKey="AssertAddToCart" /> - </actionGroup> </actionGroups> \ No newline at end of file diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCheckCategoryConfigurableProductWithUpdatedPriceActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCheckCategoryConfigurableProductWithUpdatedPriceActionGroup.xml new file mode 100644 index 0000000000000..5d5e37ecce4ef --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontCheckCategoryConfigurableProductWithUpdatedPriceActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontCheckCategoryConfigurableProductWithUpdatedPriceActionGroup"> + <arguments> + <argument name="productName" type="string"/> + <argument name="expectedPrice" type="string"/> + </arguments> + <seeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName(productName)}}" stepKey="assertProductName"/> + <see userInput="{{expectedPrice}}" selector="{{StorefrontCategoryProductSection.ProductPriceByName(productName)}}" stepKey="AssertProductPrice"/> + <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName(productName)}}" stepKey="moveMouseOverProduct"/> + <seeElement selector="{{StorefrontCategoryProductSection.ProductAddToCartByName(productName)}}" stepKey="AssertAddToCart"/> + </actionGroup> +</actionGroups> From 1b46c966d416ec27ca0891be654b69d7345da2d6 Mon Sep 17 00:00:00 2001 From: Ian Coast <icoast@crimsonagility.com> Date: Thu, 14 Mar 2019 13:56:07 -0700 Subject: [PATCH 047/585] Fixes bug when many requests to a page are made and multiple streams request to build the same merged css or js file sometimes results in serving incomplete files to the client if a second request came in and truncated the part of the work from the first request. --- .../View/Asset/MergeStrategy/Direct.php | 16 ++++++--- .../Unit/Asset/MergeStrategy/DirectTest.php | 33 +++++++++++++++---- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php index 1e8eb74bf5414..57674bf2fbe58 100644 --- a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php +++ b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php @@ -30,16 +30,23 @@ class Direct implements \Magento\Framework\View\Asset\MergeStrategyInterface */ private $cssUrlResolver; + /** + * @var \Magento\Framework\Math\Random + */ + protected $mathRandom; + /** * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\Url\CssResolver $cssUrlResolver */ public function __construct( \Magento\Framework\Filesystem $filesystem, - \Magento\Framework\View\Url\CssResolver $cssUrlResolver + \Magento\Framework\View\Url\CssResolver $cssUrlResolver, + \Magento\Framework\Math\Random $mathRandom ) { $this->filesystem = $filesystem; $this->cssUrlResolver = $cssUrlResolver; + $this->mathRandom = $mathRandom; } /** @@ -49,17 +56,18 @@ public function merge(array $assetsToMerge, Asset\LocalInterface $resultAsset) { $mergedContent = $this->composeMergedContent($assetsToMerge, $resultAsset); $filePath = $resultAsset->getPath(); + $tmpFilePath = $filePath . $this->mathRandom->getUniqueHash('_'); $staticDir = $this->filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW); $tmpDir = $this->filesystem->getDirectoryWrite(DirectoryList::TMP); - $tmpDir->writeFile($filePath, $mergedContent); - $tmpDir->renameFile($filePath, $filePath, $staticDir); + $tmpDir->writeFile($tmpFilePath, $mergedContent); + $tmpDir->renameFile($tmpFilePath, $filePath, $staticDir); } /** * Merge files together and modify content if needed * * @param \Magento\Framework\View\Asset\MergeableInterface[] $assetsToMerge - * @param \Magento\Framework\View\Asset\LocalInterface $resultAsset + * @param \Magento\ Framework\View\Asset\LocalInterface $resultAsset * @return string * @throws \Magento\Framework\Exception\LocalizedException */ diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php index 823ad5c8c8be7..19b17b4b52596 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php @@ -12,6 +12,10 @@ class DirectTest extends \PHPUnit\Framework\TestCase { + /** + * @var \Magento\Framework\Math\Random|\PHPUnit_Framework_MockObject_MockObject + */ + protected $mathRandomMock; /** * @var \Magento\Framework\View\Asset\MergeStrategy\Direct */ @@ -50,30 +54,42 @@ protected function setUp() [DirectoryList::TMP, \Magento\Framework\Filesystem\DriverPool::FILE, $this->tmpDir], ]); $this->resultAsset = $this->createMock(\Magento\Framework\View\Asset\File::class); - $this->object = new Direct($filesystem, $this->cssUrlResolver); + $this->mathRandomMock = $this->getMockBuilder(\Magento\Framework\Math\Random::class) + ->disableOriginalConstructor() + ->getMock(); + $this->object = new Direct($filesystem, $this->cssUrlResolver, $this->mathRandomMock); } public function testMergeNoAssets() { + $uniqId = '_b3bf82fa6e140594420fa90982a8e877'; $this->resultAsset->expects($this->once())->method('getPath')->will($this->returnValue('foo/result')); $this->staticDir->expects($this->never())->method('writeFile'); - $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result', ''); - $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result', 'foo/result', $this->staticDir); + $this->mathRandomMock->expects($this->once()) + ->method('getUniqueHash') + ->willReturn($uniqId); + $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, ''); + $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); $this->object->merge([], $this->resultAsset); } public function testMergeGeneric() { + $uniqId = '_be50ccf992fd81818c1a2645d1a29e92'; $this->resultAsset->expects($this->once())->method('getPath')->will($this->returnValue('foo/result')); $assets = $this->prepareAssetsToMerge([' one', 'two']); // note leading space intentionally $this->staticDir->expects($this->never())->method('writeFile'); - $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result', 'onetwo'); - $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result', 'foo/result', $this->staticDir); + $this->mathRandomMock->expects($this->once()) + ->method('getUniqueHash') + ->willReturn($uniqId); + $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, 'onetwo'); + $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); $this->object->merge($assets, $this->resultAsset); } public function testMergeCss() { + $uniqId = '_f929c374767e00712449660ea673f2f5'; $this->resultAsset->expects($this->exactly(3)) ->method('getPath') ->will($this->returnValue('foo/result')); @@ -86,9 +102,12 @@ public function testMergeCss() ->method('aggregateImportDirectives') ->with('12') ->will($this->returnValue('1020')); + $this->mathRandomMock->expects($this->once()) + ->method('getUniqueHash') + ->willReturn($uniqId); $this->staticDir->expects($this->never())->method('writeFile'); - $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result', '1020'); - $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result', 'foo/result', $this->staticDir); + $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, '1020'); + $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); $this->object->merge($assets, $this->resultAsset); } From 321816680860cc7b9f1ef50e7a136e5a3a53af21 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 15 Mar 2019 14:16:16 +0200 Subject: [PATCH 048/585] MC-15404: Stabilize AdminAbleToShipPartiallyInvoicedItemsTest --- .../order/creditmemo/create/items.phtml | 69 +++++++++++-------- .../order/invoice/create/items.phtml | 51 +++++++------- 2 files changed, 67 insertions(+), 53 deletions(-) diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml index fcf4ccad7060b..ba4af32ff69b2 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml @@ -136,67 +136,76 @@ </section> <script> -require(['jquery', 'prototype'], function(jQuery){ +require(['jquery'], function(jQuery){ //<![CDATA[ -var submitButtons = $$('.submit-button'); -var updateButtons = $$('.update-button'); -var fields = $$('.qty-input'); +var submitButtons = jQuery('.submit-button'); +var updateButtons = jQuery('.update-button'); +var fields = jQuery('.qty-input'); -updateButtons.each(function (elem) {elem.disabled=true;elem.addClassName('disabled');}); +function enableButtons(buttons) { + buttons.removeClass('disabled').prop('disabled', false); +} -for(var i=0;i<fields.length;i++){ - fields[i].observe('change', checkButtonsRelation) - fields[i].baseValue = fields[i].value; +function disableButtons(buttons) { + buttons.addClass('disabled').prop('disabled', true); } +disableButtons(updateButtons); + +fields.on('change', checkButtonsRelation); +fields.each(function (i, elem) { + elem.baseValue = elem.value; +}); + function checkButtonsRelation() { var hasChanges = false; - fields.each(function (elem) { + fields.each(function (i, elem) { if (elem.baseValue != elem.value) { hasChanges = true; } }.bind(this)); if (hasChanges) { - submitButtons.each(function (elem) {elem.disabled=true;elem.addClassName('disabled');}); - updateButtons.each(function (elem) {elem.disabled=false;elem.removeClassName('disabled');}); + disableButtons(submitButtons); + enableButtons(updateButtons); } else { - submitButtons.each(function (elem) {elem.disabled=false;elem.removeClassName('disabled');}); - updateButtons.each(function (elem) {elem.disabled=true;elem.addClassName('disabled');}); + enableButtons(submitButtons); + disableButtons(updateButtons); } } submitCreditMemo = function() { - if ($('creditmemo_do_offline')) $('creditmemo_do_offline').value=0; + var creditMemoOffline = jQuery('#creditmemo_do_offline'); + if (creditMemoOffline.length) { + creditMemoOffline.prop('value', 0); + } // Temporary solution will be replaced after refactoring order functionality jQuery('#edit_form').triggerHandler('save'); -} +}; submitCreditMemoOffline = function() { - if ($('creditmemo_do_offline')) $('creditmemo_do_offline').value=1; + var creditMemoOffline = jQuery('#creditmemo_do_offline'); + if (creditMemoOffline.length) { + creditMemoOffline.prop('value', 1); + } // Temporary solution will be replaced after refactoring order functionality jQuery('#edit_form').triggerHandler('save'); -} - -var sendEmailCheckbox = $('send_email'); +}; -if (sendEmailCheckbox) { - var notifyCustomerCheckbox = $('notify_customer'); - var creditmemoCommentText = $('creditmemo_comment_text'); - Event.observe(sendEmailCheckbox, 'change', bindSendEmail); +var sendEmailCheckbox = jQuery('#send_email'); +if (sendEmailCheckbox.length) { + var notifyCustomerCheckbox = jQuery('#notify_customer'); + sendEmailCheckbox.on('change', bindSendEmail); bindSendEmail(); } -function bindSendEmail() -{ - if (sendEmailCheckbox.checked == true) { - notifyCustomerCheckbox.disabled = false; - //creditmemoCommentText.disabled = false; +function bindSendEmail() { + if (sendEmailCheckbox.prop('checked') == true) { + notifyCustomerCheckbox.prop('disabled', false); } else { - notifyCustomerCheckbox.disabled = true; - //creditmemoCommentText.disabled = true; + notifyCustomerCheckbox.prop('disabled', true); } } diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml index 4a77c3b166de9..872be35cff206 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml @@ -134,56 +134,61 @@ </section> <script> -require(['jquery', 'prototype'], function(jQuery){ +require(['jquery'], function(jQuery){ //<![CDATA[ -var submitButtons = $$('.submit-button'); -var updateButtons = $$('.update-button'); +var submitButtons = jQuery('.submit-button'); +var updateButtons = jQuery('.update-button'); var enableSubmitButtons = <?= (int) !$block->getDisableSubmitButton() ?>; -var fields = $$('.qty-input'); +var fields = jQuery('.qty-input'); -updateButtons.each(function (elem) {elem.disabled=true;elem.addClassName('disabled');}); +function enableButtons(buttons) { + buttons.removeClass('disabled').prop('disabled', false); +} -for(var i=0;i<fields.length;i++){ - jQuery(fields[i]).on('keyup', checkButtonsRelation); - fields[i].baseValue = fields[i].value; +function disableButtons(buttons) { + buttons.addClass('disabled').prop('disabled', true); } +disableButtons(updateButtons); + +fields.on('keyup', checkButtonsRelation); +fields.each(function (i, elem) { + elem.baseValue = elem.value; +}); + function checkButtonsRelation() { var hasChanges = false; - fields.each(function (elem) { + fields.each(function (i, elem) { if (elem.baseValue != elem.value) { hasChanges = true; } }.bind(this)); if (hasChanges) { - submitButtons.each(function (elem) {elem.disabled=true;elem.addClassName('disabled');}); - updateButtons.each(function (elem) {elem.disabled=false;elem.removeClassName('disabled');}); + disableButtons(submitButtons); + enableButtons(updateButtons); } else { if (enableSubmitButtons) { - submitButtons.each(function (elem) {elem.disabled=false;elem.removeClassName('disabled');}); + enableButtons(submitButtons); } - updateButtons.each(function (elem) {elem.disabled=true;elem.addClassName('disabled');}); + disableButtons(updateButtons); } } -var sendEmailCheckbox = $('send_email'); -if (sendEmailCheckbox) { - var notifyCustomerCheckbox = $('notify_customer'); - var invoiceCommentText = $('invoice_comment_text'); - Event.observe(sendEmailCheckbox, 'change', bindSendEmail); +var sendEmailCheckbox = jQuery('#send_email'); +if (sendEmailCheckbox.length) { + var notifyCustomerCheckbox = jQuery('#notify_customer'); + sendEmailCheckbox.on('change', bindSendEmail); bindSendEmail(); } function bindSendEmail() { - if (sendEmailCheckbox.checked == true) { - notifyCustomerCheckbox.disabled = false; - //invoiceCommentText.disabled = false; + if (sendEmailCheckbox.prop('checked') == true) { + notifyCustomerCheckbox.prop('disabled', false); } else { - notifyCustomerCheckbox.disabled = true; - //invoiceCommentText.disabled = true; + notifyCustomerCheckbox.prop('disabled', true); } } From dc3bdb8e2e3dc2b111c4174da2f523e3764f9b71 Mon Sep 17 00:00:00 2001 From: stkec <skechedji@gmail.com> Date: Fri, 15 Mar 2019 15:02:13 +0200 Subject: [PATCH 049/585] Make sure Yes/No attribute Layered Navigation filter will be joined from index table --- .../CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php | 2 +- .../CatalogSearch/Model/Search/CustomAttributeFilterCheck.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php index 2ffa63098cdee..51eb2077b80ea 100644 --- a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php +++ b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php @@ -170,7 +170,7 @@ private function processQueryWithField(FilterInterface $filter, $isNegation, $qu } elseif ($filter->getField() === VisibilityFilter::VISIBILITY_FILTER_FIELD) { return ''; } elseif ($filter->getType() === FilterInterface::TYPE_TERM && - in_array($attribute->getFrontendInput(), ['select', 'multiselect'], true) + in_array($attribute->getFrontendInput(), ['select', 'multiselect', 'boolean'], true) ) { $resultQuery = $this->processTermSelect($filter, $isNegation); } elseif ($filter->getType() === FilterInterface::TYPE_RANGE && diff --git a/app/code/Magento/CatalogSearch/Model/Search/CustomAttributeFilterCheck.php b/app/code/Magento/CatalogSearch/Model/Search/CustomAttributeFilterCheck.php index bcd4080b30b14..657c8540d7c68 100644 --- a/app/code/Magento/CatalogSearch/Model/Search/CustomAttributeFilterCheck.php +++ b/app/code/Magento/CatalogSearch/Model/Search/CustomAttributeFilterCheck.php @@ -44,7 +44,7 @@ public function isCustom(FilterInterface $filter) return $attribute && $filter->getType() === FilterInterface::TYPE_TERM - && in_array($attribute->getFrontendInput(), ['select', 'multiselect'], true); + && in_array($attribute->getFrontendInput(), ['select', 'multiselect', 'boolean'], true); } /** From 730c576c88ee8da80f277d469a3b4f0d0451aba4 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 15 Mar 2019 15:05:43 +0200 Subject: [PATCH 050/585] MC-15406: [FT] [MFTF] StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest fails because of bad design --- ...ctCustomOptionsDifferentStoreViewsTest.xml | 89 ++++++++++--------- .../Mftf/ActionGroup/CheckoutActionGroup.xml | 2 +- .../AdminCreateStoreViewActionGroup.xml | 4 +- .../AdminSwitchStoreViewActionGroup.xml | 1 + 4 files changed, 53 insertions(+), 43 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml index df4803bcd7906..91b6766169b91 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml @@ -52,10 +52,6 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <!-- Reset Product filter --> - - <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductsFilter"/> - <!-- Delete Store View EN --> <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView1"> @@ -67,6 +63,12 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView2"> <argument name="customStore" value="customStoreFR"/> </actionGroup> + <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearWebsitesGridFilters"/> + + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilter"/> + + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearProductsGridFilters"/> </after> <!-- Open Product Grid, Filter product and open --> @@ -78,8 +80,9 @@ <argument name="product" value="_defaultProduct"/> </actionGroup> - <click selector="{{AdminProductGridSection.productGridXRowYColumnButton('1', '2')}}" stepKey="openProductForEdit"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad2"/> + <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProductPage"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> <!-- Update Product with Option Value DropDown 1--> <conditionalClick selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.checkIfCustomizableOptionsTabOpen}}" visible="true" stepKey="clickIfContentTabCloses2"/> @@ -101,15 +104,12 @@ <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSaveButton1"/> <!-- Switcher to Store FR--> - <scrollToTopOfPage stepKey="scrollToTopOfPage1"/> - - <click selector="{{AdminProductFormActionSection.changeStoreButton}}" stepKey="clickStoreSwitcher"/> - <click selector="{{AdminProductFormActionSection.selectStoreView(customStoreFR.name)}}" stepKey="clickStoreView"/> - <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="acceptMessage"/> + <actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="switchToStoreFR"> + <argument name="storeView" value="customStoreFR.name"/> + </actionGroup> <!-- Open tab Customizable Options --> - <waitForPageLoad time="10" stepKey="waitForPageLoad4"/> <conditionalClick selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.checkIfCustomizableOptionsTabOpen}}" visible="true" stepKey="clickIfContentTabCloses3"/> <!-- Update Option Customizable Options and Option Value 1--> @@ -129,11 +129,9 @@ <!-- Login Customer Storefront --> - <amOnPage url="{{StorefrontCustomerSignInPage.url}}" stepKey="amOnSignInPage"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad6"/> - <fillField userInput="$$createCustomer.email$$" selector="{{StorefrontCustomerSignInFormSection.emailField}}" stepKey="fillEmail"/> - <fillField userInput="$$createCustomer.password$$" selector="{{StorefrontCustomerSignInFormSection.passwordField}}" stepKey="fillPassword"/> - <click selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" stepKey="clickSignInAccountButton"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> + <argument name="Customer" value="$$createCustomer$$" /> + </actionGroup> <!-- Go to Product Page --> @@ -176,24 +174,29 @@ <conditionalClick selector="{{CheckoutPaymentSection.productOptionsByProductItemPrice('150')}}" dependentSelector="{{CheckoutPaymentSection.productOptionsActiveByProductItemPrice('150')}}" visible="false" stepKey="exposeProductOptions1"/> <see selector="{{CheckoutPaymentSection.productOptionsActiveByProductItemPrice('150')}}" userInput="option2" stepKey="seeProductOptionValueDropdown1Input2"/> - <click selector="{{CheckoutShippingSection.next}}" stepKey="clickNext"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad8"/> <!-- Place Order --> - <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyOrder1"/> - <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder"/> + <!--Select shipping method--> + <actionGroup ref="CheckoutSelectFlatRateShippingMethodActionGroup" stepKey="selectFlatRateShippingMethod"/> + <waitForElementVisible selector="{{CheckoutShippingSection.next}}" time="30" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingSection.next}}" stepKey="clickNext"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskAfterClickNext"/> + <!--Select payment method--> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectPaymentMethod"/> + <!-- Place Order --> + <actionGroup ref="CheckoutPlaceOrderActionGroup" stepKey="customerPlaceOrder"> + <argument name="orderNumberMessage" value="CONST.successCheckoutOrderNumberMessage"/> + <argument name="emailYouMessage" value="CONST.successCheckoutEmailYouMessage"/> + </actionGroup> <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> <!-- Open Order --> - <amOnPage url="{{AdminOrdersPage.url}}" stepKey="onOrdersPage"/> - <waitForPageLoad stepKey="waitForPageLoadOrdersPage"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearFilters" /> - <fillField selector="{{AdminOrdersGridSection.search}}" userInput="{$grabOrderNumber}" stepKey="fillOrderNum"/> - <click selector="{{AdminOrdersGridSection.submitSearch}}" stepKey="submitSearchOrderNum"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappearOnSearch"/> + <actionGroup ref="filterOrderGridById" stepKey="openOrdersGrid"> + <argument name="orderId" value="{$grabOrderNumber}"/> + </actionGroup> <click selector="{{AdminOrdersGridSection.firstRow}}" stepKey="clickOrderRow"/> <waitForPageLoad time="30" stepKey="waitForPageLoad10"/> @@ -205,14 +208,12 @@ <!-- Switch to FR Store View Storefront --> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnProduct4Page"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad11"/> - <click selector="{{StorefrontHeaderSection.storeViewSwitcher}}" stepKey="clickStoreViewSwitcher1"/> - <waitForElementVisible selector="{{StorefrontHeaderSection.storeViewDropdown}}" stepKey="waitForStoreViewDropdown1"/> - <click selector="{{StorefrontHeaderSection.storeViewOption(customStoreFR.code)}}" stepKey="selectStoreView1"/> - <waitForPageLoad stepKey="waitForPageLoad12"/> - <amOnPage url="{{StorefrontHomePage.url}}$$createProduct.custom_attributes[url_key]$$.html" stepKey="amOnProduct2Page"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad13"/> + <actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="switchStore"> + <argument name="storeView" value="customStoreFR"/> + </actionGroup> + + <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="amOnProduct2Page"/> <seeElement selector="{{StorefrontProductInfoMainSection.productOptionDropDownTitle('FR Custom Options 1')}}" stepKey="seeProductFrOptionDropDownTitle"/> <seeElement selector="{{StorefrontProductInfoMainSection.productOptionDropDownOptionTitle('FR Custom Options 1', 'FR option1')}}" stepKey="productFrOptionDropDownOptionTitle1"/> @@ -250,13 +251,22 @@ <conditionalClick selector="{{CheckoutPaymentSection.productOptionsByProductItemPrice('150')}}" dependentSelector="{{CheckoutPaymentSection.productOptionsActiveByProductItemPrice('150')}}" visible="false" stepKey="exposeProductOptions3"/> <see selector="{{CheckoutPaymentSection.productOptionsActiveByProductItemPrice('150')}}" userInput="FR option2" stepKey="seeProductFrOptionValueDropdown1Input3"/> - <click selector="{{CheckoutShippingSection.next}}" stepKey="clickNext1"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad14"/> <!-- Place Order --> - <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyOrder2"/> - <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder1"/> + <!--Select shipping method--> + <actionGroup ref="CheckoutSelectFlatRateShippingMethodActionGroup" stepKey="selectFlatRateShippingMethod2"/> + <waitForElementVisible selector="{{CheckoutShippingSection.next}}" time="30" stepKey="waitForNextButton2"/> + <click selector="{{CheckoutShippingSection.next}}" stepKey="clickNext2"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskAfterClickNext2"/> + + <!--Select payment method--> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectPaymentMethod2"/> + <!-- Place Order --> + <actionGroup ref="CheckoutPlaceOrderActionGroup" stepKey="customerPlaceOrder2"> + <argument name="orderNumberMessage" value="CONST.successCheckoutOrderNumberMessage"/> + <argument name="emailYouMessage" value="CONST.successCheckoutEmailYouMessage"/> + </actionGroup> <!-- Open Product Grid, Filter product and open --> @@ -296,8 +306,7 @@ <!--Go to Product Page--> - <amOnPage url="{{StorefrontHomePage.url}}$$createProduct.custom_attributes[url_key]$$.html" stepKey="amOnProduct2Page2"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad20"/> + <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="amOnProduct2Page2"/> <seeElement selector="{{StorefrontProductInfoMainSection.productOptionDropDownTitle('Custom Options 1')}}" stepKey="seeProductOptionDropDownTitle1"/> <seeElement selector="{{StorefrontProductInfoMainSection.productOptionDropDownOptionTitle('Custom Options 1', 'option1')}}" stepKey="seeProductOptionDropDownOptionTitle3"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml index b67b7451d5968..7ddecf94a2e39 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml @@ -263,7 +263,7 @@ <argument name="orderNumberMessage"/> <argument name="emailYouMessage"/> </arguments> - <waitForElement selector="{{CheckoutPaymentSection.placeOrder}}" time="30" stepKey="waitForPlaceOrderButton"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.placeOrder}}" time="30" stepKey="waitForPlaceOrderButton"/> <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder"/> <see selector="{{CheckoutSuccessMainSection.success}}" userInput="{{orderNumberMessage}}" stepKey="seeOrderNumber"/> <see selector="{{CheckoutSuccessMainSection.success}}" userInput="{{emailYouMessage}}" stepKey="seeEmailYou"/> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml index 9b942109785d4..45b44b2d82f38 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml @@ -25,8 +25,8 @@ <waitForElementVisible selector="{{AdminConfirmationModalSection.ok}}" stepKey="waitForModal" /> <see selector="{{AdminConfirmationModalSection.title}}" userInput="Warning message" stepKey="seeWarningAboutTakingALongTimeToComplete" /> <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="confirmModal" /> - <waitForPageLoad stepKey="waitForStorePageLoad" /> - <waitForElementNotVisible selector="{{AdminNewStoreViewActionsSection.loadingMask}}" stepKey="waitForElementVisible"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForPageReolad"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You saved the store view." stepKey="seeSavedMessage" /> </actionGroup> <!--Save the Store view--> <actionGroup name="AdminCreateStoreViewActionSaveGroup"> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchStoreViewActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchStoreViewActionGroup.xml index ac8e9d717fdca..47236376f0209 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchStoreViewActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchStoreViewActionGroup.xml @@ -18,6 +18,7 @@ <waitForElementVisible selector="{{AdminConfirmationModalSection.ok}}" stepKey="waitingForInformationModal"/> <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="confirmStoreSwitch"/> <waitForPageLoad stepKey="waitForStoreViewSwitched"/> + <scrollToTopOfPage stepKey="scrollToStoreSwitcher"/> <see userInput="{{storeView}}" selector="{{AdminMainActionsSection.storeSwitcher}}" stepKey="seeNewStoreViewName"/> </actionGroup> <actionGroup name="AdminSwitchToAllStoreViewActionGroup" extends="AdminSwitchStoreViewActionGroup"> From c6affacaa982952bca93c9760bf256bf5af262e8 Mon Sep 17 00:00:00 2001 From: Ian Coast <icoast@crimsonagility.com> Date: Fri, 15 Mar 2019 08:26:42 -0700 Subject: [PATCH 051/585] Updated mathrandom class property to private to meet Magento technical guidelines Made mathrandom class optional to meet backwards compatibility requirements. --- .../Magento/Framework/View/Asset/MergeStrategy/Direct.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php index 57674bf2fbe58..e6ff58efe071a 100644 --- a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php +++ b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php @@ -33,20 +33,21 @@ class Direct implements \Magento\Framework\View\Asset\MergeStrategyInterface /** * @var \Magento\Framework\Math\Random */ - protected $mathRandom; + private $mathRandom; /** * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\Url\CssResolver $cssUrlResolver + * @param \Magento\Framework\Math\Random|null $mathRandom */ public function __construct( \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\Url\CssResolver $cssUrlResolver, - \Magento\Framework\Math\Random $mathRandom + \Magento\Framework\Math\Random $mathRandom = null ) { $this->filesystem = $filesystem; $this->cssUrlResolver = $cssUrlResolver; - $this->mathRandom = $mathRandom; + $this->mathRandom = $mathRandom ?: \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Framework\Math\Random::class);; } /** From 961e05c23d074b00ebf7c411d6bb677d467244be Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 5 Jan 2018 17:53:52 +0200 Subject: [PATCH 052/585] magento/magento2#8035: Join extension attributes are not added to Order results (REST api) --- .../Magento/Sales/Model/OrderRepository.php | 15 +++++- .../etc/extension_attributes.xml | 12 +++++ .../Magento/Webapi/JoinDirectivesTest.php | 48 +++++++++++++++++-- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Sales/Model/OrderRepository.php b/app/code/Magento/Sales/Model/OrderRepository.php index 9a1392fbe9065..79548cb190754 100644 --- a/app/code/Magento/Sales/Model/OrderRepository.php +++ b/app/code/Magento/Sales/Model/OrderRepository.php @@ -6,7 +6,9 @@ namespace Magento\Sales\Model; +use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Sales\Api\Data\OrderExtensionFactory; @@ -16,7 +18,6 @@ use Magento\Sales\Api\Data\ShippingAssignmentInterface; use Magento\Sales\Model\Order\ShippingAssignmentBuilder; use Magento\Sales\Model\ResourceModel\Metadata; -use Magento\Framework\App\ObjectManager; use Magento\Tax\Api\OrderTaxManagementInterface; use Magento\Payment\Api\Data\PaymentAdditionalInfoInterface; use Magento\Payment\Api\Data\PaymentAdditionalInfoInterfaceFactory; @@ -74,6 +75,11 @@ class OrderRepository implements \Magento\Sales\Api\OrderRepositoryInterface */ private $serializer; + /** + * @var JoinProcessorInterface + */ + private $extensionAttributesJoinProcessor; + /** * Constructor * @@ -84,6 +90,7 @@ class OrderRepository implements \Magento\Sales\Api\OrderRepositoryInterface * @param OrderTaxManagementInterface|null $orderTaxManagement * @param PaymentAdditionalInfoInterfaceFactory|null $paymentAdditionalInfoFactory * @param JsonSerializer|null $serializer + * @param JoinProcessorInterface $extensionAttributesJoinProcessor */ public function __construct( Metadata $metadata, @@ -92,7 +99,8 @@ public function __construct( \Magento\Sales\Api\Data\OrderExtensionFactory $orderExtensionFactory = null, OrderTaxManagementInterface $orderTaxManagement = null, PaymentAdditionalInfoInterfaceFactory $paymentAdditionalInfoFactory = null, - JsonSerializer $serializer = null + JsonSerializer $serializer = null, + JoinProcessorInterface $extensionAttributesJoinProcessor = null ) { $this->metadata = $metadata; $this->searchResultFactory = $searchResultFactory; @@ -106,6 +114,8 @@ public function __construct( ->get(PaymentAdditionalInfoInterfaceFactory::class); $this->serializer = $serializer ?: ObjectManager::getInstance() ->get(JsonSerializer::class); + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor + ?: ObjectManager::getInstance()->get(JoinProcessorInterface::class); } /** @@ -198,6 +208,7 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr { /** @var \Magento\Sales\Api\Data\OrderSearchResultInterface $searchResult */ $searchResult = $this->searchResultFactory->create(); + $this->extensionAttributesJoinProcessor->process($searchResult); $this->collectionProcessor->process($searchCriteria, $searchResult); $searchResult->setSearchCriteria($searchCriteria); foreach ($searchResult->getItems() as $order) { diff --git a/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/etc/extension_attributes.xml b/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/etc/extension_attributes.xml index 3bd64a7aff728..8254a9d8e92cf 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/etc/extension_attributes.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/etc/extension_attributes.xml @@ -31,4 +31,16 @@ </join> </attribute> </extension_attributes> + <extension_attributes for="Magento\Sales\Api\Data\OrderInterface"> + <attribute code="orderApiTestAttribute" type="Magento\User\Api\Data\UserInterface"> + <join reference_table="admin_user" + join_on_field="store_id" + reference_field="user_id" + > + <field>firstname</field> + <field>lastname</field> + <field>email</field> + </join> + </attribute> + </extension_attributes> </config> diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php index 5f967758e21bd..d00cfb831953e 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php @@ -6,11 +6,10 @@ namespace Magento\Webapi; +use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\Framework\Api\SortOrderBuilder; use Magento\Framework\Api\SortOrder; -use Magento\Framework\Api\SearchCriteria; -use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\Api\SortOrderBuilder; class JoinDirectivesTest extends \Magento\TestFramework\TestCase\WebapiAbstract { @@ -124,6 +123,49 @@ public function testAutoGeneratedGetList() $this->assertEquals($expectedExtensionAttributes['email'], $testAttribute['email']); } + /** + * Test get list of orders with extension attributes. + * + * @magentoApiDataFixture Magento/Sales/_files/order.php + */ + public function testGetOrdertList() + { + $filter = $this->filterBuilder + ->setField('increment_id') + ->setValue('100000001') + ->setConditionType('eq') + ->create(); + $this->searchBuilder->addFilters([$filter]); + $searchData = $this->searchBuilder->create()->__toArray(); + + $requestData = ['searchCriteria' => $searchData]; + + $restResourcePath = '/V1/orders/'; + $soapService = 'salesOrderRepositoryV1'; + $expectedExtensionAttributes = $this->getExpectedExtensionAttributes(); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => $restResourcePath . '?' . http_build_query($requestData), + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => $soapService, + 'operation' => $soapService . 'GetList', + ], + ]; + $searchResult = $this->_webApiCall($serviceInfo, $requestData); + + $this->assertArrayHasKey('items', $searchResult); + $itemData = array_pop($searchResult['items']); + $this->assertArrayHasKey('extension_attributes', $itemData); + $this->assertArrayHasKey('order_api_test_attribute', $itemData['extension_attributes']); + $testAttribute = $itemData['extension_attributes']['order_api_test_attribute']; + $this->assertEquals($expectedExtensionAttributes['firstname'], $testAttribute['first_name']); + $this->assertEquals($expectedExtensionAttributes['lastname'], $testAttribute['last_name']); + $this->assertEquals($expectedExtensionAttributes['email'], $testAttribute['email']); + } + /** * Retrieve the admin user's information. * From 6ce9ee7dbd13bbce08372482c3a4fcd7dcd08499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20M=C3=BCnch?= <c.muench@netz98.de> Date: Sat, 16 Mar 2019 11:27:48 +0200 Subject: [PATCH 053/585] Issue #7227: "x_forwarded_for" value is always empty in Order object --- .../Magento/Quote/Model/QuoteManagement.php | 28 ++++++- .../Test/Unit/Model/QuoteManagementTest.php | 78 +++++++++++++++---- 2 files changed, 88 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php index 8f216b64aa9b0..4c37e22898de9 100644 --- a/app/code/Magento/Quote/Model/QuoteManagement.php +++ b/app/code/Magento/Quote/Model/QuoteManagement.php @@ -146,6 +146,16 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface */ private $addressesToSync = []; + /** + * @var \Magento\Framework\App\RequestInterface + */ + private $request; + + /** + * @var \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress + */ + private $remoteAddress; + /** * @param EventManager $eventManager * @param QuoteValidator $quoteValidator @@ -169,6 +179,8 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface * @param QuoteFactory $quoteFactory * @param \Magento\Quote\Model\QuoteIdMaskFactory|null $quoteIdMaskFactory * @param \Magento\Customer\Api\AddressRepositoryInterface|null $addressRepository + * @param \Magento\Framework\App\RequestInterface|null $request + * @param \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress $remoteAddress * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -193,7 +205,9 @@ public function __construct( \Magento\Customer\Api\AccountManagementInterface $accountManagement, \Magento\Quote\Model\QuoteFactory $quoteFactory, \Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory = null, - \Magento\Customer\Api\AddressRepositoryInterface $addressRepository = null + \Magento\Customer\Api\AddressRepositoryInterface $addressRepository = null, + \Magento\Framework\App\RequestInterface $request = null, + \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress $remoteAddress = null ) { $this->eventManager = $eventManager; $this->quoteValidator = $quoteValidator; @@ -219,6 +233,10 @@ public function __construct( ->get(\Magento\Quote\Model\QuoteIdMaskFactory::class); $this->addressRepository = $addressRepository ?: ObjectManager::getInstance() ->get(\Magento\Customer\Api\AddressRepositoryInterface::class); + $this->request = $request ?: ObjectManager::getInstance() + ->get(\Magento\Framework\App\RequestInterface::class); + $this->remoteAddress = $remoteAddress ?: ObjectManager::getInstance() + ->get(\Magento\Framework\HTTP\PhpEnvironment\RemoteAddress::class); } /** @@ -368,6 +386,14 @@ public function placeOrder($cartId, PaymentInterface $paymentMethod = null) $quote->setCustomerGroupId(\Magento\Customer\Api\Data\GroupInterface::NOT_LOGGED_IN_ID); } + $remoteAddress = $this->remoteAddress->getRemoteAddress(); + if ($remoteAddress !== false) { + $quote->setRemoteIp($remoteAddress); + $quote->setXForwardedFor( + $this->request->getServer('HTTP_X_FORWARDED_FOR') + ); + } + $this->eventManager->dispatch('checkout_submit_before', ['quote' => $quote]); $order = $this->submit($quote); diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php index b61f95b4eee6c..8d8200cd6ef62 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php @@ -6,9 +6,12 @@ namespace Magento\Quote\Test\Unit\Model; +use Magento\Framework\App\RequestInterface; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress; use Magento\Quote\Model\CustomerManagement; +use Magento\Quote\Model\QuoteIdMaskFactory; use Magento\Sales\Api\Data\OrderAddressInterface; /** @@ -137,6 +140,21 @@ class QuoteManagementTest extends \PHPUnit\Framework\TestCase */ private $quoteFactoryMock; + /** + * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $requestMock; + + /** + * @var \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress|\PHPUnit_Framework_MockObject_MockObject + */ + private $remoteAddressMock; + + /** + * @var \Magento\Quote\Model\QuoteIdMaskFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $quoteIdMaskFactoryMock; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -178,18 +196,20 @@ protected function setUp() ); $this->quoteMock = $this->createPartialMock(\Magento\Quote\Model\Quote::class, [ - 'getId', - 'getCheckoutMethod', - 'setCheckoutMethod', - 'setCustomerId', - 'setCustomerEmail', - 'getBillingAddress', - 'setCustomerIsGuest', - 'setCustomerGroupId', - 'assignCustomer', - 'getPayment', - 'collectTotals' - ]); + 'assignCustomer', + 'collectTotals', + 'getBillingAddress', + 'getCheckoutMethod', + 'getPayment', + 'setCheckoutMethod', + 'setCustomerEmail', + 'setCustomerGroupId', + 'setCustomerId', + 'setCustomerIsGuest', + 'setRemoteIp', + 'setXForwardedFor', + 'getId', + ]); $this->quoteAddressFactory = $this->createPartialMock( \Magento\Quote\Model\Quote\AddressFactory::class, @@ -237,8 +257,11 @@ protected function setUp() // Set the new dependency $this->quoteIdMock = $this->createMock(\Magento\Quote\Model\QuoteIdMask::class); - $quoteIdFactoryMock = $this->createPartialMock(\Magento\Quote\Model\QuoteIdMaskFactory::class, ['create']); - $this->setPropertyValue($this->model, 'quoteIdMaskFactory', $quoteIdFactoryMock); + $this->quoteIdMaskFactoryMock = $this->createPartialMock(QuoteIdMaskFactory::class, ['create']); + $this->setPropertyValue($this->model, 'quoteIdMaskFactory', $this->quoteIdMaskFactoryMock); + + $this->requestMock = $this->createPartialMockForAbstractClass(RequestInterface::class, ['getServer']); + $this->remoteAddressMock = $this->createMock(RemoteAddress::class); } public function testCreateEmptyCartAnonymous() @@ -676,7 +699,11 @@ public function testPlaceOrderIfCustomerIsGuest() 'checkoutSession' => $this->checkoutSessionMock, 'customerSession' => $this->customerSessionMock, 'accountManagement' => $this->accountManagementMock, - 'quoteFactory' => $this->quoteFactoryMock + 'quoteFactory' => $this->quoteFactoryMock, + 'quoteIdMaskFactory' => $this->quoteIdMaskFactoryMock, + 'addressRepository' => $this->addressRepositoryMock, + 'request' => $this->requestMock, + 'remoteAddress' => $this->remoteAddressMock, ] ) ->getMock(); @@ -709,13 +736,15 @@ public function testPlaceOrder() $orderId = 332; $orderIncrementId = 100003332; $orderStatus = 'status1'; + $remoteAddress = '192.168.1.10'; + $forwardedForIp = '192.168.1.11'; /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Quote\Model\QuoteManagement $service */ $service = $this->getMockBuilder(\Magento\Quote\Model\QuoteManagement::class) ->setMethods(['submit']) ->setConstructorArgs( [ - 'eventManager' => $this->eventManager, + 'eventManager' => $this->eventManager, 'quoteValidator' => $this->quoteValidator, 'orderFactory' => $this->orderFactory, 'orderManagement' => $this->orderManagement, @@ -734,7 +763,11 @@ public function testPlaceOrder() 'checkoutSession' => $this->checkoutSessionMock, 'customerSession' => $this->customerSessionMock, 'accountManagement' => $this->accountManagementMock, - 'quoteFactory' => $this->quoteFactoryMock + 'quoteFactory' => $this->quoteFactoryMock, + 'quoteIdMaskFactory' => $this->quoteIdMaskFactoryMock, + 'addressRepository' => $this->addressRepositoryMock, + 'request' => $this->requestMock, + 'remoteAddress' => $this->remoteAddressMock, ] ) ->getMock(); @@ -762,6 +795,17 @@ public function testPlaceOrder() ->method('setCustomerIsGuest') ->with(true); + $this->remoteAddressMock + ->method('getRemoteAddress') + ->willReturn($remoteAddress); + + $this->requestMock + ->method('getServer') + ->willReturn($forwardedForIp); + + $this->quoteMock->expects($this->once())->method('setRemoteIp')->with($remoteAddress); + $this->quoteMock->expects($this->once())->method('setXForwardedFor')->with($forwardedForIp); + $service->expects($this->once())->method('submit')->willReturn($orderMock); $this->quoteMock->expects($this->atLeastOnce())->method('getId')->willReturn($cartId); From a5daaec8b264b6c648424441d3e452065399e6f3 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 18 Mar 2019 12:20:09 +0200 Subject: [PATCH 054/585] MC-15406: [FT] [MFTF] StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest fails because of bad design --- .../AdminCreateStoreViewActionGroup.xml | 16 ++++----- .../Mftf/Section/AdminStoresGridSection.xml | 1 + .../Mftf/Test/AdminCreateStoreViewTest.xml | 34 +++++++++++-------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml index 45b44b2d82f38..c02b3fc0fb72c 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml @@ -8,6 +8,7 @@ <!-- Test XML Example --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateStoreViewActionGroup"> <arguments> <argument name="StoreGroup" defaultValue="_defaultStoreGroup"/> @@ -28,17 +29,12 @@ <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForPageReolad"/> <see selector="{{AdminMessagesSection.success}}" userInput="You saved the store view." stepKey="seeSavedMessage" /> </actionGroup> - <!--Save the Store view--> - <actionGroup name="AdminCreateStoreViewActionSaveGroup"> - <waitForLoadingMaskToDisappear stepKey="waitForGridLoad"/> - <waitForElementVisible selector="{{AdminStoresGridSection.websiteFilterTextField}}" stepKey="waitForStoreGridToReload2"/> - <see userInput="You saved the store view." stepKey="seeSavedMessage" /> - </actionGroup> - <!--Save the same Store view code for code validation--> - <actionGroup name="AdminCreateStoreViewCodeUniquenessActionGroup"> - <waitForLoadingMaskToDisappear stepKey="waitForForm"/> - <see userInput="Store with the same code already exists." stepKey="seeMessage" /> + + <actionGroup name="AdminCreateStoreViewWithoutCheckActionGroup" extends="AdminCreateStoreViewActionGroup"> + <remove keyForRemoval="waitForPageReolad"/> + <remove keyForRemoval="seeSavedMessage"/> </actionGroup> + <actionGroup name="navigateToAdminContentManagementPage"> <amOnPage url="{{AdminContentManagementPage.url}}" stepKey="navigateToConfigurationPage"/> <waitForPageLoad stepKey="waitForPageLoad1"/> diff --git a/app/code/Magento/Store/Test/Mftf/Section/AdminStoresGridSection.xml b/app/code/Magento/Store/Test/Mftf/Section/AdminStoresGridSection.xml index 592af42f2de30..898c8b8841203 100644 --- a/app/code/Magento/Store/Test/Mftf/Section/AdminStoresGridSection.xml +++ b/app/code/Magento/Store/Test/Mftf/Section/AdminStoresGridSection.xml @@ -23,5 +23,6 @@ <element name="firstRow" type="textarea" selector="(//*[@id='storeGrid_table']/tbody/tr)[1]"/> <element name="successMessage" type="text" selector="//div[@class='message message-success success']/div"/> <element name="emptyText" type="text" selector="//tr[@class='data-grid-tr-no-data even']/td[@class='empty-text']"/> + <element name="gridCell" type="text" selector="//table[@class='data-grid']//tr[{{row}}]//td[count(//table[@class='data-grid']//tr//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewTest.xml index af8aceed07f0f..e20eb70ae6f45 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewTest.xml @@ -11,32 +11,36 @@ <annotations> <features value="Store"/> <stories value="Create a store view in admin"/> - <title value="Admin should be able to create a store view"/> - <description value="Admin should be able to create a store view"/> + <title value="Admin shouldn't be able to create a Store View with the same code"/> + <description value="Admin shouldn't be able to create a Store View with the same code"/> <group value="storeView"/> <severity value="AVERAGE"/> - <testCaseId value="MAGETWO-95111"/> + <useCaseId value="MAGETWO-95111"/> + <testCaseId value="MC-15422"/> </annotations> + <before> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView" /> - <!--<createData stepKey="b2" entity="customStoreGroup"/>--> </before> - <!--Save store view on Store Grid--> - <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="createStoreViewSave" /> - <!--Confirm new store view created on Store Grid--> - <fillField selector="{{AdminStoresGridSection.storeFilterTextField}}" userInput="{{customStore.name}}" stepKey="fillStoreViewFilter"/> - <click selector="{{AdminStoresGridSection.searchButton}}" stepKey="clickSearch" /> - <waitForPageLoad stepKey="waitForPageLoad"/> - <see selector="{{AdminStoresGridSection.storeNameInFirstRow}}" userInput="{{customStore.name}}" stepKey="seeNewStoreView" /> - <!--Creating the same store view to validate the code uniqueness on store form--> - <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView2" /> - <actionGroup ref="AdminCreateStoreViewCodeUniquenessActionGroup" stepKey="createStoreViewCode" /> + <after> <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> <argument name="customStore" value="customStore"/> </actionGroup> + <click selector="{{AdminStoresGridSection.resetButton}}" stepKey="resetSearchFilter"/> <actionGroup ref="logout" stepKey="logout"/> </after> + + <!--Filter grid and see created store view--> + <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="navigateToStoresIndex"/> + <click selector="{{AdminStoresGridSection.resetButton}}" stepKey="resetSearchFilter"/> + <fillField selector="{{AdminStoresGridSection.storeFilterTextField}}" userInput="{{customStore.name}}" stepKey="fillStoreViewFilterField"/> + <click selector="{{AdminStoresGridSection.searchButton}}" stepKey="clickSearch"/> + <see selector="{{AdminStoresGridSection.gridCell('1', 'Store View')}}" userInput="{{customStore.name}}" stepKey="seeNewStoreView"/> + <!--Try to create store view with the same code--> + <actionGroup ref="AdminCreateStoreViewWithoutCheckActionGroup" stepKey="createSameStoreView"/> + <dontSeeElement selector="{{AdminMessagesSection.success}}" stepKey="dontSeeSuccessMessage"/> + <see selector="{{AdminMessagesSection.error}}" userInput="Store with the same code already exists." stepKey="seeErrorMessage"/> </test> </tests> From 1dc63e8becdceb7ec50560c30af14e74cdd355d1 Mon Sep 17 00:00:00 2001 From: RomanKis <roman.kis.y@gmail.com> Date: Mon, 18 Mar 2019 13:09:00 +0200 Subject: [PATCH 055/585] #21779 Adminhtml textarea field doesn't accept maxlength --- lib/internal/Magento/Framework/Data/Form/Element/Textarea.php | 1 + .../Framework/Data/Test/Unit/Form/Element/TextareaTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php b/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php index 7cd3fb1f7fb99..47c89e0615df3 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php @@ -64,6 +64,7 @@ public function getHtmlAttributes() 'rows', 'cols', 'readonly', + 'maxlength', 'disabled', 'onkeyup', 'tabindex', diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php index e99df6c4c6e6f..4653aa2a50769 100644 --- a/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php +++ b/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php @@ -76,6 +76,7 @@ public function testGetHtmlAttributes() 'rows', 'cols', 'readonly', + 'maxlength', 'disabled', 'onkeyup', 'tabindex', From 7c33f43704d438828393f32d48254be2b9881de6 Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Mon, 18 Mar 2019 10:59:35 -0500 Subject: [PATCH 056/585] MC-4871: Convert CreateStoreEntityTest to MFTF --- ...iewDisabledErrorSaveMessageActionGroup.xml | 29 ++++++++ .../Store/Test/Mftf/Data/StoreData.xml | 20 +++++- .../Section/AdminStoresMainActionsSection.xml | 3 +- ...atusDisabledVerifyErrorSaveMessageTest.xml | 48 +++++++++++++ ...EnabledVerifyAbsenceOfDeleteButtonTest.xml | 61 ++++++++++++++++ ...tusEnabledVerifyBackendAndFrontendTest.xml | 72 +++++++++++++++++++ ...NewLocalizedStoreViewStatusEnabledTest.xml | 45 ++++++++++++ ...usDisabledVerifyBackendAndFrontendTest.xml | 52 ++++++++++++++ ...tusEnabledVerifyBackendAndFrontendTest.xml | 53 ++++++++++++++ 9 files changed, 381 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/StoreViewDisabledErrorSaveMessageActionGroup.xml create mode 100644 app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml create mode 100644 app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml create mode 100644 app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml create mode 100644 app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml create mode 100644 app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml create mode 100644 app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/StoreViewDisabledErrorSaveMessageActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/StoreViewDisabledErrorSaveMessageActionGroup.xml new file mode 100644 index 0000000000000..355af60b24ff2 --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/StoreViewDisabledErrorSaveMessageActionGroup.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StoreViewDisabledErrorSaveMessageActionGroup"> + <arguments> + <argument name="storeGroupName" type="string"/> + <argument name="storeView" type="string"/> + <argument name="storeViewStatus"/> + </arguments> + <amOnPage url="{{AdminSystemStoreViewPage.url}}" stepKey="amOnAdminSystemStoreViewPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <selectOption userInput="{{storeGroupName}}" selector="{{AdminNewStoreSection.storeGrpDropdown}}" stepKey="selectStoreGroup"/> + <fillField userInput="{{storeView}}" selector="{{AdminNewStoreSection.storeNameTextField}}" stepKey="fillStoreViewName"/> + <fillField userInput="{{storeView}}" selector="{{AdminNewStoreSection.storeCodeTextField}}" stepKey="fillStoreViewCode"/> + <selectOption userInput="{{storeViewStatus}}" selector="{{AdminNewStoreSection.statusDropdown}}" stepKey="selectStoreViewStatus"/> + <click selector="{{AdminStoresMainActionsSection.saveButton}}" stepKey="clickSaveStoreViewButton"/> + <waitForElementVisible selector="{{AdminNewStoreSection.acceptNewStoreViewCreation}}" stepKey="waitForAcceptNewStoreViewCreationButton"/> + <conditionalClick selector="{{AdminNewStoreSection.acceptNewStoreViewCreation}}" dependentSelector="{{AdminNewStoreSection.acceptNewStoreViewCreation}}" visible="true" stepKey="clickAcceptNewStoreViewCreationButton"/> + <waitForElementVisible selector="{{AdminStoresMainActionsSection.errorMessage}}" stepKey="waitForErrorMessage"/> + <see selector="{{AdminStoresMainActionsSection.errorMessage}}" userInput="The default store cannot be disabled" stepKey="AssertStoreDisabledErrorSaveMessage"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml b/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml index 4e043f9ff27db..f32b6dd83a2c6 100644 --- a/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml +++ b/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml @@ -166,4 +166,22 @@ <data key="store_type">store</data> <requiredEntity type="storeGroup">SecondStoreGroup</requiredEntity> </entity> -</entities> + <entity name="storeViewDataDisabled" type="store"> + <data key="group_id">1</data> + <data key="name" unique="suffix">storeView</data> + <data key="code" unique="suffix">storeView</data> + <data key="is_active">0</data> + <data key="store_id">null</data> + <data key="store_type">store</data> + <data key="store_action">add</data> + </entity> + <entity name="storeViewGermany" type="store"> + <data key="group_id">1</data> + <data key="name" unique="suffix">DE_</data> + <data key="code" unique="suffix">de_</data> + <data key="is_active">1</data> + <data key="store_id">null</data> + <data key="store_type">store</data> + <data key="store_action">add</data> + </entity> +</entities> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Section/AdminStoresMainActionsSection.xml b/app/code/Magento/Store/Test/Mftf/Section/AdminStoresMainActionsSection.xml index e40aa76967bec..35f4507a80f81 100644 --- a/app/code/Magento/Store/Test/Mftf/Section/AdminStoresMainActionsSection.xml +++ b/app/code/Magento/Store/Test/Mftf/Section/AdminStoresMainActionsSection.xml @@ -13,5 +13,6 @@ <element name="saveButton" type="button" selector="#save" timeout="90"/> <element name="backButton" type="button" selector="#back" timeout="30"/> <element name="deleteButton" type="button" selector="#delete" timeout="30"/> + <element name="errorMessage" type="text" selector="//div[@class='message message-error error']/div"/> </section> -</sections> +</sections> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml new file mode 100644 index 0000000000000..94959c7bf0a91 --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest"> + <annotations> + <stories value="Create Store View"/> + <title value="Create Custom Store View Status Disabled and Verify Error Save Message"/> + <description value="Test log in to Stores and Create Custom Store View Status Enabled and Verify Error Save Message Test"/> + <testCaseId value="MC-14309"/> + <severity value="CRITICAL"/> + <group value="store"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + <!--Create website--> + <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createWebsite"> + <argument name="newWebsiteName" value="{{customWebsite.name}}"/> + <argument name="websiteCode" value="{{customWebsite.code}}"/> + </actionGroup> + <!-- Create store --> + <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="createStore"> + <argument name="website" value="{{customWebsite.name}}"/> + <argument name="storeGroupName" value="{{customStore.name}}"/> + <argument name="storeGroupCode" value="{{customStore.code}}"/> + </actionGroup> + </before> + <after> + <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> + <argument name="websiteName" value="{{customWebsite.name}}"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create store view selecting store created, choose disabled status and verify AssertStoreDisabledErrorSaveMessage--> + <actionGroup ref="StoreViewDisabledErrorSaveMessageActionGroup" stepKey="createStoreViewAssertStoreDisabledErrorSaveMessage"> + <argument name="storeGroupName" value="{{customStore.name}}"/> + <argument name="storeView" value="storeViewDataDisabled"/> + <argument name="storeViewStatus" value="storeViewDataDisabled.is_active"/> + </actionGroup> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml new file mode 100644 index 0000000000000..64713ce64fd54 --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest"> + <annotations> + <stories value="Create Store View"/> + <title value="Create Custom Store View Status Enabled and Verify Absence Of Delete Button"/> + <description value="Test log in to Stores and Create Custom Store View Status Enabled and Verify Absence Of Delete Button Test"/> + <testCaseId value="MC-14308"/> + <severity value="CRITICAL"/> + <group value="store"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + <!-- Create store --> + <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="createFirstStore"> + <argument name="website" value="{{_defaultWebsite.name}}"/> + <argument name="storeGroupName" value="{{customStore.name}}"/> + <argument name="storeGroupCode" value="{{customStore.code}}"/> + </actionGroup> + </before> + <after> + <actionGroup ref="DeleteCustomStoreActionGroup" stepKey="deleteStore"> + <argument name="storeGroupName" value="customStore.name"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create custom store view--> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView"> + <argument name="StoreGroup" value="customStore"/> + <argument name="customStore" value="storeViewData"/> + </actionGroup> + + <!--Save the above store view and verify AssertStoreViewSuccessSaveMessage--> + <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"> + </actionGroup> + + <!--Search store view(from above step) in grid--> + <actionGroup ref="AssertStoreViewInGridActionGroup" stepKey="searchStoreViewInGrid"> + <argument name="storeViewName" value="{{storeViewData.name}}"/> + </actionGroup> + + <!--Go to store view form page and verify AssertStoreForm--> + <actionGroup ref="AssertStoreViewFormActionGroup" stepKey="verifyStoreViewForm"> + <argument name="storeDropdown" value="{{customStore.name}}"/> + <argument name="storeViewName" value="{{storeViewData.name}}"/> + <argument name="storeViewCode" value="{{storeViewData.code}}"/> + <argument name="status" value="Enabled"/> + </actionGroup> + <!--Go to store view form page and verify AssertStoreNoDeleteButton--> + <dontSee selector="{{AdminNewStoreViewActionsSection.delete}}" stepKey="AssertStoreNoDeleteButton"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml new file mode 100644 index 0000000000000..a7c5cfd575909 --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest"> + <annotations> + <stories value="Create Store View"/> + <title value="Create Custom Store View Status Enabled and Verify Backend and Frontend"/> + <description value="Test log in to Stores and Create Custom Store View Status Enabled and Verify Backend and Frontend Test"/> + <testCaseId value="MC-14306"/> + <severity value="CRITICAL"/> + <group value="store"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + <!-- Create store --> + <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="createStore"> + <argument name="website" value="{{_defaultWebsite.name}}"/> + <argument name="storeGroupName" value="{{customStore.name}}"/> + <argument name="storeGroupCode" value="{{customStore.code}}"/> + </actionGroup> + </before> + <after> + <actionGroup ref="DeleteCustomStoreActionGroup" stepKey="deleteStore"> + <argument name="storeGroupName" value="customStore.name"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create custom store view--> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView"> + <argument name="StoreGroup" value="customStore"/> + <argument name="customStore" value="storeViewData"/> + </actionGroup> + + <!--Save the above store view and verify AssertStoreViewSuccessSaveMessage--> + <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"> + </actionGroup> + + <!--Search store view(from above step) in grid and verify AssertStoreInGrid--> + <actionGroup ref="AssertStoreViewInGridActionGroup" stepKey="searchStoreViewInGrid"> + <argument name="storeViewName" value="{{storeViewData.name}}"/> + </actionGroup> + + <!--Go to store view form page and verify AssertStoreForm--> + <actionGroup ref="AssertStoreViewFormActionGroup" stepKey="verifyStoreViewForm"> + <argument name="storeDropdown" value="{{customStore.name}}"/> + <argument name="storeViewName" value="{{storeViewData.name}}"/> + <argument name="storeViewCode" value="{{storeViewData.code}}"/> + <argument name="status" value="Enabled"/> + </actionGroup> + + <!--Go to store configuration page and verify AssertStoreBackend--> + <amOnPage url="{{AdminConfigPage.url}}" stepKey="goToStoreConfigurationPage"/> + <waitForPageLoad stepKey="waitForSystemStoreConfigurationPageLoad" /> + <click selector="{{AdminConfigSection.defaultConfigButton}}" stepKey="clickDefaultConfigButton"/> + <see selector="{{AdminConfigSection.defaultConfigDropdown}}" userInput="{{storeViewData.name}}" stepKey="seeAssertStoreViewInDefaultConfigDropdown"/> + + <!--Go to storefront and verify AssertStoreFrontend--> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> + <waitForPageLoad stepKey="waitForStorefrontHomePageLoad"/> + <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="clickSwitchStoreButton"/> + <waitForPageLoad stepKey="waitForSwitchStoreButtonLoad"/> + <seeElement selector="{{StorefrontFooterSection.storeLink(customStore.name)}}" stepKey="seeCustomStoreInStoreLink"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml new file mode 100644 index 0000000000000..fda0c3b1aa840 --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateNewLocalizedStoreViewStatusEnabledTest"> + <annotations> + <stories value="Create Store View"/> + <title value="Create New Localized Store View Status Enabled and Verify Save Message"/> + <description value="Test log in to Stores and Create New Localized Store View Status Enabled Test"/> + <testCaseId value="MC-14307"/> + <severity value="CRITICAL"/> + <group value="store"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> + <argument name="customStore" value="storeViewGermany"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create new localized store view--> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView"> + <argument name="StoreGroup" value="_defaultStoreGroup"/> + <argument name="customStore" value="storeViewGermany"/> + </actionGroup> + + <!--Save the above store view and verify AssertStoreViewSuccessSaveMessage--> + <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"> + </actionGroup> + + <!--Search store view(from above step) in grid and verify AssertStoreInGrid--> + <actionGroup ref="AssertStoreViewInGridActionGroup" stepKey="searchStoreViewInGrid"> + <argument name="storeViewName" value="{{storeViewGermany.name}}"/> + </actionGroup> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml new file mode 100644 index 0000000000000..65c126bb8eff9 --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest"> + <annotations> + <stories value="Create Store View"/> + <title value="Create Store View Status Disabled and Verify Backend and Frontend"/> + <description value="Test log in to Stores and Create Store View Status Disabled Test"/> + <testCaseId value="MC-14305"/> + <severity value="CRITICAL"/> + <group value="store"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> + <argument name="customStore" value="storeViewDataDisabled"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create store view--> + <actionGroup ref="CreateStoreView" stepKey="createStoreView"> + <argument name="storeView" value="storeViewDataDisabled"/> + <argument name="storeGroupName" value="_defaultStoreGroup.name"/> + <argument name="storeViewStatus" value="storeViewDataDisabled.is_active"/> + </actionGroup> + + <!--Save the above store view and verify AssertStoreViewSuccessSaveMessage--> + <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"> + </actionGroup> + + <!--Go to store configuration page and verify AssertStoreBackend--> + <amOnPage url="{{AdminConfigPage.url}}" stepKey="goToConfigStoreConfigurationPage"/> + <waitForPageLoad stepKey="waitForSystemStoreConfigurationPageLoad"/> + <click selector="{{AdminConfigSection.defaultConfigButton}}" stepKey="clickDefaultConfigButton"/> + <see selector="{{AdminConfigSection.defaultConfigDropdown}}" userInput="{{storeViewDataDisabled.name}}" stepKey="seeAssertStoreViewInDefaultConfigDropdown"/> + + <!--Go to storefront and verify AssertStoreNotOnFrontend--> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> + <waitForPageLoad stepKey="waitForStorefrontHomePageLoad"/> + <dontSee selector="{{StorefrontHeaderSection.storeViewDropdown}}" userInput="{{storeViewDataDisabled.name}}" stepKey="AssertStoreNotOnFrontend"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml new file mode 100644 index 0000000000000..6552f04b747b4 --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest"> + <annotations> + <stories value="Create Store View"/> + <title value="Create Store View Status Enabled and Verify Backend and Frontend"/> + <description value="Test log in to Stores and Create Store View Status Enabled Test"/> + <testCaseId value="MC-14304"/> + <severity value="CRITICAL"/> + <group value="store"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> + <argument name="customStore" value="storeViewData"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create store view--> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView"> + <argument name="StoreGroup" value="_defaultStoreGroup"/> + <argument name="customStore" value="storeViewData"/> + </actionGroup> + + <!--Save the above store view and verify AssertStoreViewSuccessSaveMessage--> + <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"> + </actionGroup> + + <!--Go to store configuration page and verify AssertStoreBackend--> + <amOnPage url="{{AdminConfigPage.url}}" stepKey="goToConfigStoreConfigurationPage"/> + <waitForPageLoad stepKey="waitForSystemStoreConfigurationPageLoad" /> + <click selector="{{AdminConfigSection.defaultConfigButton}}" stepKey="clickDefaultConfigButton"/> + <see selector="{{AdminConfigSection.defaultConfigDropdown}}" userInput="{{storeViewData.name}}" stepKey="seeAssertStoreViewInDefaultConfigDropdown"/> + + <!--Go to storefront and verify AssertStoreFrontend--> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> + <waitForPageLoad stepKey="waitForStorefrontHomePageLoad"/> + <click selector="{{StorefrontHeaderSection.storeViewSwitcher}}" stepKey="selectStoreSwitcher"/> + <waitForPageLoad stepKey="waitForFirstStoreView"/> + <see selector="{{StorefrontHeaderSection.storeViewDropdown}}" userInput="{{storeViewData.name}}" stepKey="seeAssertStoreViewOnStorefront"/> + </test> +</tests> \ No newline at end of file From 28997a88c8ddaae8c948a1e10705389e0d570e32 Mon Sep 17 00:00:00 2001 From: Yuliya Labudova <Yuliya_Labudova@epam.com> Date: Mon, 18 Mar 2019 22:28:06 +0300 Subject: [PATCH 057/585] MAGETWO-98522: Adding out of stock items to comparison shows success message but fails - Fix static and functional test --- .../Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml | 1 + .../ViewModel/Product/Checker/AddToCompareAvailability.php | 2 ++ .../Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml | 1 + 3 files changed, 4 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index cc894dcc178aa..4a3ce7310c02c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -29,6 +29,7 @@ <deleteData createDataKey="product" stepKey="deleteProduct"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> <amOnPage url="{{AdminLogoutPage.url}}" stepKey="amOnLogoutPage"/> + <actionGroup ref="noDisplayOutOfStockProduct" stepKey="noDisplayOutOfStockProduct"/> </after> <!--Check 'out of stock' is turned off by default--> diff --git a/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php b/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php index 24fd03f023be2..fde621a395fbf 100644 --- a/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php +++ b/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php @@ -32,6 +32,7 @@ public function __construct(StockConfigurationInterface $stockConfiguration) /** * Is product available for comparison. * + * @param ProductInterface $product * @return bool */ public function isAvailableForCompare(ProductInterface $product): bool @@ -43,6 +44,7 @@ public function isAvailableForCompare(ProductInterface $product): bool /** * Get is in stock status. * + * @param ProductInterface $product * @return bool */ private function isInStock(ProductInterface $product): bool diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml index c7c9126f46803..2850b8d069201 100644 --- a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml +++ b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml @@ -21,6 +21,7 @@ <actionGroup name="noDisplayOutOfStockProduct"> <amOnPage url="{{InventoryConfigurationPage.url}}" stepKey="navigateToInventoryConfigurationPage"/> <waitForPageLoad stepKey="waitForConfigPageToLoad"/> + <conditionalClick stepKey="expandProductStockOptions" selector="{{InventoryConfigSection.ProductStockOptionsTab}}" dependentSelector="{{InventoryConfigSection.CheckIfProductStockOptionsTabExpanded}}" visible="true" /> <uncheckOption selector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" stepKey="uncheckUseSystemValue"/> <waitForElementVisible selector="{{InventoryConfigSection.DisplayOutOfStockDropdown}}" stepKey="waitForSwitcherDropdown" /> <selectOption selector="{{InventoryConfigSection.DisplayOutOfStockDropdown}}" userInput="No" stepKey="switchToNo" /> From 1576876895d42af2c80efee078b4a47ad162d880 Mon Sep 17 00:00:00 2001 From: Yuliya Labudova <Yuliya_Labudova@epam.com> Date: Tue, 19 Mar 2019 09:41:23 +0300 Subject: [PATCH 058/585] MAGETWO-98522: Adding out of stock items to comparison shows success message but fails - Stabilize functional test --- .../Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index 4a3ce7310c02c..849976a4c9e79 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -26,10 +26,10 @@ </createData> </before> <after> + <actionGroup ref="noDisplayOutOfStockProduct" stepKey="noDisplayOutOfStockProduct"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> <amOnPage url="{{AdminLogoutPage.url}}" stepKey="amOnLogoutPage"/> - <actionGroup ref="noDisplayOutOfStockProduct" stepKey="noDisplayOutOfStockProduct"/> </after> <!--Check 'out of stock' is turned off by default--> From 645e82e86d43fc729c85c41c15ef9e478d2fa4fb Mon Sep 17 00:00:00 2001 From: Yuliya Labudova <Yuliya_Labudova@epam.com> Date: Tue, 19 Mar 2019 11:05:55 +0300 Subject: [PATCH 059/585] MAGETWO-98522: Adding out of stock items to comparison shows success message but fails - Fix functional test --- .../Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index 849976a4c9e79..47926edaabe02 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -47,6 +47,7 @@ <!--Clear cache--> <actionGroup ref="ClearCacheActionGroup" stepKey="clearCache" /> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> <!--Open product page--> <amOnPage url="$$product.name$$.html" stepKey="goToSimpleProductPage2"/> From c90d75ed9e34445a78ecc651c79d8bb99f455199 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 19 Mar 2019 12:17:17 +0200 Subject: [PATCH 060/585] ENGCOM-3715: Health Index fix. --- .../Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php b/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php index 7078cc0a502ad..5625dd5aabb73 100644 --- a/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php +++ b/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Column/Cart.php @@ -23,7 +23,7 @@ class Cart extends \Magento\Wishlist\Block\Customer\Wishlist\Item\Column /** * @var View */ - protected $productView; + private $productView; /** * @param \Magento\Catalog\Block\Product\Context $context From e546a8b3331135c739f0356cdc7f0e1a0d9d66b9 Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Tue, 19 Mar 2019 11:11:50 -0500 Subject: [PATCH 061/585] MC-4894: Convert GridFilteringDeletedEntityTest to MFTF --- ...CategoryAndWebsiteToProductActionGroup.xml | 28 +++++++ ...uctInGridByStoreViewAndNameActionGroup.xml | 25 ++++++ .../Section/AdminProductGridFilterSection.xml | 1 + ...dFilterDeleteAndVerifyErrorMessageTest.xml | 80 +++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddCategoryAndWebsiteToProductActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/FilterProductInGridByStoreViewAndNameActionGroup.xml create mode 100644 app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddCategoryAndWebsiteToProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddCategoryAndWebsiteToProductActionGroup.xml new file mode 100644 index 0000000000000..45553f6b5337f --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddCategoryAndWebsiteToProductActionGroup.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AddCategoryAndWebsiteToProductActionGroup"> + <arguments> + <argument name="category" type="string"/> + <argument name="website" type="string"/> + </arguments> + <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> + <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="{{category}}" stepKey="fillSearchForInitialCategory"/> + <click selector="{{AdminProductFormSection.selectCategory(category)}}" stepKey="selectCategory"/> + <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneButton"/> + <scrollTo selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="scrollToProductInWebsiteSectionHeader"/> + <click selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="clickProductInWebsiteSectionHeader"/> + <checkOption selector="{{ProductInWebsitesSection.website(website)}}" stepKey="checkWebsite"/> + <scrollToTopOfPage stepKey="scrollToTopOfAdminProductFormSection"/> + <click selector="{{AdminProductFormSection.save}}" stepKey="clickSaveButton"/> + <waitForPageLoad stepKey="waitForSimpleProductSaved"/> + <see selector="{{AdminProductFormSection.successMessage}}" userInput="You saved the product." stepKey="seeAssertProductSaveSuccessMessage"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/FilterProductInGridByStoreViewAndNameActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/FilterProductInGridByStoreViewAndNameActionGroup.xml new file mode 100644 index 0000000000000..d5d378ad11bd9 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/FilterProductInGridByStoreViewAndNameActionGroup.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="FilterProductInGridByStoreViewAndNameActionGroup"> + <arguments> + <argument name="storeView" type="string"/> + <argument name="productName" type="string"/> + </arguments> + <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPageToSearchProduct"/> + <waitForPageLoad stepKey="waitForProductCatalogPageToLoad"/> + <conditionalClick selector="{{AdminProductGridFilterSection.clearAll}}" dependentSelector="{{AdminProductGridFilterSection.clearAll}}" visible="true" stepKey="clickClearAll"/> + <click selector="{{AdminProductGridFilterSection.filters}}" stepKey="clickFiltersButton"/> + <click selector="{{AdminProductGridFilterSection.storeViewDropdown(storeView)}}" stepKey="clickStoreViewDropdown"/> + <fillField selector="{{AdminProductGridFilterSection.nameFilter}}" userInput="{{productName}}" stepKey="fillProductNameInNameFilter"/> + <click selector="{{AdminProductGridFilterSection.applyFilters}}" stepKey="clickApplyFiltersButton"/> + <see selector="{{AdminProductGridFilterSection.nthRow('1')}}" userInput="{{productName}}" stepKey="seeFirstRowToVerifyProductVisibleInGrid"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridFilterSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridFilterSection.xml index 939974248aabf..3b6f24c0f259d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridFilterSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridFilterSection.xml @@ -35,5 +35,6 @@ <element name="nthRow" type="block" selector=".data-row:nth-of-type({{var}})" parameterized="true" timeout="30"/> <element name="productCount" type="text" selector="#catalog_category_products-total-count"/> <element name="productPerPage" type="select" selector="#catalog_category_products_page-limit"/> + <element name="storeViewDropdown" type="text" selector="//select[@name='store_id']/option[contains(.,'{{storeView}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml b/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml new file mode 100644 index 0000000000000..351e4677dbd9a --- /dev/null +++ b/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminGridFilterDeleteAndVerifyErrorMessageTest"> + <annotations> + <stories value="Delete Grid Filter"/> + <title value="Grid Filter Delete and Verify Error Message"/> + <description value="Test log in to uI and Delete Grid Filter Test"/> + <testCaseId value="MC-14272"/> + <severity value="CRITICAL"/> + <group value="uI"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <magentoCLI command="config:set system/backup/functionality_enabled 1" stepKey="setEnableBackupToYes"/> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="NewRootCategory" stepKey="rootCategory"/> + <createData entity="defaultSimpleProduct" stepKey="createProduct"/> + <!--Create website--> + <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createWebsite"> + <argument name="newWebsiteName" value="{{customWebsite.name}}"/> + <argument name="websiteCode" value="{{customWebsite.code}}"/> + </actionGroup> + <!-- Create second store --> + <actionGroup ref="CreateCustomStore" stepKey="createCustomStore"> + <argument name="website" value="{{customWebsite.name}}"/> + <argument name="store" value="{{customStoreGroup.name}}"/> + <argument name="rootCategory" value="$$rootCategory.name$$"/> + </actionGroup> + <!-- Create second store view --> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createCustomStoreView"> + <argument name="StoreGroup" value="customStoreGroup"/> + <argument name="customStore" value="customStoreEN"/> + </actionGroup> + </before> + <after> + <deleteData stepKey="deleteRootCategory" createDataKey="rootCategory"/> + <deleteData stepKey="deleteProduct" createDataKey="createProduct"/> + <magentoCLI command="config:set system/backup/functionality_enabled 0" stepKey="setEnableBackupToNo"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Filter created simple product in grid and add category and website created in create data--> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="openProductCatalogPage"/> + <waitForPageLoad stepKey="waitForProductCatalogPage"/> + <actionGroup ref="filterProductGridBySku" stepKey="filterProduct"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowOfCreatedSimpleProduct"/> + <waitForPageLoad stepKey="waitUntilProductIsOpened"/> + <actionGroup ref="AddCategoryAndWebsiteToProductActionGroup" stepKey="updateSimpleProductAddingCategoryAndWebsiteCreated"> + <argument name="category" value="$$rootCategory.name$$"/> + <argument name="website" value="{{customWebsite.name}}"/> + </actionGroup> + + <!--Search updated simple product(from above step) in the grid by StoreView and Name--> + <actionGroup ref="FilterProductInGridByStoreViewAndNameActionGroup" stepKey="searchCreatedSimpleProductInGrid"> + <argument name="storeView" value="{{customStoreEN.name}}"/> + <argument name="productName" value="$$createProduct.name$$"/> + </actionGroup> + + <!--Go to stores and delete website created in create data--> + <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> + <argument name="websiteName" value="{{customWebsite.name}}"/> + </actionGroup> + + <!--Go to grid page and verify AssertErrorMessage--> + <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/> + <waitForPageLoad stepKey="waitForProductCatalogPageLoad"/> + <click selector="{{AdminCategoryModalSection.ok}}" stepKey="clickOkButtonFromAdminCategoryModalSection"/> + <see selector="{{AdminCategoryMessagesSection.errorMessage}}" userInput="Something went wrong with processing the default view and we have restored the filter to its original state." stepKey="seeAssertErrorMessage"/> + </test> +</tests> \ No newline at end of file From b0cf24cdfbf1514f2300185e1f6196932076e7f9 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Tue, 19 Mar 2019 16:05:12 -0500 Subject: [PATCH 062/585] MC-4585: Convert CreateDownloadableProductEntityTest to MFTF --- ...AdvancedPricingToTheProductActionGroup.xml | 26 ++++ ...lickOnAdvancedInventoryLinkActionGroup.xml | 16 +++ ...CreateCustomDropDownOptionsActionGroup.xml | 33 ++++++ ...nventoryOutOfStockThresholdActionGroup.xml | 18 +++ ...minFillAdvancedInventoryQtyActionGroup.xml | 17 +++ ...SubmitAdvancedInventoryFormActionGroup.xml | 15 +++ ...CheckProductPriceInCategoryActionGroup.xml | 16 +++ .../Catalog/Test/Mftf/Data/GroupPriceData.xml | 18 +++ ...minProductFormAdvancedInventorySection.xml | 2 + ...AdminProductFormAdvancedPricingSection.xml | 1 + ...DownloadableLinkInformationActionGroup.xml | 21 ++++ .../Test/Mftf/Data/ProductData.xml | 11 ++ .../AdminProductDownloadableSection.xml | 1 + .../StorefrontDownloadableProductSection.xml | 16 +++ ...bleProductAndAssignItToCustomStoreTest.xml | 93 +++++++++++++++ ...wnloadableProductWithCustomOptionsTest.xml | 111 +++++++++++++++++ ...loadableProductWithDefaultSetLinksTest.xml | 112 ++++++++++++++++++ ...eDownloadableProductWithGroupPriceTest.xml | 110 +++++++++++++++++ ...nCreateDownloadableProductWithLinkTest.xml | 102 ++++++++++++++++ ...DownloadableProductWithManageStockTest.xml | 109 +++++++++++++++++ ...oadableProductWithOutOfStockStatusTest.xml | 95 +++++++++++++++ ...ownloadableProductWithSpecialPriceTest.xml | 36 ++++++ ...teDownloadableProductWithTierPriceText.xml | 40 +++++++ ...ductWithoutFillingQuantityAndStockTest.xml | 100 ++++++++++++++++ ...wnloadableProductWithoutTaxClassIdTest.xml | 103 ++++++++++++++++ 25 files changed, 1222 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddAdvancedPricingToTheProductActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminClickOnAdvancedInventoryLinkActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateCustomDropDownOptionsActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillAdvancedInventoryOutOfStockThresholdActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillAdvancedInventoryQtyActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSubmitAdvancedInventoryFormActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckProductPriceInCategoryActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Data/GroupPriceData.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/ActionGroup/AdminAddDownloadableLinkInformationActionGroup.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontDownloadableProductSection.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddAdvancedPricingToTheProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddAdvancedPricingToTheProductActionGroup.xml new file mode 100644 index 0000000000000..14ff6640f1274 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddAdvancedPricingToTheProductActionGroup.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- You must already be on the product form > Advanced Inventory; + Action group can be used for customer group price and tier price --> + <actionGroup name="AdminAddAdvancedPricingToTheProductActionGroup"> + <arguments> + <argument name="index" type="string"/> + <argument name="groupPrice" type="entity"/> + </arguments> + <waitForPageLoad stepKey="waitForPageLoad"/> + <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink"/> + <click selector="{{AdminProductFormAdvancedPricingSection.addCustomerGroupPrice}}" stepKey="clickCustomerGroupPriceAddButton"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect(index)}}" userInput="{{groupPrice.website_id}}" stepKey="selectProductTierPriceWebsiteInput"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect(index)}}" userInput="{{groupPrice.customer_group}}" stepKey="selectProductTierPriceCustomerGroupInput"/> + <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput(index)}}" userInput="{{groupPrice.quantity}}" stepKey="fillProductTierPriceQuantityInput"/> + <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput(index)}}" userInput="{{groupPrice.price}}" stepKey="selectProductTierPriceFixedPrice"/> + <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDoneButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminClickOnAdvancedInventoryLinkActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminClickOnAdvancedInventoryLinkActionGroup.xml new file mode 100644 index 0000000000000..58164ce5f8989 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminClickOnAdvancedInventoryLinkActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- ActionGroup click on Advanced Inventory in product form; + You must already be on the product form page --> + <actionGroup name="AdminClickOnAdvancedInventoryLinkActionGroup"> + <click selector="{{AdminProductFormSection.advancedInventoryLink}}" stepKey="clickOnAdvancedInventoryLink"/> + <waitForPageLoad stepKey="waitForAdvancedInventoryPageToLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateCustomDropDownOptionsActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateCustomDropDownOptionsActionGroup.xml new file mode 100644 index 0000000000000..2b2e288fcfedb --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateCustomDropDownOptionsActionGroup.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCustomDropDownOptionsActionGroup"> + <!-- ActionGroup will add a single custom option to a product + You must already be on the product creation page --> + <arguments> + <argument name="customOptionName"/> + <argument name="firstOption"/> + <argument name="secondOption"/> + </arguments> + <click stepKey="clickAddOptions" selector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}"/> + <waitForPageLoad stepKey="waitForAddProductPageLoad"/> + <!-- Fill in the option and select the type of drop down --> + <fillField stepKey="fillInOptionTitle" selector="{{AdminProductCustomizableOptionsSection.lastOptionTitle}}" userInput="{{customOptionName}}"/> + <click stepKey="clickOptionTypeParent" selector="{{AdminProductCustomizableOptionsSection.lastOptionTypeParent}}"/> + <waitForPageLoad stepKey="waitForDropdownOpen"/> + <click stepKey="clickOptionType" selector="{{AdminProductCustomizableOptionsSection.optionType('Drop-down')}}"/> + <!-- Add option based on the parameter --> + <click stepKey="clickAddFirstValue" selector="{{AdminProductCustomizableOptionsSection.addValue}}"/> + <fillField stepKey="fillInFirstOptionValueTitle" selector="{{AdminProductCustomizableOptionsSection.valueTitle}}" userInput="{{firstOption.title}}"/> + <fillField stepKey="fillInFirstOptionValuePrice" selector="{{AdminProductCustomizableOptionsSection.valuePrice}}" userInput="{{firstOption.price}}"/> + <click stepKey="clickAddSecondValue" selector="{{AdminProductCustomizableOptionsSection.addValue}}"/> + <fillField stepKey="fillInSecondOptionValueTitle" selector="{{AdminProductCustomizableOptionsSection.valueTitle}}" userInput="{{secondOption.title}}"/> + <fillField stepKey="fillInSecondOptionValuePrice" selector="{{AdminProductCustomizableOptionsSection.valuePrice}}" userInput="{{secondOption.price}}"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillAdvancedInventoryOutOfStockThresholdActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillAdvancedInventoryOutOfStockThresholdActionGroup.xml new file mode 100644 index 0000000000000..d0116467be5ea --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillAdvancedInventoryOutOfStockThresholdActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- You must already be on the product form > Advanced Inventory --> + <actionGroup name="AdminFillAdvancedInventoryOutOfStockThresholdActionGroup"> + <arguments> + <argument name="qty" type="string"/> + </arguments> + <uncheckOption selector="{{AdminProductFormAdvancedInventorySection.minQtyConfigSetting}}" stepKey="uncheckMiniQtyCheckBox"/> + <fillField selector="{{AdminProductFormAdvancedInventorySection.outOfStockThreshold}}" userInput="{{qty}}" stepKey="fillMiniAllowedQty"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillAdvancedInventoryQtyActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillAdvancedInventoryQtyActionGroup.xml new file mode 100644 index 0000000000000..1faa3f04d366e --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillAdvancedInventoryQtyActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- You must already be on the product form > Advanced Inventory --> + <actionGroup name="AdminFillAdvancedInventoryQtyActionGroup"> + <arguments> + <argument name="qty" type="string"/> + </arguments> + <fillField selector="{{AdminProductFormAdvancedInventorySection.advancedInventoryQty}}" userInput="{{qty}}" stepKey="fillQty"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSubmitAdvancedInventoryFormActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSubmitAdvancedInventoryFormActionGroup.xml new file mode 100644 index 0000000000000..e27454fb60491 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSubmitAdvancedInventoryFormActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Click done button; + You must already be on the product form > Advanced Inventory --> + <actionGroup name="AdminSubmitAdvancedInventoryFormActionGroup"> + <click stepKey="clickOnDoneButton" selector="{{AdminProductFormAdvancedInventorySection.doneButton}}"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckProductPriceInCategoryActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckProductPriceInCategoryActionGroup.xml new file mode 100644 index 0000000000000..5c975998ab92e --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckProductPriceInCategoryActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- You must already be on the category page --> + <actionGroup name="StorefrontCheckProductPriceInCategoryActionGroup" extends="StorefrontCheckCategorySimpleProduct"> + <remove keyForRemoval="AssertProductPrice"/> + <see userInput="{{product.price}}" selector="{{StorefrontCategoryProductSection.ProductPriceByName(product.name)}}" stepKey="AssertProductPrice"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/GroupPriceData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/GroupPriceData.xml new file mode 100644 index 0000000000000..ae4736a1ca234 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/GroupPriceData.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="simpleGroupPrice" type="data"> + <data key="price">90.00</data> + <data key="price_type">fixed</data> + <data key="website_id">0</data> + <data key="customer_group">ALL GROUPS</data> + <data key="quantity">1</data> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedInventorySection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedInventorySection.xml index bc7c472df6eac..a4517cfd46168 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedInventorySection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedInventorySection.xml @@ -28,5 +28,7 @@ <element name="notifyBelowQty" type="input" selector="//*[@name='product[stock_data][notify_stock_qty]']"/> <element name="advancedInventoryQty" type="input" selector="//div[@class='modal-inner-wrap']//input[@name='product[quantity_and_stock_status][qty]']"/> <element name="advancedInventoryStockStatus" type="select" selector="//div[@class='modal-inner-wrap']//select[@name='product[quantity_and_stock_status][is_in_stock]']"/> + <element name="outOfStockThreshold" type="select" selector="//*[@name='product[stock_data][min_qty]']" timeout="30"/> + <element name="minQtyConfigSetting" type="checkbox" selector="//input[@name='product[stock_data][use_config_min_qty]']" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml index 697648cedb7ba..c0a1987ceceaa 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminProductFormAdvancedPricingSection"> <element name="customerGroupPriceAddButton" type="button" selector="[data-action='add_new_row']" timeout="30"/> + <element name="addCustomerGroupPrice" type="button" selector="//span[text()='Add']/ancestor::button" timeout="30"/> <element name="customerGroupPriceDeleteButton" type="button" selector="[data-action='remove_row']" timeout="30"/> <element name="advancedPricingCloseButton" type="button" selector=".product_form_product_form_advanced_pricing_modal button.action-close" timeout="30"/> <element name="productTierPriceWebsiteSelect" type="select" selector="[name='product[tier_price][{{var1}}][website_id]']" parameterized="true"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/ActionGroup/AdminAddDownloadableLinkInformationActionGroup.xml b/app/code/Magento/Downloadable/Test/Mftf/ActionGroup/AdminAddDownloadableLinkInformationActionGroup.xml new file mode 100644 index 0000000000000..37c6936cfb28a --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/ActionGroup/AdminAddDownloadableLinkInformationActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Add information before create downloadable link --> + <actionGroup name="AdminAddDownloadableLinkInformationActionGroup"> + <arguments> + <argument name="downloadableData" type="entity" defaultValue="downloadableData"/> + </arguments> + <click selector="{{AdminProductDownloadableSection.sectionHeader}}" stepKey="openDownloadableSection"/> + <checkOption selector="{{AdminProductDownloadableSection.isDownloadableProduct}}" stepKey="checkOptionIsDownloadable" after="openDownloadableSection"/> + <fillField userInput="{{downloadableData.link_title}}" selector="{{AdminProductDownloadableSection.linksTitleInput}}" stepKey="fillLinkTitle" after="checkOptionIsDownloadable"/> + <fillField userInput="{{downloadableData.sample_title}}" selector="{{AdminProductDownloadableSection.samplesTitleInput}}" stepKey="fillSampleTitle" after="fillLinkTitle"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml index 4bed31d9f854e..e22d3b2276fec 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml @@ -19,6 +19,17 @@ <data key="status">1</data> <data key="urlKey" unique="suffix">downloadableproduct</data> </entity> + <entity name="DownloadableProductOutOfStock" type="product"> + <data key="sku" unique="suffix">downloadableoutofstockproduct</data> + <data key="type_id">downloadable</data> + <data key="attribute_set_id">4</data> + <data key="name" unique="suffix">DownloadableProduct</data> + <data key="price">50.99</data> + <data key="quantity">100</data> + <data key="weight">0</data> + <data key="status">0</data> + <data key="urlKey" unique="suffix">downloadableproduct</data> + </entity> <entity name="DownloadableProductWithTwoLink" type="product"> <data key="sku" unique="suffix">downloadableproduct</data> <data key="type_id">downloadable</data> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Section/AdminProductDownloadableSection.xml b/app/code/Magento/Downloadable/Test/Mftf/Section/AdminProductDownloadableSection.xml index 274f26498958b..074ed55781103 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Section/AdminProductDownloadableSection.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Section/AdminProductDownloadableSection.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminProductDownloadableSection"> <element name="sectionHeader" type="button" selector="div[data-index='downloadable']" timeout="30" /> + <element name="sectionLinkGrid" type="text" selector="//div[@data-index='link']" timeout="30"/> <element name="isDownloadableProduct" type="input" selector="input[name='is_downloadable']" /> <element name="linksTitleInput" type="input" selector="input[name='product[links_title]']" /> <element name="isLinksPurchasedSeparately" type="input" selector="input[name='product[links_purchased_separately]']" /> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontDownloadableProductSection.xml b/app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontDownloadableProductSection.xml new file mode 100644 index 0000000000000..a1db2d4d94941 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontDownloadableProductSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontDownloadableProductSection"> + <element name="downloadableLinkBlock" type="text" selector="//div[contains(@class, 'field downloads required')]//span[text()='Downloadable Links']"/> + <element name="downloadableLinkLabel" type="text" selector="//label[contains(., '{{title}}')]" parameterized="true" timeout="30"/> + <element name="downloadableLinkByTitle" type="input" selector="//*[@id='downloadable-links-list']/*[contains(.,'{{title}}')]//input" parameterized="true" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml new file mode 100644 index 0000000000000..a47cef13a4d49 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductAndAssignItToCustomStoreTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create downloadable product and assign it to custom store test"/> + <description value="Admin should be able to create downloadable and assign it to custom website"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14516"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete created downloadable product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Delete store view --> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteCreatedStoreView"/> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create store view --> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView"/> + + <!-- Create Downloadable product --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <waitForPageLoad stepKey="waitForProductGridPageLoad"/> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createProduct"> + <argument name="productType" value="downloadable"/> + </actionGroup> + + <!-- Fill downloadable product values --> + <actionGroup ref="fillMainProductFormNoWeight" stepKey="fillDownloadableProductForm"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Add downloadable product to category --> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + + <!-- Fill downloadable link information before the creation link --> + <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> + + <!-- Links can be purchased separately --> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + + <!-- Add downloadable link --> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <argument name="link" value="downloadableLinkWithMaxDownloads"/> + </actionGroup> + + <!-- Save product --> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Switch default store view on store view created below --> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> + <waitForPageLoad stepKey="waitForStorefrontPageLoad"/> + <actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="SwitchStoreView"> + <argument name="storeView" value="customStore"/> + </actionGroup> + + <!-- Assert product in custom store --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPage" stepKey="AssertProductInStorefrontProductPage"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- See product link in storefront product page in custom store --> + <scrollTo selector="{{StorefrontDownloadableProductSection.downloadableLinkBlock}}" stepKey="scrollToLinksInStorefront"/> + <seeElement stepKey="seeDownloadableLink" selector="{{StorefrontDownloadableProductSection.downloadableLinkLabel(downloadableLinkWithMaxDownloads.title)}}"/> + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml new file mode 100644 index 0000000000000..7e19d7071fed4 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductWithCustomOptionsTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create downloadable product with custom options test"/> + <description value="Admin should be able to create downloadable product with custom options"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14508"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete created downloadable product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create Downloadable product --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <waitForPageLoad stepKey="waitForProductGridPageLoad"/> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createProduct"> + <argument name="productType" value="downloadable"/> + </actionGroup> + + <!-- Fill downloadable product values --> + <actionGroup ref="fillMainProductFormNoWeight" stepKey="fillDownloadableProductForm"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Add downloadable product to category --> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + + <!-- Open custom option panel --> + <click selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" stepKey="openCustomizableOptions"/> + <waitForPageLoad stepKey="waitForCustomOptionsOpen"/> + + <!-- Create a first custom option with 2 values --> + <actionGroup ref="AdminCreateCustomDropDownOptionsActionGroup" stepKey="createFirstCustomOption"> + <argument name="customOptionName" value="ProductOptionDropDown.title"/> + <argument name="firstOption" value="ProductOptionValueDropdown1"/> + <argument name="secondOption" value="ProductOptionValueDropdown2"/> + </actionGroup> + + <!-- Create a second custom option with 2 values --> + <actionGroup ref="AdminCreateCustomDropDownOptionsActionGroup" stepKey="createSecondCustomOption"> + <argument name="customOptionName" value="ProductOptionDropDownWithLongValuesTitle.title"/> + <argument name="firstOption" value="ProductOptionValueDropdown1"/> + <argument name="secondOption" value="ProductOptionValueDropdown2"/> + </actionGroup> + + <!-- Fill downloadable link information before the creation link --> + <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> + + <!-- Links can be purchased separately --> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + + <!-- Add downloadable link --> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <argument name="link" value="downloadableLinkWithMaxDownloads"/> + </actionGroup> + + <!-- Save product --> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Go to storefront category page --> + <amOnPage url="$$createCategory.name$$.html" stepKey="amOnCategoryPage"/> + <waitForPageLoad stepKey="waitForCategoryPageLoad"/> + + <!-- Assert product in storefront category page --> + <actionGroup ref="StorefrontCheckProductPriceInCategoryActionGroup" stepKey="StorefrontCheckCategorySimpleProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Assert product in storefront product page --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPage" stepKey="AssertProductInStorefrontProductPage"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Assert product custom options on product page --> + <seeElement stepKey="seeFirstOptionName" selector="{{StorefrontProductInfoMainSection.customOptionLabel(ProductOptionDropDown.title)}}"/> + <seeElement stepKey="seeSecondOptionName" selector="{{StorefrontProductInfoMainSection.customOptionLabel(ProductOptionDropDownWithLongValuesTitle.title)}}"/> + + <!-- Assert downloadable links data --> + <scrollTo selector="{{StorefrontDownloadableProductSection.downloadableLinkBlock}}" stepKey="scrollToLinks"/> + <seeElement stepKey="seeDownloadableLink" selector="{{StorefrontDownloadableProductSection.downloadableLinkLabel(downloadableLinkWithMaxDownloads.title)}}"/> + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml new file mode 100644 index 0000000000000..f78eee00fb486 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductWithLinkTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create downloadable product with default set links"/> + <description value="Admin should be able to create downloadable product with default set links"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14507"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete created downloadable product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create downloadable product --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <waitForPageLoad stepKey="waitForProductGridPageLoad"/> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createProduct"> + <argument name="productType" value="downloadable"/> + </actionGroup> + + <!-- Fill downloadable product values --> + <actionGroup ref="fillMainProductFormNoWeight" stepKey="fillDownloadableProductForm"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Add downloadable product to category --> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + + <!-- Fill downloadable link information before the creation link --> + <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> + + <!-- Links can be purchased separately --> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + + <!-- Add first downloadable link --> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <argument name="link" value="downloadableLinkWithMaxDownloads"/> + </actionGroup> + + <!-- Add second downloadable link --> + <actionGroup ref="addDownloadableProductLink" stepKey="addSecondDownloadableProductLink"> + <argument name="link" value="downloadableLink"/> + </actionGroup> + + <!-- Save product --> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Find downloadable product in grid --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPage"/> + <waitForPageLoad stepKey="waitForAdminProductPageLoad"/> + <actionGroup ref="filterProductGridBySku" stepKey="findCreatedConfigurableProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + <click selector="{{AdminProductGridSection.firstRow}}" stepKey="clickOnProduct"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + + <!-- Assert downloadable links in product form --> + <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + + <!-- Go to storefront category page --> + <amOnPage url="$$createCategory.name$$.html" stepKey="amOnCategoryPage"/> + <waitForPageLoad stepKey="waitForCategoryPageLoad"/> + + <!-- Assert product in storefront category page --> + <actionGroup ref="StorefrontCheckProductPriceInCategoryActionGroup" stepKey="StorefrontCheckCategorySimpleProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Assert product in storefront product page --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPage" stepKey="AssertProductInStorefrontProductPage"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- See product links in storefront product page --> + <scrollTo selector="{{StorefrontDownloadableProductSection.downloadableLinkBlock}}" stepKey="scrollToLinksInStorefront"/> + <seeElement stepKey="seeFirstDownloadableLink" selector="{{StorefrontDownloadableProductSection.downloadableLinkLabel(downloadableLinkWithMaxDownloads.title)}}"/> + <seeElement stepKey="seeSecondDownloadableLink" selector="{{StorefrontDownloadableProductSection.downloadableLinkLabel(downloadableLink.title)}}"/> + + <!-- Assert product in stock --> + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="In Stock" stepKey="seeProductStatusInStoreFront"/> + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml new file mode 100644 index 0000000000000..a4b44280cc951 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductWithGroupPriceTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create downloadable product with group price test"/> + <description value="Admin should be able to create downloadable product with group price"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14514"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete created downloadable product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="ApiDownloadableProduct"/> + </actionGroup> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create downloadable product --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <waitForPageLoad stepKey="waitForProductGridPageLoad"/> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createProduct"> + <argument name="productType" value="downloadable"/> + </actionGroup> + + <!-- Add group price to product --> + <actionGroup ref="AdminAddAdvancedPricingToTheProductActionGroup" stepKey="addCustomerGroupPrice"> + <argument name="index" value="0"/> + <argument name="groupPrice" value="simpleGroupPrice"/> + </actionGroup> + + <!-- Fill downloadable product values --> + <actionGroup ref="fillMainProductFormNoWeight" stepKey="fillDownloadableProductForm"> + <argument name="product" value="ApiDownloadableProduct"/> + </actionGroup> + + <!-- Add downloadable product to category --> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + + <!-- Fill downloadable link information before the creation link --> + <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> + + <!-- Links can be purchased separately --> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + + <!-- Add first downloadable link --> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <argument name="link" value="downloadableLinkWithMaxDownloads"/> + </actionGroup> + + <!-- Add second downloadable link --> + <actionGroup ref="addDownloadableProductLink" stepKey="addSecondDownloadableProductLink"> + <argument name="link" value="downloadableLink"/> + </actionGroup> + + <!-- Save product --> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Find downloadable product in grid --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPage"/> + <waitForPageLoad stepKey="waitForAdminProductPageLoad"/> + <actionGroup ref="filterProductGridBySku" stepKey="findCreatedConfigurableProduct"> + <argument name="product" value="ApiDownloadableProduct"/> + </actionGroup> + <click selector="{{AdminProductGridSection.firstRow}}" stepKey="clickOnProduct"/> + <waitForPageLoad stepKey="waitForProductFormPageLoad"/> + + <!-- Assert downloadable links in product form --> + <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + + <!-- Assert product in storefront product page --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPage" stepKey="AssertProductInStorefrontProductPage"> + <argument name="product" value="ApiDownloadableProduct"/> + </actionGroup> + + <!-- Assert group price in storefront product page --> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.updatedPrice}}" stepKey="grabGroupPrice"/> + <assertEquals expected='${{simpleGroupPrice.price}}' expectedType="string" actual="$grabGroupPrice" stepKey="assertGroupPrice"/> + + <!-- See product link in storefront product page --> + <scrollTo selector="{{StorefrontDownloadableProductSection.downloadableLinkBlock}}" stepKey="scrollToLinksInStorefront"/> + <seeElement stepKey="seeFirstDownloadableLink" selector="{{StorefrontDownloadableProductSection.downloadableLinkLabel(downloadableLinkWithMaxDownloads.title)}}"/> + <seeElement stepKey="seeSecondDownloadableLink" selector="{{StorefrontDownloadableProductSection.downloadableLinkLabel(downloadableLink.title)}}"/> + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml new file mode 100644 index 0000000000000..477e932c9ed74 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductWithDefaultSetLinksTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create Downloadable Product with link"/> + <description value="Admin should be able to create downloadable product with one simple link"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14506"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete created downloadable product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create downloadable product --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <waitForPageLoad stepKey="waitForProductGridPageLoad"/> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createProduct"> + <argument name="productType" value="downloadable"/> + </actionGroup> + + <!-- Fill downloadable product values --> + <actionGroup ref="fillMainProductFormNoWeight" stepKey="fillDownloadableProductForm"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Add downloadable product to category --> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + + <!-- Fill downloadable link information before the creation link --> + <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> + + <!-- Links can be purchased separately --> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + + <!-- Add downloadable link --> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <argument name="link" value="downloadableLinkWithMaxDownloads"/> + </actionGroup> + + <!-- Save product --> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Assert product in storefront category page --> + <amOnPage url="$$createCategory.name$$.html" stepKey="amOnCategoryPage"/> + <waitForPageLoad stepKey="waitForCategoryPageLoad"/> + <actionGroup ref="StorefrontCheckProductPriceInCategoryActionGroup" stepKey="StorefrontCheckCategorySimpleProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Assert product in storefront product page --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPage" stepKey="AssertProductInStorefrontProductPage"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Select product link in storefront product page--> + <scrollTo selector="{{StorefrontDownloadableProductSection.downloadableLinkBlock}}" stepKey="scrollToLinks"/> + <click selector="{{StorefrontDownloadableProductSection.downloadableLinkByTitle(downloadableLinkWithMaxDownloads.title)}}" stepKey="selectProductLink"/> + + <!-- Assert product price in storefront product page--> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="grabProductsPrice"/> + <assertEquals expected='$51.99' expectedType="string" actual="$grabProductsPrice" message="ExpectedPrice" stepKey="assertProductPrice"/> + + <!-- Add product with selected link to the cart --> + <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToCart" after="assertProductPrice"> + <argument name="product" value="DownloadableProduct"/> + <argument name="productCount" value="1"/> + </actionGroup> + + <!-- Assert product price in cart --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="openShoppingCartPage"/> + <waitForPageLoad stepKey="waitForShoppingCartPageLoad"/> + <assertEquals expected='$51.99' expectedType="string" actual="$grabProductsPrice" message="ExpectedPrice" stepKey="assertProductPriceInCart"/> + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml new file mode 100644 index 0000000000000..47ff348ebaab7 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductWithManageStockTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create downloadable product with manage stock test"/> + <description value="Admin should be able to create downloadable product with manage stock"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14510"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete created downloadable product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create downloadable product --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <waitForPageLoad stepKey="waitForProductGridPageLoad"/> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createProduct"> + <argument name="productType" value="downloadable"/> + </actionGroup> + + <!-- Fill downloadable product values --> + <actionGroup ref="fillMainProductFormNoWeight" stepKey="fillDownloadableProductForm"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Add advanced inventory data to downloadable product --> + <actionGroup ref="AdminClickOnAdvancedInventoryLinkActionGroup" stepKey="clickOnAdvancedInventoryLink"/> + + <actionGroup ref="AdminFillAdvancedInventoryQtyActionGroup" stepKey="fillAdvancedInventoryQty"> + <argument name="qty" value="{{DownloadableProduct.quantity}}"/> + </actionGroup> + + <actionGroup ref="AdminFillAdvancedInventoryOutOfStockThresholdActionGroup" stepKey="fillAdvancedInventoryOutOfStockThreshold"> + <argument name="qty" value="{{DownloadableProduct.quantity}}"/> + </actionGroup> + + <actionGroup ref="AdminSubmitAdvancedInventoryFormActionGroup" stepKey="clickDoneBtn"/> + + <!-- Add downloadable product to category --> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + + <!-- Fill downloadable link information before the creation link --> + <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> + + <!-- Links can be purchased separately --> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + + <!-- Add first downloadable link --> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <argument name="link" value="downloadableLinkWithMaxDownloads"/> + </actionGroup> + + <!-- Add second downloadable link --> + <actionGroup ref="addDownloadableProductLink" stepKey="addSecondDownloadableProductLink"> + <argument name="link" value="downloadableLink"/> + </actionGroup> + + <!-- Save product --> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Find downloadable product in grid --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPage"/> + <waitForPageLoad stepKey="waitForAdminProductPageLoad"/> + <actionGroup ref="filterProductGridBySku" stepKey="findCreatedConfigurableProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + <click selector="{{AdminProductGridSection.firstRow}}" stepKey="clickOnProduct"/> + <waitForPageLoad stepKey="waitForProductFormPageLoad"/> + + <!-- Assert downloadable links in product form --> + <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + + <!-- Assert product is out of stock in store front --> + <amOnPage url="{{DownloadableProduct.urlKey}}.html" stepKey="navigateToProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{DownloadableProduct.name}}" stepKey="seeProductNameInStoreFront"/> + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="OUT OF STOCK" stepKey="seeProductStatusInStoreFront"/> + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml new file mode 100644 index 0000000000000..6f369c00f25ac --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductWithOutOfStockStatusTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create downloadable product with out of stock status test"/> + <description value="Admin should be able to create downloadable product with out of stock status"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14509"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete created downloadable product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="DownloadableProductOutOfStock"/> + </actionGroup> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create Downloadable product --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <waitForPageLoad stepKey="waitForProductGridPageLoad"/> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createProduct"> + <argument name="productType" value="downloadable"/> + </actionGroup> + + <!-- Fill downloadable product values --> + <actionGroup ref="fillMainProductFormNoWeight" stepKey="fillDownloadableProductForm"> + <argument name="product" value="DownloadableProductOutOfStock"/> + </actionGroup> + + <!-- Add downloadable product to category --> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + + <!-- Fill downloadable link information before the creation link --> + <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> + + <!-- Links can be purchased separately --> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + + <!-- Add first downloadable link --> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <argument name="link" value="downloadableLinkWithMaxDownloads"/> + </actionGroup> + + <!-- Add second downloadable link --> + <actionGroup ref="addDownloadableProductLink" stepKey="addSecondDownloadableProductLink"> + <argument name="link" value="downloadableLink"/> + </actionGroup> + + <!-- Save product --> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Assert product is out of stock --> + <amOnPage url="{{DownloadableProductOutOfStock.urlKey}}.html" stepKey="navigateToProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="OUT OF STOCK" stepKey="seeProductStatusInStoreFront"/> + + <!-- Find downloadable product in grid --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPage"/> + <waitForPageLoad stepKey="waitForAdminProductPageLoad"/> + <actionGroup ref="filterProductGridBySku" stepKey="findCreatedConfigurableProduct"> + <argument name="product" value="DownloadableProductOutOfStock"/> + </actionGroup> + <click selector="{{AdminProductGridSection.firstRow}}" stepKey="clickOnProduct"/> + <waitForPageLoad stepKey="waitForProductFormPageLoad"/> + + <!-- Assert downloadable links in product form --> + <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml new file mode 100644 index 0000000000000..267b6bb6f883a --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductWithSpecialPriceTest" extends="AdminCreateDownloadableProductWithGroupPriceTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create downloadable product with special price test"/> + <description value="Admin should be able to create downloadable product with special price"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14513"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <remove keyForRemoval="addCustomerGroupPrice"/> + + <!-- Add special price to product --> + <actionGroup ref="AddSpecialPriceToProductActionGroup" stepKey="setSpecialPriceToCreatedProduct" after="createProduct"> + <argument name="price" value="{{specialProductPrice.price}}"/> + </actionGroup> + + <remove keyForRemoval="grabGroupPrice"/> + <remove keyForRemoval="assertGroupPrice"/> + + <!-- Assert special price in storefront product page --> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.specialPriceValue}}" stepKey="grabSpecialPrice" after="AssertProductInStorefrontProductPage"/> + <assertEquals expected='${{specialProductPrice.price}}' expectedType="string" actual="$grabSpecialPrice" stepKey="assertSpecialPrice"/> + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml new file mode 100644 index 0000000000000..a34393b5f8e92 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductWithTierPriceText" extends="AdminCreateDownloadableProductWithGroupPriceTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create downloadable product with tier price test"/> + <description value="Admin should be able to create downloadable with tier price"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14515"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <remove keyForRemoval="addCustomerGroupPrice"/> + + <!-- Add tier price to product --> + <actionGroup ref="AdminAddAdvancedPricingToTheProductActionGroup" stepKey="addCustomerTierPrice" after="createProduct"> + <argument name="index" value="0"/> + <argument name="groupPrice" value="tierProductPrice"/> + </actionGroup> + + <remove keyForRemoval="grabGroupPrice"/> + <remove keyForRemoval="assertGroupPrice"/> + + <!-- Assert tier price in storefront product page --> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.tierPriceText}}" stepKey="tierPriceText" after="AssertProductInStorefrontProductPage"/> + <assertEquals stepKey="assertTierPriceTextOnProductPage"> + <expectedResult type="string">Buy {{tierProductPrice.quantity}} for ${{tierProductPrice.price}} each and save 27%</expectedResult> + <actualResult type="variable">tierPriceText</actualResult> + </assertEquals> + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml new file mode 100644 index 0000000000000..5948c19cb8026 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create downloadable product without filling quantity and stock test"/> + <description value="Admin should be able to create downloadable product without filling quantity and stock"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14512"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete created downloadable product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create downloadable product --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <waitForPageLoad stepKey="waitForProductGridPageLoad"/> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createProduct"> + <argument name="productType" value="downloadable"/> + </actionGroup> + + <!-- Fill downloadable product values --> + <actionGroup ref="fillMainProductFormNoWeight" stepKey="fillDownloadableProductForm"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <clearField selector="{{AdminProductFormSection.productQuantity}}" stepKey="clearProductQty" after="fillDownloadableProductForm"/> + + <!-- Add downloadable product to category --> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + + <!-- Fill downloadable link information before the creation link --> + <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> + + <!-- Links can be purchased separately --> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + + <!-- Add first downloadable link --> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <argument name="link" value="downloadableLinkWithMaxDownloads"/> + </actionGroup> + + <!-- Add second downloadable link --> + <actionGroup ref="addDownloadableProductLink" stepKey="addSecondDownloadableProductLink"> + <argument name="link" value="downloadableLink"/> + </actionGroup> + + <!-- Save product --> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Find downloadable product in grid --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPage"/> + <waitForPageLoad stepKey="waitForAdminProductPageLoad"/> + <actionGroup ref="filterProductGridBySku" stepKey="findCreatedConfigurableProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + <click selector="{{AdminProductGridSection.firstRow}}" stepKey="clickOnProduct"/> + <waitForPageLoad stepKey="waitForProductFormPageLoad"/> + + <!-- Assert downloadable links in product form --> + <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + + <!-- See stock status--> + <seeOptionIsSelected selector="{{AdminProductFormSection.productStockStatus}}" userInput="Out of Stock" stepKey="seeStockStatus"/> + + <!-- Assert product is out of stock --> + <amOnPage url="{{DownloadableProduct.urlKey}}.html" stepKey="navigateToProductPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="OUT OF STOCK" stepKey="seeProductStatusInStoreFront"/> + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml new file mode 100644 index 0000000000000..da691b207cac2 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDownloadableProductWithoutTaxClassIdTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create Downloadable Product"/> + <title value="Create downloadable product without tax class id test"/> + <description value="Admin should be able to create downloadable product without tax class id"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14511"/> + <group value="Downloadable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete created downloadable product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create downloadable product --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <waitForPageLoad stepKey="waitForProductGridPageLoad"/> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createProduct"> + <argument name="productType" value="downloadable"/> + </actionGroup> + + <!-- Fill downloadable product values --> + <actionGroup ref="fillMainProductFormNoWeight" stepKey="fillDownloadableProductForm"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- Tax class id = "none" --> + <selectOption selector="{{AdminProductFormBundleSection.taxClassDropDown}}" userInput="None" stepKey="taxClassDropDown"/> + + <!-- Add downloadable product to category --> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="taxClassDropDown"/> + + <!-- Fill downloadable link information before the creation link --> + <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> + + <!-- Links can be purchased separately --> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + + <!-- Add first downloadable link --> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <argument name="link" value="downloadableLinkWithMaxDownloads"/> + </actionGroup> + + <!-- Add second downloadable link --> + <actionGroup ref="addDownloadableProductLink" stepKey="addSecondDownloadableProductLink"> + <argument name="link" value="downloadableLink"/> + </actionGroup> + + <!-- Save product --> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Find downloadable product in grid --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPage"/> + <waitForPageLoad stepKey="waitForAdminProductPageLoad"/> + <actionGroup ref="filterProductGridBySku" stepKey="findCreatedConfigurableProduct"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + <click selector="{{AdminProductGridSection.firstRow}}" stepKey="clickOnProduct"/> + <waitForPageLoad stepKey="waitForProductFormPageLoad"/> + + <!-- Assert downloadable links in product form --> + <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + + <!-- Assert product in storefront product page --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPage" stepKey="AssertProductInStorefrontProductPage"> + <argument name="product" value="DownloadableProduct"/> + </actionGroup> + + <!-- See product link in storefront product page --> + <scrollTo selector="{{StorefrontDownloadableProductSection.downloadableLinkBlock}}" stepKey="scrollToLinksInStorefront"/> + <seeElement stepKey="seeFirstDownloadableLink" selector="{{StorefrontDownloadableProductSection.downloadableLinkLabel(downloadableLinkWithMaxDownloads.title)}}"/> + <seeElement stepKey="seeSecondDownloadableLink" selector="{{StorefrontDownloadableProductSection.downloadableLinkLabel(downloadableLink.title)}}"/> + </test> +</tests> From 7d0d01e327a54b460d334165e7a68fcae7456f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20F=C3=BChr?= <d.fuehr@techdivision.com> Date: Wed, 20 Mar 2019 00:30:02 +0100 Subject: [PATCH 063/585] 21842 - do not cache absolute file paths Github issue: https://github.com/magento/magento2/issues/21842 In customer and customer_address validation context the validator factory no longer caches absolute file paths for the validation.xml files (currently two file) as the file content is evaluated later in the filesystem directly and the file paths may not be correct in a multi server setup with shared cache (id_prefix) --- lib/internal/Magento/Framework/Validator/Factory.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/internal/Magento/Framework/Validator/Factory.php b/lib/internal/Magento/Framework/Validator/Factory.php index f2089c662e955..4e82c89720462 100644 --- a/lib/internal/Magento/Framework/Validator/Factory.php +++ b/lib/internal/Magento/Framework/Validator/Factory.php @@ -75,17 +75,7 @@ public function __construct( protected function _initializeConfigList() { if (!$this->_configFiles) { - $this->_configFiles = $this->cache->load(self::CACHE_KEY); - if (!$this->_configFiles) { - $this->_configFiles = $this->moduleReader->getConfigurationFiles('validation.xml'); - $this->cache->save( - $this->getSerializer()->serialize($this->_configFiles->toArray()), - self::CACHE_KEY - ); - } else { - $filesArray = $this->getSerializer()->unserialize($this->_configFiles); - $this->_configFiles = $this->getFileIteratorFactory()->create(array_keys($filesArray)); - } + $this->_configFiles = $this->moduleReader->getConfigurationFiles('validation.xml'); } } From e266d9af43a01fce13d98001b335bf69b4219eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20F=C3=BChr?= <d.fuehr@techdivision.com> Date: Wed, 20 Mar 2019 11:46:41 +0100 Subject: [PATCH 064/585] clean up Validator Factory - adapt unit test --- .../Magento/Framework/Validator/Factory.php | 90 +++++-------------- .../Validator/Test/Unit/FactoryTest.php | 76 +--------------- 2 files changed, 24 insertions(+), 142 deletions(-) diff --git a/lib/internal/Magento/Framework/Validator/Factory.php b/lib/internal/Magento/Framework/Validator/Factory.php index 4e82c89720462..7a9eacac6ddbe 100644 --- a/lib/internal/Magento/Framework/Validator/Factory.php +++ b/lib/internal/Magento/Framework/Validator/Factory.php @@ -6,24 +6,26 @@ namespace Magento\Framework\Validator; -use Magento\Framework\Cache\FrontendInterface; +use Magento\Framework\Module\Dir\Reader; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Validator; +/** + * Factory for \Magento\Framework\Validator and \Magento\Framework\Validator\Builder. + */ class Factory { - /** cache key */ - const CACHE_KEY = __CLASS__; - /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ protected $_objectManager; /** * Validator config files * - * @var array|null + * @var iterable|null */ - protected $_configFiles = null; + protected $_configFiles; /** * @var bool @@ -31,40 +33,22 @@ class Factory private $isDefaultTranslatorInitialized = false; /** - * @var \Magento\Framework\Module\Dir\Reader + * @var Reader */ private $moduleReader; - /** - * @var FrontendInterface - */ - private $cache; - - /** - * @var \Magento\Framework\Serialize\SerializerInterface - */ - private $serializer; - - /** - * @var \Magento\Framework\Config\FileIteratorFactory - */ - private $fileIteratorFactory; - /** * Initialize dependencies * - * @param \Magento\Framework\ObjectManagerInterface $objectManager - * @param \Magento\Framework\Module\Dir\Reader $moduleReader - * @param FrontendInterface $cache + * @param ObjectManagerInterface $objectManager + * @param Reader $moduleReader */ public function __construct( - \Magento\Framework\ObjectManagerInterface $objectManager, - \Magento\Framework\Module\Dir\Reader $moduleReader, - FrontendInterface $cache + ObjectManagerInterface $objectManager, + Reader $moduleReader ) { $this->_objectManager = $objectManager; $this->moduleReader = $moduleReader; - $this->cache = $cache; } /** @@ -83,6 +67,7 @@ protected function _initializeConfigList() * Create and set default translator to \Magento\Framework\Validator\AbstractValidator. * * @return void + * @throws \Zend_Translate_Exception */ protected function _initializeDefaultTranslator() { @@ -95,7 +80,7 @@ protected function _initializeDefaultTranslator() /** @var \Magento\Framework\Translate\Adapter $translator */ $translator = $this->_objectManager->create(\Magento\Framework\Translate\Adapter::class); $translator->setOptions(['translator' => $translatorCallback]); - \Magento\Framework\Validator\AbstractValidator::setDefaultTranslator($translator); + AbstractValidator::setDefaultTranslator($translator); $this->isDefaultTranslatorInitialized = true; } } @@ -105,14 +90,15 @@ protected function _initializeDefaultTranslator() * * Will instantiate \Magento\Framework\Validator\Config * - * @return \Magento\Framework\Validator\Config + * @return Config + * @throws \Zend_Translate_Exception */ public function getValidatorConfig() { $this->_initializeConfigList(); $this->_initializeDefaultTranslator(); return $this->_objectManager->create( - \Magento\Framework\Validator\Config::class, + Config::class, ['configFiles' => $this->_configFiles] ); } @@ -123,7 +109,8 @@ public function getValidatorConfig() * @param string $entityName * @param string $groupName * @param array|null $builderConfig - * @return \Magento\Framework\Validator\Builder + * @return Builder + * @throws \Zend_Translate_Exception */ public function createValidatorBuilder($entityName, $groupName, array $builderConfig = null) { @@ -137,43 +124,12 @@ public function createValidatorBuilder($entityName, $groupName, array $builderCo * @param string $entityName * @param string $groupName * @param array|null $builderConfig - * @return \Magento\Framework\Validator + * @return Validator + * @throws \Zend_Translate_Exception */ public function createValidator($entityName, $groupName, array $builderConfig = null) { $this->_initializeDefaultTranslator(); return $this->getValidatorConfig()->createValidator($entityName, $groupName, $builderConfig); } - - /** - * Get serializer - * - * @return \Magento\Framework\Serialize\SerializerInterface - * @deprecated 100.2.0 - */ - private function getSerializer() - { - if ($this->serializer === null) { - $this->serializer = $this->_objectManager->get( - \Magento\Framework\Serialize\SerializerInterface::class - ); - } - return $this->serializer; - } - - /** - * Get file iterator factory - * - * @return \Magento\Framework\Config\FileIteratorFactory - * @deprecated 100.2.0 - */ - private function getFileIteratorFactory() - { - if ($this->fileIteratorFactory === null) { - $this->fileIteratorFactory = $this->_objectManager->get( - \Magento\Framework\Config\FileIteratorFactory::class - ); - } - return $this->fileIteratorFactory; - } } diff --git a/lib/internal/Magento/Framework/Validator/Test/Unit/FactoryTest.php b/lib/internal/Magento/Framework/Validator/Test/Unit/FactoryTest.php index 5511627c6dcc3..73a8c95c9a2ff 100644 --- a/lib/internal/Magento/Framework/Validator/Test/Unit/FactoryTest.php +++ b/lib/internal/Magento/Framework/Validator/Test/Unit/FactoryTest.php @@ -25,21 +25,6 @@ class FactoryTest extends \PHPUnit\Framework\TestCase */ private $validatorConfigMock; - /** - * @var \Magento\Framework\Cache\FrontendInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $cacheMock; - - /** - * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $serializerMock; - - /** - * @var \Magento\Framework\Config\FileIteratorFactory|\PHPUnit_Framework_MockObject_MockObject - */ - private $fileIteratorFactoryMock; - /** * @var \Magento\Framework\Config\FileIterator|\PHPUnit_Framework_MockObject_MockObject */ @@ -55,11 +40,6 @@ class FactoryTest extends \PHPUnit\Framework\TestCase */ private $factory; - /** - * @var string - */ - private $jsonString = '["\/tmp\/moduleOne\/etc\/validation.xml"]'; - /** * @var array */ @@ -99,23 +79,9 @@ protected function setUp() \Magento\Framework\Validator\Factory::class, [ 'objectManager' => $this->objectManagerMock, - 'moduleReader' => $this->readerMock, - 'cache' => $this->cacheMock + 'moduleReader' => $this->readerMock ] ); - - $this->serializerMock = $this->createMock(\Magento\Framework\Serialize\SerializerInterface::class); - $this->fileIteratorFactoryMock = $this->createMock(\Magento\Framework\Config\FileIteratorFactory::class); - $objectManager->setBackwardCompatibleProperty( - $this->factory, - 'serializer', - $this->serializerMock - ); - $objectManager->setBackwardCompatibleProperty( - $this->factory, - 'fileIteratorFactory', - $this->fileIteratorFactoryMock - ); } /** @@ -147,46 +113,6 @@ public function testGetValidatorConfig() ); } - public function testGetValidatorConfigCacheNotExist() - { - $this->cacheMock->expects($this->once()) - ->method('load') - ->willReturn(false); - $this->readerMock->expects($this->once()) - ->method('getConfigurationFiles') - ->willReturn($this->fileIteratorMock); - $this->fileIteratorMock->method('toArray') - ->willReturn($this->data); - $this->cacheMock->expects($this->once()) - ->method('save') - ->with($this->jsonString); - $this->serializerMock->expects($this->once()) - ->method('serialize') - ->with($this->data) - ->willReturn($this->jsonString); - $this->factory->getValidatorConfig(); - $this->factory->getValidatorConfig(); - } - - public function testGetValidatorConfigCacheExist() - { - $this->cacheMock->expects($this->once()) - ->method('load') - ->willReturn($this->jsonString); - $this->readerMock->expects($this->never()) - ->method('getConfigurationFiles'); - $this->cacheMock->expects($this->never()) - ->method('save'); - $this->serializerMock->expects($this->once()) - ->method('unserialize') - ->with($this->jsonString) - ->willReturn($this->data); - $this->fileIteratorFactoryMock->method('create') - ->willReturn($this->fileIteratorMock); - $this->factory->getValidatorConfig(); - $this->factory->getValidatorConfig(); - } - public function testCreateValidatorBuilder() { $this->readerMock->method('getConfigurationFiles') From 83b34b89b5caffb1b2eef74423090e7f343b0e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20F=C3=BChr?= <d.fuehr@techdivision.com> Date: Wed, 20 Mar 2019 14:48:40 +0100 Subject: [PATCH 065/585] untouch static method call to prevent codacy fail - refactoring of static method use should be in a separate pull request --- lib/internal/Magento/Framework/Validator/Factory.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Validator/Factory.php b/lib/internal/Magento/Framework/Validator/Factory.php index 7a9eacac6ddbe..198f4fb6730fa 100644 --- a/lib/internal/Magento/Framework/Validator/Factory.php +++ b/lib/internal/Magento/Framework/Validator/Factory.php @@ -8,6 +8,7 @@ use Magento\Framework\Module\Dir\Reader; use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Phrase; use Magento\Framework\Validator; /** @@ -75,12 +76,12 @@ protected function _initializeDefaultTranslator() // Pass translations to \Magento\Framework\TranslateInterface from validators $translatorCallback = function () { $argc = func_get_args(); - return (string)new \Magento\Framework\Phrase(array_shift($argc), $argc); + return (string)new Phrase(array_shift($argc), $argc); }; /** @var \Magento\Framework\Translate\Adapter $translator */ $translator = $this->_objectManager->create(\Magento\Framework\Translate\Adapter::class); $translator->setOptions(['translator' => $translatorCallback]); - AbstractValidator::setDefaultTranslator($translator); + \Magento\Framework\Validator\AbstractValidator::setDefaultTranslator($translator); $this->isDefaultTranslatorInitialized = true; } } From 791b47ca8cb58e91c01d9c35ab18aa28742b173f Mon Sep 17 00:00:00 2001 From: Denys Saltanahmedov <d.saltanakhmedov@atwix.com> Date: Wed, 20 Mar 2019 16:42:49 +0200 Subject: [PATCH 066/585] Adding delete customer group test case #581 --- .../Mftf/Test/DeleteCustomerGroupTest.xml | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml new file mode 100644 index 0000000000000..e5f889a068067 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="DeleteCustomerGroup"> + <annotations> + <title value="Delete customer group group"/> + <description value="Delete a customer group"/> + <stories value="Delete Customer Group"/> + <group value="customers"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <actionGroup ref="AdminCreateCustomerGroupActionGroup" stepKey="createCustomerGroup"> + <argument name="groupName" value="{{CustomerGroupChange.code}}"/> + <argument name="taxClass" value="{{CustomerGroupChange.tax_class_name}}"/> + </actionGroup> + <actionGroup ref="NavigateToAllCustomerPage" stepKey="navToCustomersCreate"/> + <actionGroup ref="AdminFilterCustomerByName" stepKey="filterCustomer"> + <argument name="customerName" value="{{Simple_US_Customer.fullname}}"/> + </actionGroup> + <actionGroup ref="AdminSelectCustomerByEmail" stepKey="selectCustomer"> + <argument name="customerEmail" value="$$createCustomer.email$$"/> + </actionGroup> + <actionGroup ref="SetCustomerGroupForSelectedCustomersViaGrid" stepKey="setCustomerGroup"> + <argument name="groupName" value="{{CustomerGroupChange.code}}"/> + </actionGroup> + <actionGroup ref="AdminFilterCustomerByName" stepKey="filterCustomerAfterGroupChange"> + <argument name="customerName" value="{{Simple_US_Customer.fullname}}"/> + </actionGroup> + <actionGroup ref="VerifyCustomerGroupForCustomer" stepKey="verifyCustomerGroupSet"> + <argument name="customerEmail" value="$$createCustomer.email$$"/> + <argument name="groupName" value="{{CustomerGroupChange.code}}"/> + </actionGroup> + <!--Customer Group success delete message--> + <actionGroup ref="AdminDeleteCustomerGroupActionGroup" stepKey="deleteCustomerGroup"> + <argument name="customerGroupName" value="{{CustomerGroupChange.code}}"/> + </actionGroup> + + <!--Customer Group is not in grid--> + <actionGroup ref="NavigateToCustomerGroupPage" stepKey="navToCustomerGroupPage"/> + + <!--Customer Group changed to "General" on customer form--> + <actionGroup ref="NavigateToAllCustomerPage" stepKey="navToCustomers"/> + <actionGroup ref="AdminFilterCustomerByName" stepKey="filterCustomerAfterGroupDelete"> + <argument name="customerName" value="{{Simple_US_Customer.fullname}}"/> + </actionGroup> + <actionGroup ref="AdminSelectCustomerByEmail" stepKey="selectCustomerAfterGroupDelete"> + <argument name="customerEmail" value="$$createCustomer.email$$"/> + </actionGroup> + <actionGroup ref="VerifyCustomerGroupForCustomer" stepKey="verifyGeneralGroupSet"> + <argument name="customerEmail" value="$$createCustomer.email$$"/> + <argument name="groupName" value="{{GeneralCustomerGroup.code}}"/> + </actionGroup> + </test> +</tests> From 8652bc88614875920ecb506c45dff777b2069701 Mon Sep 17 00:00:00 2001 From: Jitheesh <jitheeshvo@gmail.com> Date: Thu, 21 Mar 2019 09:48:30 +0530 Subject: [PATCH 067/585] - CR fix --- .../Observer/UpdateLinkPurchasedObserver.php | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php index d9d743a052446..067c91981cd89 100644 --- a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php +++ b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php @@ -3,13 +3,15 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Downloadable\Observer; use Magento\Framework\Event\ObserverInterface; /** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * Class UpdateLinkPurchasedObserver + * Assign Downloadable links to customer created after issuing guest order. */ class UpdateLinkPurchasedObserver implements ObserverInterface { @@ -17,17 +19,17 @@ class UpdateLinkPurchasedObserver implements ObserverInterface * Core store config * @var \Magento\Framework\App\Config\ScopeConfigInterface */ - protected $_scopeConfig; + private $scopeConfig; /** * @var \Magento\Downloadable\Model\ResourceModel\Link\Purchased\CollectionFactory */ - protected $_purchasedFactory; + private $purchasedFactory; /** * @var \Magento\Framework\DataObject\Copy */ - protected $_objectCopyService; + private $objectCopyService; /** * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig @@ -39,9 +41,9 @@ public function __construct( \Magento\Downloadable\Model\ResourceModel\Link\Purchased\CollectionFactory $purchasedFactory, \Magento\Framework\DataObject\Copy $objectCopyService ) { - $this->_scopeConfig = $scopeConfig; - $this->_purchasedFactory = $purchasedFactory; - $this->_objectCopyService = $objectCopyService; + $this->scopeConfig = $scopeConfig; + $this->purchasedFactory = $purchasedFactory; + $this->objectCopyService = $objectCopyService; } /** @@ -58,13 +60,13 @@ public function execute(\Magento\Framework\Event\Observer $observer) return $this; } - $purchasedLinks = $this->_createPurchasedCollection()->addFieldToFilter( + $purchasedLinks = $this->purchasedFactory->create()->addFieldToFilter( 'order_id', ['eq' => $order->getId()] ); foreach ($purchasedLinks as $linkPurchased) { - $this->_objectCopyService->copyFieldsetToTarget( + $this->objectCopyService->copyFieldsetToTarget( \downloadable_sales_copy_order::class, 'to_downloadable', $order, @@ -75,12 +77,4 @@ public function execute(\Magento\Framework\Event\Observer $observer) return $this; } - - /** - * @return \Magento\Downloadable\Model\ResourceModel\Link\Purchased\Collection - */ - protected function _createPurchasedCollection() - { - return $this->_purchasedFactory->create(); - } } From 2f49a5c430d1fc805ef0471b4d604d58b6ba0234 Mon Sep 17 00:00:00 2001 From: Lorenzo Stramaccia <lorenzo.stramaccia@magespecialist.it> Date: Thu, 21 Mar 2019 10:48:53 +0100 Subject: [PATCH 068/585] Fix importFromArray by setting _isCollectionLoaded to true after import --- .../Magento/Eav/Model/Entity/Collection/AbstractCollection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index dad420ea0b375..05c6d989fa130 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -1061,6 +1061,7 @@ public function importFromArray($arr) $this->_items[$entityId]->addData($row); } } + $this->_setIsLoaded(); return $this; } From f92c8fd2b031531bac32615ab80ca09a66665617 Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Thu, 21 Mar 2019 14:46:56 +0300 Subject: [PATCH 069/585] MAGETWO-98584: Google chart API used by Magento dashboard scheduled to be turned off --- .../Magento/Backend/Block/Dashboard/Graph.php | 80 +++++-------------- 1 file changed, 21 insertions(+), 59 deletions(-) diff --git a/app/code/Magento/Backend/Block/Dashboard/Graph.php b/app/code/Magento/Backend/Block/Dashboard/Graph.php index 8e238ccab44cb..71a6cf4e938f2 100644 --- a/app/code/Magento/Backend/Block/Dashboard/Graph.php +++ b/app/code/Magento/Backend/Block/Dashboard/Graph.php @@ -15,7 +15,7 @@ class Graph extends \Magento\Backend\Block\Dashboard\AbstractDashboard /** * Api URL */ - const API_URL = 'http://chart.apis.google.com/chart'; + const API_URL = 'https://image-charts.com/chart'; /** * All series @@ -76,6 +76,7 @@ class Graph extends \Magento\Backend\Block\Dashboard\AbstractDashboard /** * Google chart api data encoding * + * @deprecated since the Google Image Charts API not accessible from March 14, 2019 * @var string */ protected $_encoding = 'e'; @@ -187,11 +188,12 @@ public function getChartUrl($directUrl = true) { $params = [ 'cht' => 'lc', - 'chf' => 'bg,s,ffffff', - 'chco' => 'ef672f', 'chls' => '7', - 'chxs' => '0,676056,15,0,l,676056|1,676056,15,0,l,676056', - 'chm' => 'h,f2ebde,0,0:1:.1,1,-1', + 'chf' => 'bg,s,f4f4f4|c,lg,90,ffffff,0.1,ededed,0', + 'chm' => 'B,f4d4b2,0,0,0', + 'chco' => 'db4814', + 'chxs' => '0,0,11|1,0,11', + 'chma' => '15,15,15,15' ]; $this->_allSeries = $this->getRowsData($this->_dataRows); @@ -279,20 +281,11 @@ public function getChartUrl($directUrl = true) $this->_axisLabels['x'] = $dates; $this->_allSeries = $datas; - //Google encoding values - if ($this->_encoding == "s") { - // simple encoding - $params['chd'] = "s:"; - $dataDelimiter = ""; - $dataSetdelimiter = ","; - $dataMissing = "_"; - } else { - // extended encoding - $params['chd'] = "e:"; - $dataDelimiter = ""; - $dataSetdelimiter = ","; - $dataMissing = "__"; - } + // Image-Charts Awesome data format values + $params['chd'] = "a:"; + $dataDelimiter = ","; + $dataSetdelimiter = "|"; + $dataMissing = "_"; // process each string in the array, and find the max length $localmaxvalue = [0]; @@ -306,7 +299,6 @@ public function getChartUrl($directUrl = true) $minvalue = min($localminvalue); // default values - $yrange = 0; $yLabels = []; $miny = 0; $maxy = 0; @@ -321,7 +313,6 @@ public function getChartUrl($directUrl = true) $maxy = ceil($maxvalue + 1); $yLabels = range($miny, $maxy, 1); } - $yrange = $maxy; $yorigin = 0; } @@ -329,44 +320,13 @@ public function getChartUrl($directUrl = true) foreach ($this->getAllSeries() as $index => $serie) { $thisdataarray = $serie; - if ($this->_encoding == "s") { - // SIMPLE ENCODING - for ($j = 0; $j < sizeof($thisdataarray); $j++) { - $currentvalue = $thisdataarray[$j]; - if (is_numeric($currentvalue)) { - $ylocation = round( - (strlen($this->_simpleEncoding) - 1) * ($yorigin + $currentvalue) / $yrange - ); - $chartdata[] = substr($this->_simpleEncoding, $ylocation, 1) . $dataDelimiter; - } else { - $chartdata[] = $dataMissing . $dataDelimiter; - } - } - } else { - // EXTENDED ENCODING - for ($j = 0; $j < sizeof($thisdataarray); $j++) { - $currentvalue = $thisdataarray[$j]; - if (is_numeric($currentvalue)) { - if ($yrange) { - $ylocation = 4095 * ($yorigin + $currentvalue) / $yrange; - } else { - $ylocation = 0; - } - $firstchar = floor($ylocation / 64); - $secondchar = $ylocation % 64; - $mappedchar = substr( - $this->_extendedEncoding, - $firstchar, - 1 - ) . substr( - $this->_extendedEncoding, - $secondchar, - 1 - ); - $chartdata[] = $mappedchar . $dataDelimiter; - } else { - $chartdata[] = $dataMissing . $dataDelimiter; - } + for ($j = 0; $j < sizeof($thisdataarray); $j++) { + $currentvalue = $thisdataarray[$j]; + if (is_numeric($currentvalue)) { + $ylocation = $yorigin + $currentvalue; + $chartdata[] = $ylocation . $dataDelimiter; + } else { + $chartdata[] = $dataMissing . $dataDelimiter; } } $chartdata[] = $dataSetdelimiter; @@ -540,6 +500,8 @@ protected function getHeight() } /** + * Sets data helper + * * @param \Magento\Backend\Helper\Dashboard\AbstractDashboard $dataHelper * @return void */ From 6351911a168dc8c2b62abea2c7c171581e0dee9e Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Thu, 21 Mar 2019 15:13:50 -0500 Subject: [PATCH 070/585] MC-4871: Convert CreateStoreEntityTest to MFTF Addressing review comments --- ...rtStoreConfigurationBackendActionGroup.xml | 27 ++++++++++++++++++ .../AssertStoreFrontendActionGroup.xml | 28 +++++++++++++++++++ ...rontStoreNotVisibleInFooterActionGroup.xml | 19 +++++++++++++ ...refrontStoreVisibleInFooterActionGroup.xml | 21 ++++++++++++++ ...refrontStoreVisibleInHeaderActionGroup.xml | 21 ++++++++++++++ ...iewDisabledErrorSaveMessageActionGroup.xml | 2 +- ...atusDisabledVerifyErrorSaveMessageTest.xml | 2 +- ...EnabledVerifyAbsenceOfDeleteButtonTest.xml | 3 +- ...tusEnabledVerifyBackendAndFrontendTest.xml | 20 ++++++------- ...NewLocalizedStoreViewStatusEnabledTest.xml | 3 +- ...usDisabledVerifyBackendAndFrontendTest.xml | 16 +++++------ ...tusEnabledVerifyBackendAndFrontendTest.xml | 18 +++++------- 12 files changed, 143 insertions(+), 37 deletions(-) create mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreConfigurationBackendActionGroup.xml create mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreFrontendActionGroup.xml create mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreNotVisibleInFooterActionGroup.xml create mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInFooterActionGroup.xml create mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInHeaderActionGroup.xml diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreConfigurationBackendActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreConfigurationBackendActionGroup.xml new file mode 100644 index 0000000000000..cd34dcd89705a --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreConfigurationBackendActionGroup.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStoreConfigurationBackendActionGroup"> + <arguments> + <!-- defaultValue is blank so that it can be used in cases where there is only one store view --> + <argument name="website" type="string" defaultValue=""/> + <argument name="customStore" type="string" defaultValue=""/> + <argument name="storeView1" type="string" defaultValue=""/> + <argument name="storeView2" type="string" defaultValue=""/> + </arguments> + <amOnPage url="{{AdminConfigPage.url}}" stepKey="goToConfigStoreConfigurationPage"/> + <waitForPageLoad stepKey="waitForSystemStoreConfigurationPageLoad"/> + <click selector="{{AdminConfigSection.defaultConfigButton}}" stepKey="clickDefaultConfigButton"/> + <see selector="{{AdminConfigSection.defaultConfigDropdown}}" userInput="{{website}}" stepKey="seeAssertWebsiteInDefaultConfigDropdown"/> + <see selector="{{AdminConfigSection.defaultConfigDropdown}}" userInput="{{customStore}}" stepKey="seeAssertSecondStoreInDefaultConfigDropdown"/> + <see selector="{{AdminConfigSection.defaultConfigDropdown}}" userInput="{{storeView1}}" stepKey="seeAssertFirstStoreViewInDefaultConfigDropdown"/> + <see selector="{{AdminConfigSection.defaultConfigDropdown}}" userInput="{{storeView2}}" stepKey="seeAssertSecondStoreViewInDefaultConfigDropdown"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreFrontendActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreFrontendActionGroup.xml new file mode 100644 index 0000000000000..471421a9bd73a --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreFrontendActionGroup.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStoreFrontendActionGroup"> + <arguments> + <argument name="customStore" type="string"/> + <!-- defaultValue is blank so that it can be used in cases where there is only one store view --> + <argument name="storeView1" type="string" defaultValue=""/> + <argument name="storeView2" type="string" defaultValue=""/> + </arguments> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> + <waitForPageLoad stepKey="waitForStorefrontHomePageLoad"/> + <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="clickSwitchStoreButton"/> + <waitForElementVisible selector="{{StorefrontFooterSection.storeLink(customStore)}}" stepKey="waitForStoreLinkToVosible"/> + <click selector="{{StorefrontFooterSection.storeLink(customStore)}}" stepKey="clickStoreLinkCustomStore"/> + <waitForPageLoad stepKey="waitForCustomStoreToLoad"/> + <see selector="{{StorefrontHeaderSection.storeViewName}}" userInput="{{storeView1}}" stepKey="seeAssertFirstStoreViewOnStorefront"/> + <click selector="{{StorefrontHeaderSection.storeViewName}}" stepKey="clickStoreViewName"/> + <see selector="{{StorefrontHeaderSection.storeViewDropdown}}" userInput="{{storeView2}}" stepKey="seeAssertSecondStoreViewOnStorefront"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreNotVisibleInFooterActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreNotVisibleInFooterActionGroup.xml new file mode 100644 index 0000000000000..dbeaf20da5ebd --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreNotVisibleInFooterActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontStoreNotVisibleInFooterActionGroup"> + <arguments> + <argument name="store" type="string"/> + </arguments> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> + <waitForPageLoad stepKey="waitForStorefrontHomePageLoad"/> + <dontSee selector="{{StorefrontFooterSection.storeLink(store)}}" stepKey="AssertStoreNotOnStorefront"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInFooterActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInFooterActionGroup.xml new file mode 100644 index 0000000000000..9d15cc8b2f90f --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInFooterActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontStoreVisibleInFooterActionGroup"> + <arguments> + <argument name="customStore" type="string"/> + </arguments> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> + <waitForPageLoad stepKey="waitForStorefrontHomePageLoad"/> + <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="clickSwitchStoreButton"/> + <waitForElementVisible selector="{{StorefrontFooterSection.storeLink(customStore)}}" stepKey="waitForStoreLinkToVosible"/> + <seeElement selector="{{StorefrontFooterSection.storeLink(customStore)}}" stepKey="seeAssertStoreOnStorefront"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInHeaderActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInHeaderActionGroup.xml new file mode 100644 index 0000000000000..24ac4a8eb9c7c --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInHeaderActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontStoreVisibleInHeaderActionGroup"> + <arguments> + <argument name="store" type="string"/> + </arguments> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> + <waitForPageLoad stepKey="waitForStorefrontHomePageLoad"/> + <click selector="{{StorefrontHeaderSection.storeViewSwitcher}}" stepKey="selectStoreSwitcher"/> + <waitForPageLoad stepKey="waitForFirstStoreView"/> + <see selector="{{StorefrontHeaderSection.storeViewDropdown}}" userInput="{{store}}" stepKey="seeAssertStoreViewOnStorefront"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/StoreViewDisabledErrorSaveMessageActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/StoreViewDisabledErrorSaveMessageActionGroup.xml index 355af60b24ff2..1cf48e9c82566 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/StoreViewDisabledErrorSaveMessageActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/StoreViewDisabledErrorSaveMessageActionGroup.xml @@ -12,7 +12,7 @@ <arguments> <argument name="storeGroupName" type="string"/> <argument name="storeView" type="string"/> - <argument name="storeViewStatus"/> + <argument name="storeViewStatus" type="string"/> </arguments> <amOnPage url="{{AdminSystemStoreViewPage.url}}" stepKey="amOnAdminSystemStoreViewPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml index 94959c7bf0a91..cd514859edf61 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml @@ -42,7 +42,7 @@ <actionGroup ref="StoreViewDisabledErrorSaveMessageActionGroup" stepKey="createStoreViewAssertStoreDisabledErrorSaveMessage"> <argument name="storeGroupName" value="{{customStore.name}}"/> <argument name="storeView" value="storeViewDataDisabled"/> - <argument name="storeViewStatus" value="storeViewDataDisabled.is_active"/> + <argument name="storeViewStatus" value="{{storeViewDataDisabled.is_active}}"/> </actionGroup> </test> </tests> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml index 64713ce64fd54..7ec129238de2f 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml @@ -40,8 +40,7 @@ </actionGroup> <!--Save the above store view and verify AssertStoreViewSuccessSaveMessage--> - <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"> - </actionGroup> + <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"/> <!--Search store view(from above step) in grid--> <actionGroup ref="AssertStoreViewInGridActionGroup" stepKey="searchStoreViewInGrid"> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml index a7c5cfd575909..0b003cb46453d 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml @@ -40,8 +40,7 @@ </actionGroup> <!--Save the above store view and verify AssertStoreViewSuccessSaveMessage--> - <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"> - </actionGroup> + <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"/> <!--Search store view(from above step) in grid and verify AssertStoreInGrid--> <actionGroup ref="AssertStoreViewInGridActionGroup" stepKey="searchStoreViewInGrid"> @@ -57,16 +56,15 @@ </actionGroup> <!--Go to store configuration page and verify AssertStoreBackend--> - <amOnPage url="{{AdminConfigPage.url}}" stepKey="goToStoreConfigurationPage"/> - <waitForPageLoad stepKey="waitForSystemStoreConfigurationPageLoad" /> - <click selector="{{AdminConfigSection.defaultConfigButton}}" stepKey="clickDefaultConfigButton"/> - <see selector="{{AdminConfigSection.defaultConfigDropdown}}" userInput="{{storeViewData.name}}" stepKey="seeAssertStoreViewInDefaultConfigDropdown"/> + <actionGroup ref="AssertStoreConfigurationBackendActionGroup" stepKey="verifyValuesOnStoreBackend"> + <argument name="website" value="{{_defaultWebsite.name}}"/> + <argument name="customStore" value="{{customStore.name}}"/> + <argument name="storeView1" value="{{storeViewData.name}}"/> + </actionGroup> <!--Go to storefront and verify AssertStoreFrontend--> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> - <waitForPageLoad stepKey="waitForStorefrontHomePageLoad"/> - <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="clickSwitchStoreButton"/> - <waitForPageLoad stepKey="waitForSwitchStoreButtonLoad"/> - <seeElement selector="{{StorefrontFooterSection.storeLink(customStore.name)}}" stepKey="seeCustomStoreInStoreLink"/> + <actionGroup ref="AssertStorefrontStoreVisibleInFooterActionGroup" stepKey="verifyValuesOnStoreFrontend"> + <argument name="customStore" value="{{customStore.name}}"/> + </actionGroup> </test> </tests> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml index fda0c3b1aa840..f424a309b56c4 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml @@ -34,8 +34,7 @@ </actionGroup> <!--Save the above store view and verify AssertStoreViewSuccessSaveMessage--> - <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"> - </actionGroup> + <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"/> <!--Search store view(from above step) in grid and verify AssertStoreInGrid--> <actionGroup ref="AssertStoreViewInGridActionGroup" stepKey="searchStoreViewInGrid"> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml index 65c126bb8eff9..c4308504659bc 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml @@ -35,18 +35,16 @@ </actionGroup> <!--Save the above store view and verify AssertStoreViewSuccessSaveMessage--> - <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"> - </actionGroup> + <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"/> <!--Go to store configuration page and verify AssertStoreBackend--> - <amOnPage url="{{AdminConfigPage.url}}" stepKey="goToConfigStoreConfigurationPage"/> - <waitForPageLoad stepKey="waitForSystemStoreConfigurationPageLoad"/> - <click selector="{{AdminConfigSection.defaultConfigButton}}" stepKey="clickDefaultConfigButton"/> - <see selector="{{AdminConfigSection.defaultConfigDropdown}}" userInput="{{storeViewDataDisabled.name}}" stepKey="seeAssertStoreViewInDefaultConfigDropdown"/> + <actionGroup ref="AssertStoreConfigurationBackendActionGroup" stepKey="verifyValuesOnStoreBackend"> + <argument name="storeView1" value="{{storeViewDataDisabled.name}}"/> + </actionGroup> <!--Go to storefront and verify AssertStoreNotOnFrontend--> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> - <waitForPageLoad stepKey="waitForStorefrontHomePageLoad"/> - <dontSee selector="{{StorefrontHeaderSection.storeViewDropdown}}" userInput="{{storeViewDataDisabled.name}}" stepKey="AssertStoreNotOnFrontend"/> + <actionGroup ref="AssertStorefrontStoreNotVisibleInFooterActionGroup" stepKey="verifyValuesNotOnStorefront"> + <argument name="store" value="{{storeViewDataDisabled.name}"/> + </actionGroup> </test> </tests> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml index 6552f04b747b4..0b108e7ab06d0 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml @@ -34,20 +34,16 @@ </actionGroup> <!--Save the above store view and verify AssertStoreViewSuccessSaveMessage--> - <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"> - </actionGroup> + <actionGroup ref="AdminCreateStoreViewActionSaveGroup" stepKey="verifyAssertStoreViewSuccessSaveMessage"/> <!--Go to store configuration page and verify AssertStoreBackend--> - <amOnPage url="{{AdminConfigPage.url}}" stepKey="goToConfigStoreConfigurationPage"/> - <waitForPageLoad stepKey="waitForSystemStoreConfigurationPageLoad" /> - <click selector="{{AdminConfigSection.defaultConfigButton}}" stepKey="clickDefaultConfigButton"/> - <see selector="{{AdminConfigSection.defaultConfigDropdown}}" userInput="{{storeViewData.name}}" stepKey="seeAssertStoreViewInDefaultConfigDropdown"/> + <actionGroup ref="AssertStoreConfigurationBackendActionGroup" stepKey="verifyValuesOnStoreBackend"> + <argument name="storeView1" value="{{storeViewData.name}}"/> + </actionGroup> <!--Go to storefront and verify AssertStoreFrontend--> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> - <waitForPageLoad stepKey="waitForStorefrontHomePageLoad"/> - <click selector="{{StorefrontHeaderSection.storeViewSwitcher}}" stepKey="selectStoreSwitcher"/> - <waitForPageLoad stepKey="waitForFirstStoreView"/> - <see selector="{{StorefrontHeaderSection.storeViewDropdown}}" userInput="{{storeViewData.name}}" stepKey="seeAssertStoreViewOnStorefront"/> + <actionGroup ref="AssertStorefrontStoreVisibleInHeaderActionGroup" stepKey="verifyValuesOnStoreFrontend"> + <argument name="store" value="{{storeViewData.name}}"/> + </actionGroup> </test> </tests> \ No newline at end of file From 099908a832b3a2e5b8073e4152f8126dadafc5a7 Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Thu, 21 Mar 2019 15:58:35 -0500 Subject: [PATCH 071/585] MC-4894: Convert GridFilteringDeletedEntityTest to MFTF Addressing review comments --- ...xml => AddWebsiteToProductActionGroup.xml} | 7 +------ ...MessageAfterDeletingWebsiteActionGroup.xml | 20 +++++++++++++++++++ ...dFilterDeleteAndVerifyErrorMessageTest.xml | 17 ++++++++-------- 3 files changed, 30 insertions(+), 14 deletions(-) rename app/code/Magento/Catalog/Test/Mftf/ActionGroup/{AddCategoryAndWebsiteToProductActionGroup.xml => AddWebsiteToProductActionGroup.xml} (67%) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertErrorMessageAfterDeletingWebsiteActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddCategoryAndWebsiteToProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddWebsiteToProductActionGroup.xml similarity index 67% rename from app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddCategoryAndWebsiteToProductActionGroup.xml rename to app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddWebsiteToProductActionGroup.xml index 45553f6b5337f..9a4d15a0909fd 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddCategoryAndWebsiteToProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddWebsiteToProductActionGroup.xml @@ -8,15 +8,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AddCategoryAndWebsiteToProductActionGroup"> + <actionGroup name="AddWebsiteToProductActionGroup"> <arguments> - <argument name="category" type="string"/> <argument name="website" type="string"/> </arguments> - <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> - <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="{{category}}" stepKey="fillSearchForInitialCategory"/> - <click selector="{{AdminProductFormSection.selectCategory(category)}}" stepKey="selectCategory"/> - <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneButton"/> <scrollTo selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="scrollToProductInWebsiteSectionHeader"/> <click selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="clickProductInWebsiteSectionHeader"/> <checkOption selector="{{ProductInWebsitesSection.website(website)}}" stepKey="checkWebsite"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertErrorMessageAfterDeletingWebsiteActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertErrorMessageAfterDeletingWebsiteActionGroup.xml new file mode 100644 index 0000000000000..2ae224c71a9bd --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertErrorMessageAfterDeletingWebsiteActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertErrorMessageAfterDeletingWebsiteActionGroup"> + <arguments> + <argument name="errorMessage" type="string"/> + </arguments> + <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/> + <waitForPageLoad stepKey="waitForProductCatalogPageLoad"/> + <click selector="{{AdminCategoryModalSection.ok}}" stepKey="clickOkButtonFromAdminCategoryModalSection"/> + <see selector="{{AdminCategoryMessagesSection.errorMessage}}" userInput="{{errorMessage}}" stepKey="seeAssertErrorMessage"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml b/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml index 351e4677dbd9a..e2c3b157c1059 100644 --- a/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml +++ b/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml @@ -22,7 +22,10 @@ <magentoCLI command="config:set system/backup/functionality_enabled 1" stepKey="setEnableBackupToYes"/> <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> <createData entity="NewRootCategory" stepKey="rootCategory"/> - <createData entity="defaultSimpleProduct" stepKey="createProduct"/> + <createData entity="defaultSimpleProduct" stepKey="createProduct"> + <requiredEntity createDataKey="rootCategory" /> + </createData> + <!--Create website--> <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createWebsite"> <argument name="newWebsiteName" value="{{customWebsite.name}}"/> @@ -41,9 +44,9 @@ </actionGroup> </before> <after> + <magentoCLI command="config:set system/backup/functionality_enabled 0" stepKey="setEnableBackupToNo"/> <deleteData stepKey="deleteRootCategory" createDataKey="rootCategory"/> <deleteData stepKey="deleteProduct" createDataKey="createProduct"/> - <magentoCLI command="config:set system/backup/functionality_enabled 0" stepKey="setEnableBackupToNo"/> <actionGroup ref="logout" stepKey="logout"/> </after> @@ -55,8 +58,7 @@ </actionGroup> <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowOfCreatedSimpleProduct"/> <waitForPageLoad stepKey="waitUntilProductIsOpened"/> - <actionGroup ref="AddCategoryAndWebsiteToProductActionGroup" stepKey="updateSimpleProductAddingCategoryAndWebsiteCreated"> - <argument name="category" value="$$rootCategory.name$$"/> + <actionGroup ref="AddWebsiteToProductActionGroup" stepKey="updateSimpleProductAddingWebsiteCreated"> <argument name="website" value="{{customWebsite.name}}"/> </actionGroup> @@ -72,9 +74,8 @@ </actionGroup> <!--Go to grid page and verify AssertErrorMessage--> - <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/> - <waitForPageLoad stepKey="waitForProductCatalogPageLoad"/> - <click selector="{{AdminCategoryModalSection.ok}}" stepKey="clickOkButtonFromAdminCategoryModalSection"/> - <see selector="{{AdminCategoryMessagesSection.errorMessage}}" userInput="Something went wrong with processing the default view and we have restored the filter to its original state." stepKey="seeAssertErrorMessage"/> + <actionGroup ref="AssertErrorMessageAfterDeletingWebsiteActionGroup" stepKey="verifyErrorMessage"> + <argument name="errorMessage" value="Something went wrong with processing the default view and we have restored the filter to its original state."/> + </actionGroup> </test> </tests> \ No newline at end of file From 450c97302ccfe64f8967f9d492f1230fc9dde7ca Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 22 Mar 2019 14:35:49 +0200 Subject: [PATCH 072/585] MC-15406: [FT] [MFTF] StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest fails because of bad design --- ...frontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml | 2 ++ .../Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml index 91b6766169b91..fb95fc3f57bca 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml @@ -69,6 +69,8 @@ <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearProductsGridFilters"/> + <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogoutStorefront"/> </after> <!-- Open Product Grid, Filter product and open --> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml index c02b3fc0fb72c..15fc413c7ec92 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml @@ -26,7 +26,7 @@ <waitForElementVisible selector="{{AdminConfirmationModalSection.ok}}" stepKey="waitForModal" /> <see selector="{{AdminConfirmationModalSection.title}}" userInput="Warning message" stepKey="seeWarningAboutTakingALongTimeToComplete" /> <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="confirmModal" /> - <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForPageReolad"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForPageReload"/> <see selector="{{AdminMessagesSection.success}}" userInput="You saved the store view." stepKey="seeSavedMessage" /> </actionGroup> From b78aa2aa72dd4cee72389f6c568130299e3fd5bd Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Fri, 22 Mar 2019 16:19:56 +0200 Subject: [PATCH 073/585] Cannot return null for non-nullable field AvailableShippingMethod.method_code when no shipping methods are available --- .../ShippingAddress/AvailableShippingMethods.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php index a9e0ba59d15d9..d0bded279bee5 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php @@ -10,6 +10,7 @@ use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\Data\ShippingMethodInterface; @@ -65,13 +66,19 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $shippingRates = $address->getGroupedAllShippingRates(); foreach ($shippingRates as $carrierRates) { foreach ($carrierRates as $rate) { - $methods[] = $this->dataObjectConverter->toFlatArray( + $method = $this->dataObjectConverter->toFlatArray( $this->shippingMethodConverter->modelToDataObject($rate, $cart->getQuoteCurrencyCode()), [], ShippingMethodInterface::class ); + if ($method['available'] && $method['error_message'] === "") { + $methods[] = $method; + } } } + if (count($methods) === 0) { + throw new GraphQlNoSuchEntityException(__(' This shipping method is not available. To use this shipping method, please contact us.')); + } return $methods; } } From 5d95670c392fe7d00616ef8d40365e06e1d8d00b Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Fri, 22 Mar 2019 10:50:10 -0500 Subject: [PATCH 074/585] MC-4871: Convert CreateStoreEntityTest to MFTF Addressing second set of review comments --- .../ActionGroup/AssertStoreConfigurationBackendActionGroup.xml | 1 - .../Test/Mftf/ActionGroup/AssertStoreFrontendActionGroup.xml | 1 - .../AssertStorefrontStoreNotVisibleInFooterActionGroup.xml | 1 - .../AssertStorefrontStoreVisibleInFooterActionGroup.xml | 1 - .../AssertStorefrontStoreVisibleInHeaderActionGroup.xml | 1 - ...teCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml | 1 - ...stomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml | 1 - ...eCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml | 1 - .../Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml | 1 - ...CreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml | 1 - ...nCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml | 1 - 11 files changed, 11 deletions(-) diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreConfigurationBackendActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreConfigurationBackendActionGroup.xml index cd34dcd89705a..e86a7d1b0c394 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreConfigurationBackendActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreConfigurationBackendActionGroup.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStoreConfigurationBackendActionGroup"> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreFrontendActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreFrontendActionGroup.xml index 471421a9bd73a..e635d715a58c2 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreFrontendActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStoreFrontendActionGroup.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStoreFrontendActionGroup"> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreNotVisibleInFooterActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreNotVisibleInFooterActionGroup.xml index dbeaf20da5ebd..2c2e07728b60a 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreNotVisibleInFooterActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreNotVisibleInFooterActionGroup.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStorefrontStoreNotVisibleInFooterActionGroup"> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInFooterActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInFooterActionGroup.xml index 9d15cc8b2f90f..5c63373f59f39 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInFooterActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInFooterActionGroup.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStorefrontStoreVisibleInFooterActionGroup"> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInHeaderActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInHeaderActionGroup.xml index 24ac4a8eb9c7c..03745ff832382 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInHeaderActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreVisibleInHeaderActionGroup.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStorefrontStoreVisibleInHeaderActionGroup"> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml index cd514859edf61..94e723c9afafb 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest"> <annotations> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml index 7ec129238de2f..7cd44d4d0ae88 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest"> <annotations> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml index 0b003cb46453d..18485abadc008 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest"> <annotations> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml index f424a309b56c4..8e9fe1e71ceb4 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCreateNewLocalizedStoreViewStatusEnabledTest"> <annotations> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml index c4308504659bc..6ccab965b7727 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest"> <annotations> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml index 0b108e7ab06d0..c2f12bd2673f7 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml @@ -5,7 +5,6 @@ * See COPYING.txt for license details. */ --> -<!-- Test XML Example --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest"> <annotations> From 9a15895df01989478ce5fc004d3157cf247cbc14 Mon Sep 17 00:00:00 2001 From: Alex Paliarush <paliarus@adobe.com> Date: Tue, 9 Oct 2018 18:26:46 -0500 Subject: [PATCH 075/585] Added caching of GraphQL GET requests with Varnish (no invalidation yet) --- .../Controller/GraphQl/Plugin.php | 30 +++++++++++++++++++ app/code/Magento/GraphQlCache/composer.json | 21 +++++++++++++ .../Magento/GraphQlCache/etc/graphql/di.xml | 12 ++++++++ app/code/Magento/GraphQlCache/etc/module.xml | 14 +++++++++ .../Magento/GraphQlCache/registration.php | 9 ++++++ 5 files changed, 86 insertions(+) create mode 100644 app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php create mode 100644 app/code/Magento/GraphQlCache/composer.json create mode 100644 app/code/Magento/GraphQlCache/etc/graphql/di.xml create mode 100644 app/code/Magento/GraphQlCache/etc/module.xml create mode 100644 app/code/Magento/GraphQlCache/registration.php diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php new file mode 100644 index 0000000000000..9e095a3201592 --- /dev/null +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller\GraphQl; + +use Magento\Framework\App\FrontControllerInterface; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\ResponseInterface; + +class Plugin +{ + public function afterDispatch( + FrontControllerInterface $subject, + ResponseInterface $response, + RequestInterface $request + ) { + /** @var \Magento\Framework\App\Request\Http $request */ + /** @var \Magento\Framework\Webapi\Response $response */ + if ($request->isGet()) { + $response->setHeader('Pragma', 'cache', true); + // TODO: Take from configuration + $response->setHeader('Cache-Control', 'max-age=86400, public, s-maxage=86400', true); + } + return $response; + } +} diff --git a/app/code/Magento/GraphQlCache/composer.json b/app/code/Magento/GraphQlCache/composer.json new file mode 100644 index 0000000000000..7b5e6137895f9 --- /dev/null +++ b/app/code/Magento/GraphQlCache/composer.json @@ -0,0 +1,21 @@ +{ + "name": "magento/module-graph-ql-cache", + "description": "N/A", + "type": "magento2-module", + "require": { + "php": "~7.1.3||~7.2.0", + "magento/module-graph-ql": "*" + }, + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Magento\\GraphQlCache\\": "" + } + } +} diff --git a/app/code/Magento/GraphQlCache/etc/graphql/di.xml b/app/code/Magento/GraphQlCache/etc/graphql/di.xml new file mode 100644 index 0000000000000..a6480d04d549b --- /dev/null +++ b/app/code/Magento/GraphQlCache/etc/graphql/di.xml @@ -0,0 +1,12 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Framework\App\FrontControllerInterface"> + <plugin name="cache" type="\Magento\GraphQlCache\Controller\GraphQl\Plugin"/> + </type> +</config> diff --git a/app/code/Magento/GraphQlCache/etc/module.xml b/app/code/Magento/GraphQlCache/etc/module.xml new file mode 100644 index 0000000000000..d7f08c5529332 --- /dev/null +++ b/app/code/Magento/GraphQlCache/etc/module.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> + <module name="Magento_GraphQlCache"> + <sequence> + <module name="Magento_GraphQl"/> + </sequence> + </module> +</config> diff --git a/app/code/Magento/GraphQlCache/registration.php b/app/code/Magento/GraphQlCache/registration.php new file mode 100644 index 0000000000000..2dfe717003a03 --- /dev/null +++ b/app/code/Magento/GraphQlCache/registration.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Framework\Component\ComponentRegistrar; + +ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_GraphQlCache', __DIR__); From f46dde4bf3c8b673add5c11274a060309e994bce Mon Sep 17 00:00:00 2001 From: Alex Paliarush <paliarus@adobe.com> Date: Wed, 10 Oct 2018 21:02:12 -0500 Subject: [PATCH 076/585] Added prototype of Varnish cache invalidation for GraphQL --- .../CatalogGraphQl/etc/schema.graphqls | 2 +- .../Controller/GraphQl/Plugin.php | 19 ++++- .../Magento/GraphQlCache/Model/CacheTags.php | 36 +++++++++ .../GraphQlCache/Query/Resolver/Plugin.php | 74 +++++++++++++++++++ .../Magento/GraphQlCache/etc/graphql/di.xml | 5 +- 5 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/GraphQlCache/Model/CacheTags.php create mode 100644 app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 778d0783305b7..f86ecea9e075d 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -9,7 +9,7 @@ type Query { currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") ): Products - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @cache(tag: "cat_p") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") category ( id: Int @doc(description: "Id of the category") ): CategoryTree diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php index 9e095a3201592..e1109da0ea9bf 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -10,9 +10,23 @@ use Magento\Framework\App\FrontControllerInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\ResponseInterface; +use Magento\GraphQlCache\Model\CacheTags; class Plugin { + /** + * @var CacheTags + */ + private $cacheTags; + + /** + * @param CacheTags $cacheTags + */ + public function __construct(CacheTags $cacheTags) + { + $this->cacheTags = $cacheTags; + } + public function afterDispatch( FrontControllerInterface $subject, ResponseInterface $response, @@ -20,10 +34,13 @@ public function afterDispatch( ) { /** @var \Magento\Framework\App\Request\Http $request */ /** @var \Magento\Framework\Webapi\Response $response */ - if ($request->isGet()) { + $cacheTags = $this->cacheTags->getCacheTags(); + if ($request->isGet() && count($cacheTags)) { + // assume that response should be cacheable if it contains cache tags $response->setHeader('Pragma', 'cache', true); // TODO: Take from configuration $response->setHeader('Cache-Control', 'max-age=86400, public, s-maxage=86400', true); + $response->setHeader('X-Magento-Tags', implode(',', $cacheTags), true); } return $response; } diff --git a/app/code/Magento/GraphQlCache/Model/CacheTags.php b/app/code/Magento/GraphQlCache/Model/CacheTags.php new file mode 100644 index 0000000000000..6889a873a3f05 --- /dev/null +++ b/app/code/Magento/GraphQlCache/Model/CacheTags.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Model; + +/** + * Cache tags object is a registry for collecting cache tags of all entities used in the GraphQL query response. + */ +class CacheTags +{ + /** + * @var string[] + */ + private $cacheTags = []; + + /** + * @return string[] + */ + public function getCacheTags(): array + { + return $this->cacheTags; + } + + /** + * @param string[] $tags + * @return void + */ + public function addCacheTags(array $cacheTags): void + { + $this->cacheTags = array_merge($this->cacheTags, $cacheTags); + } +} diff --git a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php b/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php new file mode 100644 index 0000000000000..65b05bf71da0b --- /dev/null +++ b/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Query\Resolver; + +use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Query\ResolverInterface; +use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\GraphQlCache\Model\CacheTags; + +class Plugin +{ + /** + * @var CacheTags + */ + private $cacheTags; + + /** + * @param CacheTags $cacheTags + */ + public function __construct(CacheTags $cacheTags) + { + $this->cacheTags = $cacheTags; + } + + public function afterResolve( + ResolverInterface $subject, + $resolvedValue, + Field $field, + $context, + ResolveInfo $info, + array $value = null, + array $args = null + ) { + if ($field->getName() == 'products') { + // TODO: Read cache tag value from the GraphQL schema and make it accessible via $field + $cacheTag = 'cat_p'; + } + // TODO: Can be optimized to avoid tags calculation for POST requests + if (!empty($cacheTag)) { + $cacheTags = [$cacheTag]; + // Resolved value must have cache IDs defined + $resolvedItemsIds = $this->extractResolvedItemsIds($resolvedValue); + foreach ($resolvedItemsIds as $itemId) { + $cacheTags[] = $cacheTag . '_' . $itemId; + } + $this->cacheTags->addCacheTags($cacheTags); + } + return $resolvedValue; + } + + private function extractResolvedItemsIds($resolvedValue) + { + // TODO: Implement safety checks and think about additional places which can hold items IDs + if (isset($resolvedValue['ids']) && is_array($resolvedValue['ids'])) { + return $resolvedValue['ids']; + } + if (isset($resolvedValue['items']) && is_array($resolvedValue['items'])) { + return array_keys($resolvedValue['items']); + } + $ids = []; + if (is_array($resolvedValue)) { + foreach ($resolvedValue as $item) { + if (isset($item['id'])) { + $ids[] = $item['id']; + } + } + } + } +} diff --git a/app/code/Magento/GraphQlCache/etc/graphql/di.xml b/app/code/Magento/GraphQlCache/etc/graphql/di.xml index a6480d04d549b..7dbc54fd06731 100644 --- a/app/code/Magento/GraphQlCache/etc/graphql/di.xml +++ b/app/code/Magento/GraphQlCache/etc/graphql/di.xml @@ -7,6 +7,9 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Framework\App\FrontControllerInterface"> - <plugin name="cache" type="\Magento\GraphQlCache\Controller\GraphQl\Plugin"/> + <plugin name="cache" type="Magento\GraphQlCache\Controller\GraphQl\Plugin"/> + </type> + <type name="Magento\Framework\GraphQl\Query\ResolverInterface"> + <plugin name="cache" type="Magento\GraphQlCache\Query\Resolver\Plugin"/> </type> </config> From 85c90655f7110bd9082b12f427c036206ddbf4fb Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Fri, 22 Mar 2019 14:05:32 -0500 Subject: [PATCH 077/585] MC-4461: Convert AddProductsToShoppingCartEntityTest to MFTF --- ...BundleProductDropDownOptionActionGroup.xml | 18 + ...tomizeAndAddToTheCartButtonActionGroup.xml | 16 + .../Bundle/Test/Mftf/Data/ProductData.xml | 16 + .../Mftf/Section/StorefrontBundledSection.xml | 1 + .../StorefrontProductActionSection.xml | 6 +- .../Section/StorefrontMiniCartSection.xml | 1 + .../StorefrontProductInfoMainSection.xml | 16 + .../Section/StorefrontProductPageSection.xml | 1 + ...sertStorefronElementVisibleActionGroup.xml | 17 + ...StorefrontCheckoutCartItemsActionGroup.xml | 22 ++ ...sertStorefrontMiniCartItemsActionGroup.xml | 24 ++ .../AssertStorefrontSeeElementActionGroup.xml | 19 + ...ontShoppingCartSummaryItemsActionGroup.xml | 22 ++ ...pingCartSummaryWithShippingActionGroup.xml | 19 + ...ntAddBundleProductToTheCartActionGroup.xml | 24 ++ .../StorefrontAddToTheCartActionGroup.xml | 17 + ...rontAssertMiniCartItemCountActionGroup.xml | 18 + ...roductDetailsInOrderSummaryActionGroup.xml | 20 + ...tShippingAddressPageDisplayActionGroup.xml | 15 + .../StorefrontAttachOptionFileActionGroup.xml | 17 + ...ndAssertOrderSummaryDisplayActionGroup.xml | 20 + .../StorefrontClickOnMiniCartActionGroup.xml | 16 + ...ductQuantityAndAddToTheCartActionGroup.xml | 19 + ...refrontFillOptionFieldInputActionGroup.xml | 17 + ...torefrontFillOptionTextAreaActionGroup.xml | 17 + .../StorefrontMiniCartActionGroup.xml | 2 + .../StorefrontOpenMiniCartActionGroup.xml | 15 + ...refrontSelectOptionCheckBoxActionGroup.xml | 16 + .../StorefrontSelectOptionDateActionGroup.xml | 21 ++ ...refrontSelectOptionDateTimeActionGroup.xml | 27 ++ ...refrontSelectOptionDropDownActionGroup.xml | 17 + ...rontSelectOptionMultiSelectActionGroup.xml | 17 + ...rontSelectOptionRadioButtonActionGroup.xml | 17 + .../StorefrontSelectOptionTimeActionGroup.xml | 21 ++ .../Section/CheckoutCartProductSection.xml | 4 + .../Section/CheckoutOrderSummarySection.xml | 1 + .../CheckoutShippingGuestInfoSection.xml | 1 + .../Section/StorefrontMiniCartSection.xml | 4 + ...oppingCartWithoutAnySelectedOptionTest.xml | 83 ++++ ...BundleDynamicProductToShoppingCartTest.xml | 121 ++++++ ...pingCartWithDisableMiniCartSidebarTest.xml | 126 +++++++ ...dConfigurableProductToShoppingCartTest.xml | 160 ++++++++ ...dDownloadableProductToShoppingCartTest.xml | 85 +++++ ...ontAddGroupedProductToShoppingCartTest.xml | 124 ++++++ ...MultiSelectOptionToTheShoppingCartTest.xml | 119 ++++++ ...pesOfCustomOptionToTheShoppingCartTest.xml | 114 ++++++ ...ultiSelectOptionsToTheShoppingCartTest.xml | 122 ++++++ ...isplayWithDefaultDisplayLimitationTest.xml | 342 +++++++++++++++++ ...edToTheCartThanDefaultDisplayLimitTest.xml | 282 ++++++++++++++ ...isplayLimitAndDefaultTotalQuantityTest.xml | 256 +++++++++++++ ...rtItemDisplayWithDefaultLimitationTest.xml | 356 ++++++++++++++++++ ...playWithCustomDisplayConfigurationTest.xml | 147 ++++++++ ...onfigurableProductToTheCartActionGroup.xml | 26 ++ ...hreeGroupedProductToTheCartActionGroup.xml | 30 ++ 54 files changed, 3052 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Bundle/Test/Mftf/ActionGroup/StorefrontSelectBundleProductDropDownOptionActionGroup.xml create mode 100644 app/code/Magento/Bundle/Test/Mftf/ActionGroup/StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefronElementVisibleActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontSeeElementActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryItemsActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddBundleProductToTheCartActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertMiniCartItemCountActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertProductDetailsInOrderSummaryActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingAddressPageDisplayActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAttachOptionFileActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutAndAssertOrderSummaryDisplayActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontEnterProductQuantityAndAddToTheCartActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillOptionFieldInputActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillOptionTextAreaActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenMiniCartActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionCheckBoxActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDateActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDateTimeActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDropDownActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionMultiSelectActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionRadioButtonActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionTimeActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOptionTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndSummaryBlockItemDisplayWithDefaultDisplayLimitationTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimitTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantityTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckSimpleProductCartItemDisplayWithDefaultLimitationTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckVirtualProductCountDisplayWithCustomDisplayConfigurationTest.xml create mode 100644 app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontAddConfigurableProductToTheCartActionGroup.xml create mode 100644 app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/StorefrontAddThreeGroupedProductToTheCartActionGroup.xml diff --git a/app/code/Magento/Bundle/Test/Mftf/ActionGroup/StorefrontSelectBundleProductDropDownOptionActionGroup.xml b/app/code/Magento/Bundle/Test/Mftf/ActionGroup/StorefrontSelectBundleProductDropDownOptionActionGroup.xml new file mode 100644 index 0000000000000..e6afdce6ab697 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Mftf/ActionGroup/StorefrontSelectBundleProductDropDownOptionActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectBundleProductDropDownOptionActionGroup"> + <arguments> + <argument name="productName" type="string"/> + </arguments> + <click selector="{{StorefrontBundleProductActionSection.dropdownSelectOption}}" stepKey="clickOnSelectOption"/> + <click selector="{{StorefrontBundleProductActionSection.dropdownProductSelection(productName)}}" stepKey="selectProduct"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Bundle/Test/Mftf/ActionGroup/StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup.xml b/app/code/Magento/Bundle/Test/Mftf/ActionGroup/StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup.xml new file mode 100644 index 0000000000000..cf2ccfac47023 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Mftf/ActionGroup/StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup"> + <waitForElementVisible selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="waitForCustomizeAndAddToCartButton"/> + <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickOnCustomizeAndAddToCartButton"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml index 0a0c77755fc7a..5034c72b9ee3f 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml @@ -91,4 +91,20 @@ <requiredEntity type="custom_attribute">CustomAttributeFixPrice</requiredEntity> <requiredEntity type="custom_attribute">CustomAttributePriceView</requiredEntity> </entity> + <entity name="BundleProductPriceViewRange" type="product2"> + <data key="name" unique="suffix">BundleProduct</data> + <data key="sku" unique="suffix">bundle-product</data> + <data key="type_id">bundle</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="status">1</data> + <data key="urlKey" unique="suffix">bundle-product</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributeCategoryIds</requiredEntity> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute">ApiProductDescription</requiredEntity> + <requiredEntity type="custom_attribute">ApiProductShortDescription</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributeDynamicPrice</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributePriceViewRange</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontBundledSection.xml b/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontBundledSection.xml index dbe48c46c820b..fc3de1eddc831 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontBundledSection.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontBundledSection.xml @@ -34,5 +34,6 @@ <element name="multiselectOptionFourProducts" type="multiselect" selector="//label//span[contains(text(), '{{productName}}')]/../..//select[@multiple='multiple']" parameterized="true"/> <element name="currencyTrigger" type="select" selector="#switcher-currency-trigger" timeout="30"/> <element name="currency" type="select" selector="//a[text()='{{arg}}']" parameterized="true"/> + <element name="multiSelectOption" type="select" selector="//div[@class='field option required']//select"/> </section> </sections> diff --git a/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontProductActionSection.xml b/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontProductActionSection.xml index 9dc4aed26bef0..eb92fd3756497 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontProductActionSection.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontProductActionSection.xml @@ -8,8 +8,10 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontBundleProductActionSection"> - <element name="customizeAndAddToCartButton" type="button" selector="#bundle-slide"/> + <element name="customizeAndAddToCartButton" type="button" selector="#bundle-slide" timeout="30"/> <element name="quantityField" type="input" selector="#qty"/> - <element name="addToCartButton" type="button" selector="#product-addtocart-button"/> + <element name="addToCartButton" type="button" selector="#product-addtocart-button" timeout="30"/> + <element name="dropdownSelectOption" type="select" selector="//div[@class='control']/select"/> + <element name="dropdownProductSelection" type="select" selector="//div[@class='control']/select/option[contains(.,'{{productName}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontMiniCartSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontMiniCartSection.xml index c6ea96715cf82..b2cd0f5f9af9f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontMiniCartSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontMiniCartSection.xml @@ -12,5 +12,6 @@ <element name="quantity" type="button" selector="span.counter-number"/> <element name="show" type="button" selector="a.showcart"/> <element name="goToCheckout" type="button" selector="#top-cart-btn-checkout" timeout="30"/> + <element name="emptyMiniCart" type="text" selector="//div[@class='minicart-wrapper']//span[@class='counter qty empty']/../.."/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index 8504683648bce..ff1b8b3e992d3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -85,5 +85,21 @@ <element name="customSelectOptions" type="select" selector="#{{selectId}} option" parameterized="true"/> <element name="requiredCustomInput" type="text" selector="//div[contains(.,'{{customOptionTitle}}') and contains(@class, 'required') and .//input[@aria-required='true']]" parameterized="true"/> <element name="requiredCustomSelect" type="select" selector="//div[contains(.,'{{customOptionTitle}}') and contains(@class, 'required') and .//select[@aria-required='true']]" parameterized="true"/> + <element name="requiredCustomField" type="text" selector="//div[@class='field required']/label/span[contains(.,'{{optionTitle}}')]//../../div/div[contains(.,'This is a required field.')]" parameterized="true"/> + <element name="requiredCustomFile" type="text" selector="//div[@class='field file required']/label/span[contains(.,'{{OptionFileTitle}}')]//../../div/div[contains(.,'This is a required field.')]" parameterized="true"/> + <element name="requiredCustomTextArea" type="text" selector="//div[@class='field textarea required']/label/span[contains(.,'{{OptionAreaTitle}}')]//../../div/div[contains(.,'This is a required field.')]" parameterized="true"/> + <element name="requiredCustomDate" type="text" selector="//div[@class='field date required']//span[text()='{{OptionDateTitle}}']//../../div/div[contains(.,'This is a required field.')]" parameterized="true"/> + <element name="customOptionField" type="input" selector="//input[contains(@class,'input-text product-custom-option')]"/> + <element name="customOptionTextArea" type="textarea" selector="//textarea[contains(@class,'product-custom-option')]"/> + <element name="customOptionDropDown" type="select" selector="//select[contains(@class,' required product-custom-option admin__control-select')]/option[contains(.,'{{option}}')]" parameterized="true"/> + <element name="customRadioOption" type="checkbox" selector="//div/input[@type='radio']/../label/span"/> + <element name="customOptionCheckBox" type="checkbox" selector="//div/input[@type='checkbox']/../label/span[contains(.,'{{option}}')]" parameterized="true"/> + <element name="customMultiSelectOption" type="select" selector="//select[contains(@class,'multiselect admin__control-multiselect required product-custom-option')]/option[contains(.,'{{option'}})]" parameterized="true"/> + <element name="customOptionMonth" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='month']" parameterized="true"/> + <element name="customOptionDay" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='day']" parameterized="true"/> + <element name="customOptionYear" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='year']" parameterized="true"/> + <element name="customOptionHour" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='hour']" parameterized="true"/> + <element name="customOptionMinute" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='minute']" parameterized="true"/> + <element name="customOptionDayPart" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='day_part']" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml index 8055ecfe00cde..028bbe88e2cef 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml @@ -23,5 +23,6 @@ <element name="shipping" type="input" selector="span[data-th='Shipping']"/> <element name="orderTotal" type="input" selector=".grand.totals .amount .price"/> <element name="customOptionDropDown" type="select" selector="//*[@id='product-options-wrapper']//select[contains(@class, 'product-custom-option admin__control-select')]"/> + <element name="qtyInputWithProduct" type="input" selector="//tr//strong[contains(.,'{{productName}}')]/../../td[@class='col qty']//input" parameterized="true"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefronElementVisibleActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefronElementVisibleActionGroup.xml new file mode 100644 index 0000000000000..ddda54799f985 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefronElementVisibleActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontElementVisibleActionGroup"> + <arguments> + <argument name="selector" type="string"/> + <argument name="userInput" type="string"/> + </arguments> + <see selector="{{selector}}" userInput="{{userInput}}" stepKey="assertElement"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml new file mode 100644 index 0000000000000..df234da2e49cd --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontCheckoutCartItemsActionGroup"> + <arguments> + <argument name="productName" type="string"/> + <argument name="productPrice" type="string"/> + <argument name="subtotal" type="string"/> + <argument name="qty" type="string"/> + </arguments> + <see selector="{{CheckoutCartProductSection.productName}}" userInput="{{productName}}" stepKey="seeProductNameInCheckoutSummary"/> + <see selector="{{CheckoutCartProductSection.checkoutCartProductPrice}}" userInput="{{productPrice}}" stepKey="seeProductPriceInCart"/> + <see selector="{{CheckoutCartProductSection.checkoutCartSubtotal}}" userInput="{{subtotal}}" stepKey="seeSubtotalPrice"/> + <seeElement selector="{{CheckoutCartProductSection.quantity(qty)}}" stepKey="seeProductQuantity" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml new file mode 100644 index 0000000000000..1d8f065fa1786 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontMiniCartItemsActionGroup"> + <arguments> + <argument name="productName" type="string"/> + <argument name="productPrice" type="string"/> + <argument name="cartSubtotal" type="string"/> + <argument name="qty" type="string"/> + </arguments> + <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{productName}}" stepKey="seeProductNameInMiniCart"/> + <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{productPrice}}" stepKey="seeProductPriceInMiniCart"/> + <seeElement selector="{{StorefrontMinicartSection.goToCheckout}}" stepKey="seeCheckOutButtonInMiniCart"/> + <seeElement selector="{{StorefrontMinicartSection.productQuantity(productName, qty)}}" stepKey="seeProductQuantity1"/> + <seeElement selector="{{StorefrontMinicartSection.productImage}}" stepKey="seeProductImage"/> + <see selector="{{StorefrontMinicartSection.productSubTotal}}" userInput="{{cartSubtotal}}" stepKey="seeSubTotal"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontSeeElementActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontSeeElementActionGroup.xml new file mode 100644 index 0000000000000..02f00a8cd31a9 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontSeeElementActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontSeeElementActionGroup"> + <arguments> + <argument name="selector" type="string"/> + </arguments> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <scrollTo selector="{{selector}}" stepKey="scrollToElement"/> + <seeElement selector="{{selector}}" stepKey="assertElement"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryItemsActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryItemsActionGroup.xml new file mode 100644 index 0000000000000..54fde1be70bce --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryItemsActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontShoppingCartSummaryItemsActionGroup"> + <arguments> + <argument name="subtotal" type="string"/> + <argument name="total" type="string"/> + </arguments> + <seeInCurrentUrl url="{{CheckoutCartPage.url}}" stepKey="assertUrl"/> + <waitForPageLoad stepKey="waitForCartPage"/> + <see userInput="{{subtotal}}" selector="{{CheckoutCartSummarySection.subtotal}}" stepKey="assertSubtotal"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <see userInput="{{total}}" selector="{{CheckoutCartSummarySection.total}}" stepKey="assertTotal"/> + <seeElement selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="seeProceedToCheckoutButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml new file mode 100644 index 0000000000000..c4c9b9d6814d0 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontShoppingCartSummaryWithShippingActionGroup" extends="AssertStorefrontShoppingCartSummaryItemsActionGroup"> + <arguments> + <argument name="shipping" type="string"/> + </arguments> + <waitForLoadingMaskToDisappear stepKey="waitForMaskToDisappear" after="assertSubtotal"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.shipping}}" time="60" stepKey="waitForElementToBeVisible" after="waitForMaskToDisappear"/> + <wait time="5" stepKey="waitForShippingDetailsToLoad" after="waitForElementToBeVisible"/> + <see userInput="{{shipping}}" selector="{{CheckoutCartSummarySection.shipping}}" stepKey="assertShipping" after="waitForShippingDetailsToLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddBundleProductToTheCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddBundleProductToTheCartActionGroup.xml new file mode 100644 index 0000000000000..5f418077afbe6 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddBundleProductToTheCartActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAddBundleProductToTheCartActionGroup"> + <arguments> + <argument name="productName" type="string"/> + <argument name="quantity" type="string"/> + </arguments> + <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickOnCustomizeAndAddToCartButton"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <click selector="{{StorefrontBundleProductActionSection.dropdownSelectOption}}" stepKey="clickOnSelectOption"/> + <click selector="{{StorefrontBundleProductActionSection.dropdownProductSelection(productName)}}" stepKey="selectProduct"/> + <clearField selector="{{StorefrontBundleProductActionSection.quantityField}}" stepKey="clearTheQuantityField"/> + <fillField selector="{{StorefrontBundleProductActionSection.quantityField}}" userInput="{{quantity}}" stepKey="fillTheProductQuantity"/> + <click selector="{{StorefrontBundleProductActionSection.addToCartButton}}" stepKey="clickOnAddToButton"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml new file mode 100644 index 0000000000000..88e81199e3705 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAddToTheCartActionGroup"> + <waitForPageLoad stepKey="waitForPageLoad"/> + <scrollTo selector="{{StorefrontProductActionSection.addToCart}}" stepKey="scrollToAddToCartButton"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertMiniCartItemCountActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertMiniCartItemCountActionGroup.xml new file mode 100644 index 0000000000000..03caa558e4272 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertMiniCartItemCountActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertMiniCartItemCountActionGroup"> + <arguments> + <argument name="productCount" type="string"/> + <argument name="productCountText" type="string"/> + </arguments> + <see selector="{{StorefrontMinicartSection.productCount}}" userInput="{{productCount}}" stepKey="seeProductCountInCart"/> + <see selector="{{StorefrontMinicartSection.visibleItemsCountText}}" userInput="{{productCountText}}" stepKey="seeNumberOfItemDisplayInMiniCart"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertProductDetailsInOrderSummaryActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertProductDetailsInOrderSummaryActionGroup.xml new file mode 100644 index 0000000000000..59159ea2d0e7f --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertProductDetailsInOrderSummaryActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertProductDetailsInOrderSummaryActionGroup"> + <arguments> + <argument name="productName" type="string"/> + <argument name="qty" type="string"/> + <argument name="price" type="string"/> + </arguments> + <see selector="{{CheckoutOrderSummarySection.productItemName}}" userInput="{{productName}}" stepKey="seeProductName"/> + <see selector="{{CheckoutOrderSummarySection.productItemQty}}" userInput="{{qty}}" stepKey="seeProductQty"/> + <see selector="{{CheckoutOrderSummarySection.productItemPrice}}" userInput="{{price}}" stepKey="seeProductPrice"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingAddressPageDisplayActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingAddressPageDisplayActionGroup.xml new file mode 100644 index 0000000000000..cd3d18e2aa09e --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingAddressPageDisplayActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertShippingAddressPageDisplayActionGroup"> + <seeInCurrentUrl url="checkout/#shipping" stepKey="seeCurrentUrl"/> + <seeElement selector="{{CheckoutShippingSection.shippingTab}}" stepKey="seeShippingTab"/> + <seeElement selector="{{CheckoutShippingGuestInfoSection.shippingBlock}}" stepKey="seeShippingBlock"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAttachOptionFileActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAttachOptionFileActionGroup.xml new file mode 100644 index 0000000000000..364f05abd3882 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAttachOptionFileActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAttachOptionFileActionGroup"> + <arguments> + <argument name="optionTitle" defaultValue="ProductOptionFile"/> + <argument name="file" defaultValue="MagentoLogo.file" /> + </arguments> + <attachFile selector="{{StorefrontProductInfoMainSection.addLinkFileUploadFile(optionTitle.title)}}" userInput="{{file}}" stepKey="attachFile"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutAndAssertOrderSummaryDisplayActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutAndAssertOrderSummaryDisplayActionGroup.xml new file mode 100644 index 0000000000000..0a29cba11d4a9 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutAndAssertOrderSummaryDisplayActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontCheckoutAndAssertOrderSummaryDisplayActionGroup"> + <arguments> + <argument name="itemsText" type="string"/> + </arguments> + <click selector="{{StorefrontMinicartSection.goToCheckout}}" stepKey="clickOnCheckOutButtonInMiniCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <see selector="{{CheckoutShippingGuestInfoSection.itemInCart}}" userInput="{{itemsText}}" stepKey="seeOrderSummaryText"/> + <seeElement selector="{{CheckoutOrderSummarySection.miniCartTab}}" stepKey="clickOnOrderSummaryTab"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml new file mode 100644 index 0000000000000..09e991c21645d --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontClickOnMiniCartActionGroup"> + <scrollToTopOfPage stepKey="scrollToTheTopOfThePage"/> + <waitForElementVisible selector="{{StorefrontMinicartSection.showCart}}" stepKey="waitForElementToBeVisible"/> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontEnterProductQuantityAndAddToTheCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontEnterProductQuantityAndAddToTheCartActionGroup.xml new file mode 100644 index 0000000000000..c76cb8c0f1f88 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontEnterProductQuantityAndAddToTheCartActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontEnterProductQuantityAndAddToTheCartActionGroup"> + <arguments> + <argument name="quantity" type="string"/> + </arguments> + <clearField selector="{{StorefrontBundleProductActionSection.quantityField}}" stepKey="clearTheQuantityField"/> + <fillField selector="{{StorefrontBundleProductActionSection.quantityField}}" userInput="{{quantity}}" stepKey="fillTheProductQuantity"/> + <click selector="{{StorefrontBundleProductActionSection.addToCartButton}}" stepKey="clickOnAddToButton"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillOptionFieldInputActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillOptionFieldInputActionGroup.xml new file mode 100644 index 0000000000000..001cdae5a4793 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillOptionFieldInputActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontFillOptionFieldInputActionGroup"> + <arguments> + <argument name="optionTitle" defaultValue="ProductOptionField"/> + <argument name="fieldInput" type="string" /> + </arguments> + <fillField selector="{{StorefrontProductInfoMainSection.productOptionFieldInput(optionTitle.title)}}" userInput="{{fieldInput}}" stepKey="fillOptionField"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillOptionTextAreaActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillOptionTextAreaActionGroup.xml new file mode 100644 index 0000000000000..1e3162bac3bfa --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillOptionTextAreaActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontFillOptionTextAreaActionGroup"> + <arguments> + <argument name="optionTitle" defaultValue="ProductOptionArea"/> + <argument name="fieldInput" type="string"/> + </arguments> + <fillField selector="{{StorefrontProductInfoMainSection.productOptionAreaInput(optionTitle.title)}}" userInput="{{fieldInput}}" stepKey="fillOptionTextArea"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontMiniCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontMiniCartActionGroup.xml index 7a5c5e1d15872..4726ce5fb40c8 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontMiniCartActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontMiniCartActionGroup.xml @@ -8,9 +8,11 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="clickViewAndEditCartFromMiniCart"> + <scrollTo selector="{{StorefrontMinicartSection.showCart}}" stepKey="scrollToMiniCart"/> <conditionalClick selector="{{StorefrontMinicartSection.showCart}}" dependentSelector="{{StorefrontMinicartSection.miniCartOpened}}" visible="false" stepKey="openMiniCart"/> <waitForElementVisible selector="{{StorefrontMinicartSection.viewAndEditCart}}" stepKey="waitForViewAndEditCartVisible"/> <click selector="{{StorefrontMinicartSection.viewAndEditCart}}" stepKey="viewAndEditCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> <seeInCurrentUrl url="checkout/cart" stepKey="seeInCurrentUrl"/> </actionGroup> <actionGroup name="assertOneProductNameInMiniCart"> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenMiniCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenMiniCartActionGroup.xml new file mode 100644 index 0000000000000..7afcb070f3f06 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenMiniCartActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontOpenMiniCartActionGroup"> + <waitForElementVisible selector="{{StorefrontMinicartSection.showCart}}" stepKey="waitForElementToBeVisible"/> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionCheckBoxActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionCheckBoxActionGroup.xml new file mode 100644 index 0000000000000..731ac03ca414f --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionCheckBoxActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectOptionCheckBoxActionGroup"> + <arguments> + <argument name="optionTitle" defaultValue="ProductOptionValueCheckbox"/> + </arguments> + <checkOption selector="{{StorefrontProductInfoMainSection.customOptionCheckBox(optionTitle.title)}}" stepKey="SelectOptionRadioButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDateActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDateActionGroup.xml new file mode 100644 index 0000000000000..37f2afd2a00b0 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDateActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectOptionDateActionGroup"> + <arguments> + <argument name="optionTitle" defaultValue="ProductOptionDate"/> + <argument name="month" type="string"/> + <argument name="day" type="string"/> + <argument name="year" type="string"/> + </arguments> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionMonth(optionTitle.title)}}" userInput="{{month}}" stepKey="selectMonthForOptionDate"/> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionDay(optionTitle.title)}}" userInput="{{day}}" stepKey="selectDayForOptionDate"/> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionYear(optionTitle.title)}}" userInput="{{year}}" stepKey="selectYearForOptionDate"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDateTimeActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDateTimeActionGroup.xml new file mode 100644 index 0000000000000..f2bac08a381d6 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDateTimeActionGroup.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectOptionDateTimeActionGroup"> + <arguments> + <argument name="optionTitle" defaultValue="ProductOptionDateTime"/> + <argument name="month" type="string"/> + <argument name="day" type="string"/> + <argument name="year" type="string"/> + <argument name="hour" type="string"/> + <argument name="minute" type="string"/> + <argument name="dayPart" type="string"/> + </arguments> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionMonth(optionTitle.title)}}" userInput="{{month}}" stepKey="selectMonthForOptionDate"/> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionDay(optionTitle.title)}}" userInput="{{day}}" stepKey="selectDayForOptionDate"/> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionYear(optionTitle.title)}}" userInput="{{year}}" stepKey="selectYearForOptionDate"/> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionHour(optionTitle.title)}}" userInput="{{hour}}" stepKey="selectHourrForOptionDateTime"/> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionMinute(optionTitle.title)}}" userInput="{{minute}}" stepKey="selectMinuteForOptionDateTime"/> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionDayPart(optionTitle.title)}}" userInput="{{dayPart}}" stepKey="selectDayPartForOptionDateTime"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDropDownActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDropDownActionGroup.xml new file mode 100644 index 0000000000000..1f8cedae4efb1 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionDropDownActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectOptionDropDownActionGroup"> + <arguments> + <argument name="optionTitle" defaultValue="ProductOptionDropDown"/> + <argument name="option" defaultValue="ProductOptionValueDropdown2.title" /> + </arguments> + <selectOption selector="{{StorefrontProductInfoMainSection.productOptionSelect(optionTitle.title)}}" userInput="{{option}}" stepKey="fillOptionDropDown"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionMultiSelectActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionMultiSelectActionGroup.xml new file mode 100644 index 0000000000000..ebf14b3f27d12 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionMultiSelectActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectOptionMultiSelectActionGroup"> + <arguments> + <argument name="optionTitle" defaultValue="ProductOptionMultiSelect"/> + <argument name="option" defaultValue="ProductOptionValueMultiSelect2.title"/> + </arguments> + <selectOption selector="{{StorefrontProductInfoMainSection.productOptionSelect(optionTitle.title)}}" userInput="{{option}}" stepKey="selectOption"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionRadioButtonActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionRadioButtonActionGroup.xml new file mode 100644 index 0000000000000..844c9ede80232 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionRadioButtonActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectOptionRadioButtonActionGroup"> + <arguments> + <argument name="optionTitle" defaultValue="ProductOptionRadiobutton"/> + <argument name="optionPrice" defaultValue="ProductOptionValueRadioButtons2"/> + </arguments> + <checkOption selector="{{StorefrontProductInfoMainSection.productOptionRadioButtonsCheckbox(optionTitle.title, optionPrice.price)}}" stepKey="SelectOptionCheckBox"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionTimeActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionTimeActionGroup.xml new file mode 100644 index 0000000000000..bfa75eae70251 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSelectOptionTimeActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectOptionTimeActionGroup"> + <arguments> + <argument name="optionTitle" defaultValue="ProductOptionTime"/> + <argument name="hour" type="string"/> + <argument name="minute" type="string"/> + <argument name="dayPart" type="string"/> + </arguments> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionHour(optionTitle.title)}}" userInput="{{hour}}" stepKey="selectHourrForOptionDateTime"/> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionMinute(optionTitle.title)}}" userInput="{{minute}}" stepKey="selectMinuteForOptionDateTime"/> + <selectOption selector="{{StorefrontProductInfoMainSection.customOptionDayPart(optionTitle.title)}}" userInput="{{dayPart}}" stepKey="selectDayPartForOptionDateTime"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml index dcfb12fd4e965..52d1ecb834c09 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml @@ -33,5 +33,9 @@ <element name="productSubtotalByName" type="input" selector="//main//table[@id='shopping-cart-table']//tbody//tr[..//strong[contains(@class, 'product-item-name')]//a/text()='{{var1}}'][1]//td[contains(@class, 'subtotal')]//span[@class='price']" parameterized="true"/> <element name="updateShoppingCartButton" type="button" selector="#form-validate button[type='submit'].update" timeout="30"/> <element name="qty" type="input" selector="//input[@data-cart-item-id='{{var}}'][@title='Qty']" parameterized="true"/> + <element name="quantity" type="text" selector="//div[@class='field qty']//div/input[@value='{{qty}}']" parameterized="true"/> + <element name="productOptionLabel" type="text" selector="//dl[@class='item-options']"/> + <element name="checkoutCartProductPrice" type="text" selector="//td[@class='col price']//span[@class='price']"/> + <element name="checkoutCartSubtotal" type="text" selector="//td[@class='col subtotal']//span[@class='price']"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutOrderSummarySection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutOrderSummarySection.xml index 6e00329901757..3a5b16c5a52ca 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutOrderSummarySection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutOrderSummarySection.xml @@ -17,5 +17,6 @@ <element name="shippingAddress" type="textarea" selector="//*[@class='box box-address-shipping']//address"/> <element name="billingAddress" type="textarea" selector="//*[@class='box box-address-billing']//address"/> <element name="additionalAddress" type="text" selector=".block.block-addresses-list"/> + <element name="miniCartTabClosed" type="button" selector=".title[aria-expanded='false']" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml index 6838824400b96..28739d1f17949 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml @@ -19,6 +19,7 @@ <element name="telephone" type="input" selector="input[name=telephone]"/> <element name="next" type="button" selector="button.button.action.continue.primary" timeout="30"/> <element name="firstShippingMethod" type="radio" selector=".row:nth-of-type(1) .col-method .radio"/> + <element name="shippingBlock" type="text" selector="#checkout-step-shipping"/> <!--Order Summary--> <element name="itemInCart" type="button" selector="//div[@class='title']"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml index bdb02835c6276..4a872edadcf0b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml @@ -31,5 +31,9 @@ <element name="subtotal" type="text" selector="//tr[@class='totals sub']//td[@class='amount']/span"/> <element name="emptyCart" type="text" selector=".counter.qty.empty"/> <element name="minicartContent" type="block" selector="#minicart-content-wrapper"/> + <element name="visibleItemsCountText" type="text" selector="//div[@class='items-total']"/> + <element name="productQuantity" type="input" selector="//*[@id='mini-cart']//a[contains(text(),'{{productName}}')]/../..//div[@class='details-qty qty']//input[@data-item-qty='{{qty}}']" parameterized="true"/> + <element name="productImage" type="text" selector="//ol[@id='mini-cart']//img[@class='product-image-photo']"/> + <element name="productSubTotal" type="text" selector="//div[@class='subtotal']//span/span[@class='price']"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOptionTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOptionTest.xml new file mode 100644 index 0000000000000..23389e119d268 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOptionTest.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StoreFrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOptionTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="AddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOption"/> + <description value="Add simple product with all types of custom options to cart without selecting any options "/> + <testCaseId value="MC-14725"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <updateData createDataKey="createProduct" entity="productWithOptions" stepKey="updateProductWithCustomOptions"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + </before> + <after> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + </after> + + <!-- Open Product page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct1PageAndVerifyProduct"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + + <!--Click on Add To Cart button--> + <actionGroup ref="StorefrontAddToTheCartActionGroup" stepKey="clickOnAddToCartButton"/> + + <!--Assert all types of product options field displayed Required message --> + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="assertRequiredProductOptionField"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.requiredCustomField(ProductOptionField.title)}}"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="assertRequiredProductOptionDropDown"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.requiredCustomField(ProductOptionDropDown.title)}}"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="assertRequiredProductOptionRadioButton"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.requiredCustomField(ProductOptionRadiobutton.title)}}"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="assertRequiredProductOptionCheckBox"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.requiredCustomField(ProductOptionCheckbox.title)}}"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="assertRequiredProductOptionMultiSelect"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.requiredCustomField(ProductOptionMultiSelect.title)}}"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="assertRequiredProductFileOption"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.requiredCustomFile(ProductOptionFile.title)}}"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="assertRequiredProductDateOption"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.requiredCustomDate(ProductOptionDate.title)}}"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="assertRequiredProductDateAndTimeOption"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.requiredCustomDate(ProductOptionDateTime.title)}}"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="assertRequiredProducTimeOption"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.requiredCustomDate(ProductOptionTime.title)}}"/> + </actionGroup> + + <!-- Verify mini cart is empty --> + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="assertEmptryCart"> + <argument name="selector" value="{{StorefrontMiniCartSection.emptyMiniCart}}"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml new file mode 100644 index 0000000000000..027c21ae2ae82 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddBundleDynamicProductToShoppingCartTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="AddBundleDynamicProductToShoppingCart"/> + <description value="Add bundle dynamic product to the cart"/> + <testCaseId value="MC-14715"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> + <createData entity="SimpleSubCategory" stepKey="createSubCategory"/> + <!--Create simple product--> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">50.00</field> + </createData> + <!--Create Bundle product--> + <createData entity="BundleProductPriceViewRange" stepKey="createBundleProduct"> + <requiredEntity createDataKey="createSubCategory"/> + </createData> + <createData entity="DropDownBundleOption" stepKey="createBundleOption1_1"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="required">True</field> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> + <deleteData createDataKey="createSubCategory" stepKey="deleteCategory"/> + </after> + + <!--Open Product page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$createBundleProduct$$"/> + </actionGroup> + + <!--Assert Product Price Range --> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.priceFrom}}"/> + <argument name="userInput" value="From $10.00"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible1"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.priceTo}}"/> + <argument name="userInput" value="To $50.00"/> + </actionGroup> + + <!-- Click on customize And Add To Cart Button --> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickOnCustomizeAndAddtoCartButton"/> + + <!-- Select Product, Quantity and add to the cart --> + <click selector="{{StorefrontBundleProductActionSection.dropdownSelectOption}}" stepKey="clickOnSelectOption"/> + <click selector="{{StorefrontBundleProductActionSection.dropdownProductSelection($$simpleProduct2.name$$)}}" stepKey="selectProduct"/> + <actionGroup ref="StorefrontEnterProductQuantityAndAddToTheCartActionGroup" stepKey="enterProductQuantityAndAddToTheCart"> + <argument name="quantity" value="2"/> + </actionGroup> + + <!-- Select Mini Cart and select 'View And Edit Cart' --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="selectViewAndEditCart"/> + + <!--Assert Shopping Cart Summary--> + <actionGroup ref="AssertStorefrontShoppingCartSummaryWithShippingActionGroup" stepKey="AssertCartSummary" > + <argument name="subtotal" value="$100.00"/> + <argument name="shipping" value="$10.00"/> + <argument name="total" value="$110.00"/> + </actionGroup> + + <!--Assert Product items in cart --> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> + <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="subtotal" value="$100.00" /> + <argument name="qty" value="2"/> + </actionGroup> + + <!-- Assert Product Option In CheckOut Cart --> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionTitleInCart"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="$$createBundleOption1_1.title$$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionInCart"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="1 x $$simpleProduct2.name$$ $50.00"/> + </actionGroup> + + <!-- Assert Product in Mini Cart --> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct3MiniCart"> + <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="cartSubtotal" value="$100.00" /> + <argument name="qty" value="2"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml new file mode 100644 index 0000000000000..44fa46c9b941a --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="AddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebar"/> + <description value="Create Grouped product and verify mini cart action with disabled and enable Mini Cart Sidebar"/> + <testCaseId value="MC-14719"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <magentoCLI stepKey="disableShoppingCartSidebar" command="config:set checkout/sidebar/display 0"/> + <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> + <createData entity="SimpleSubCategory" stepKey="createSubCategory"/> + + <!--Create simple products--> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">50.00</field> + </createData> + + <!--Create Bundle product--> + <createData entity="BundleProductPriceViewRange" stepKey="createBundleProduct"> + <requiredEntity createDataKey="createSubCategory"/> + </createData> + <createData entity="DropDownBundleOption" stepKey="createBundleOption1_1"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="required">True</field> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> + <deleteData createDataKey="createSubCategory" stepKey="deleteCategory"/> + <magentoCLI stepKey="disableShoppingCartSidebar" command="config:set checkout/sidebar/display 1"/> + </after> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$createBundleProduct$$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.priceFrom}}"/> + <argument name="userInput" value="From $10.00"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible1"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.priceTo}}"/> + <argument name="userInput" value="To $50.00"/> + </actionGroup> + + <!-- Add Bundle dynamic product to the cart --> + <actionGroup ref="StorefrontAddBundleProductToTheCartActionGroup" stepKey="addBundleDynamicProductToTheCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + <argument name="quantity" value="2"/> + </actionGroup> + + <!-- Select Mini Cart, verify it doen't open --> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> + <dontSeeElement selector="{{StorefrontMinicartSection.viewAndEditCart}}" stepKey="dontSeeViewAndEditCart"/> + + <!--Assert Product items in cart --> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> + <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="subtotal" value="$100.00" /> + <argument name="qty" value="2"/> + </actionGroup> + + <!-- Assert Grouped product with option is displayed in cart --> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionTitle"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="$$createBundleOption1_1.title$$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionInCart"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="1 x $$simpleProduct2.name$$ $50.00"/> + </actionGroup> + + <!--Assert Shopping Cart Summary--> + <actionGroup ref="AssertStorefrontShoppingCartSummaryWithShippingActionGroup" stepKey="AssertCartSummary" > + <argument name="subtotal" value="$100.00"/> + <argument name="shipping" value="$10.00"/> + <argument name="total" value="$110.00"/> + </actionGroup> + + <!--Enabled Shopping Cart Sidebar --> + <magentoCLI stepKey="enableShoppingCartSidebar" command="config:set checkout/sidebar/display 1"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <reloadPage stepKey="reloadThePage"/> + + <!--Click on mini cart--> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart1"/> + + <!--Assert mini cart can open and check mini cart items --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProductInMiniCart1"> + <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="cartSubtotal" value="$100.00" /> + <argument name="qty" value="2"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml new file mode 100644 index 0000000000000..31c987a701f29 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddConfigurableProductToShoppingCartTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="AddConfigurableProductToShoppingCart"/> + <description value="Create configurable product with three options and add configurable product to the cart"/> + <testCaseId value="MC-14716"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <!-- Create Default Category --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + + <!-- Create an attribute with three options to be used in the first child product --> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption3" stepKey="createConfigProductAttributeOption3"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + + <!-- Add the attribute just created to default attribute set --> + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + + <!-- Get the first option of the attribute created --> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + + <!-- Get the second option of the attribute created --> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + + <!-- Get the third option of the attribute created --> + <getData entity="ProductAttributeOptionGetter" index="3" stepKey="getConfigAttributeOption3"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + + <!-- Create Configurable product --> + <createData entity="BaseConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + + <!-- Create a simple product and give it the attribute with the first option --> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <field key="price">10.00</field> + </createData> + + <!--Create a simple product and give it the attribute with the second option --> + <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + <field key="price">20.00</field> + </createData> + + <!--Create a simple product and give it the attribute with the Third option --> + <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct3"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption3"/> + <field key="price">30.00</field> + </createData> + + <!-- Create the configurable product --> + <createData entity="ConfigurableProductThreeOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + <requiredEntity createDataKey="getConfigAttributeOption3"/> + </createData> + + <!-- Add the first simple product to the configurable product --> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct1"/> + </createData> + + <!-- Add the second simple product to the configurable product --> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct2"/> + </createData> + + <!-- Add the third simple product to the configurable product --> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild3"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct3"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteSimpleProduct1"/> + <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteSimpleProduct2"/> + <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteSimpleProduct3"/> + <deleteData createDataKey="createConfigProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> + </after> + + <!-- Add Configurable Product to the cart --> + <actionGroup ref="StorefrontAddConfigurableProductToTheCartActionGroup" stepKey="addConfigurableProductToCart"> + <argument name="urlKey" value="$$createConfigProduct.custom_attributes[url_key]$$" /> + <argument name="productAttribute" value="$$createConfigProductAttribute.default_value$$"/> + <argument name="productOption" value="$$getConfigAttributeOption2.label$$"/> + <argument name="qty" value="2"/> + </actionGroup> + + <!-- Select Mini Cart and select 'View And Edit Cart' --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="selectViewAndEditCart"/> + + <!--Assert Shopping Cart Summary --> + <actionGroup ref="AssertStorefrontShoppingCartSummaryWithShippingActionGroup" stepKey="AssertCartSummary" > + <argument name="subtotal" value="$40.00"/> + <argument name="shipping" value="$10.00"/> + <argument name="total" value="$50.00"/> + </actionGroup> + + <!--Assert Product Details In Checkout cart --> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertProductItemInCheckOutCart"> + <argument name="productName" value="$$createConfigProduct.name$$"/> + <argument name="productPrice" value="$$createConfigChildProduct2.price$$"/> + <argument name="subtotal" value="$40.00" /> + <argument name="qty" value="2"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionInCart"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="$$getConfigAttributeOption2.label$$"/> + </actionGroup> + + <!-- Assert product details in Mini Cart --> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertMiniCart"> + <argument name="productName" value="$$createConfigProduct.name$$"/> + <argument name="productPrice" value="$$createConfigChildProduct2.price$$"/> + <argument name="cartSubtotal" value="$40.00" /> + <argument name="qty" value="2"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml new file mode 100644 index 0000000000000..fabdcc2da5d86 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddDownloadableProductToShoppingCartTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="AddDownloadableProductToShoppingCart"/> + <description value="Create Downloadable product with two links and add to the shopping cart"/> + <testCaseId value="MC-14717"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> + <createData entity="ApiDownloadableProduct" stepKey="createDownloadableProduct"/> + <createData entity="downloadableLink1" stepKey="addDownloadableLink1"> + <requiredEntity createDataKey="createDownloadableProduct"/> + </createData> + <createData entity="downloadableLink2" stepKey="addDownloadableLink2"> + <requiredEntity createDataKey="createDownloadableProduct"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="createDownloadableProduct" stepKey="deleteProduct"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Open Downloadable Product page --> + <amOnPage url="{{StorefrontProductPage.url($$createDownloadableProduct.custom_attributes[url_key]$$)}}" stepKey="OpenStoreFrontProductPage"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Add Downloadable product to the cart --> + <actionGroup ref="StorefrontAddToCartCustomOptionsProductPageActionGroup" stepKey="addToTheCart"> + <argument name="productName" value="$$createDownloadableProduct.name$$" /> + </actionGroup> + + <!-- Select Mini Cart and select 'View And Edit Cart' --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="selectViewAndEditCart"/> + + <!--Assert Shopping Cart Summary--> + <actionGroup ref="AssertStorefrontShoppingCartSummaryItemsActionGroup" stepKey="AssertCartSummary" > + <argument name="subtotal" value="$123.00"/> + <argument name="total" value="$123.00"/> + </actionGroup> + + <!--Assert Product Details In Checkout cart --> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertProductItemInCheckOutCart"> + <argument name="productName" value="$$createDownloadableProduct.name$$"/> + <argument name="productPrice" value="$123.00"/> + <argument name="subtotal" value="$123.00" /> + <argument name="qty" value="1"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeLinksInCart"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="Links"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionLink1"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="{{downloadableLink1.title}}"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionLink2"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="{{downloadableLink2.title}}"/> + </actionGroup> + + <!-- Assert product details in Mini Cart --> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertMiniCart"> + <argument name="productName" value="$$createDownloadableProduct.name$$"/> + <argument name="productPrice" value="$123.00"/> + <argument name="cartSubtotal" value="123.00" /> + <argument name="qty" value="1"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml new file mode 100644 index 0000000000000..90f3022cf2b8e --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddGroupedProductToShoppingCartTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="AddGroupedProductToShoppingCartTest"/> + <description value="Create grouped product with three simple product and Add grouped product to the cart "/> + <testCaseId value="MC-14718"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <!--Create Grouped product with three simple product --> + <createData entity="ApiProductWithDescription" stepKey="simple1" before="simple2"> + <field key="price">100.00</field> + </createData> + <createData entity="ApiProductWithDescription" stepKey="simple2" before="simple3"> + <field key="price">200.00</field> + </createData> + <createData entity="ApiProductWithDescription" stepKey="simple3" before="product"> + <field key="price">300.00</field> + </createData> + <createData entity="ApiGroupedProduct" stepKey="product"/> + <createData entity="OneSimpleProductLink" stepKey="addProductOne"> + <requiredEntity createDataKey="product"/> + <requiredEntity createDataKey="simple1"/> + </createData> + <updateData entity="OneMoreSimpleProductLink" createDataKey="addProductOne" stepKey="addProductTwo"> + <requiredEntity createDataKey="product"/> + <requiredEntity createDataKey="simple2"/> + </updateData> + <updateData entity="OneMoreSimpleProductLink" createDataKey="addProductOne" stepKey="addProductThree"> + <requiredEntity createDataKey="product"/> + <requiredEntity createDataKey="simple3"/> + </updateData> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simple1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simple2" stepKey="deleteProduct2"/> + <deleteData createDataKey="simple3" stepKey="deleteProduct3"/> + <deleteData createDataKey="product" stepKey="deleteGroupProduct"/> + </after> + + <!-- Fill Quantity and add Product to the cart --> + <actionGroup ref="StorefrontAddThreeGroupedProductToTheCartActionGroup" stepKey="addGropedProductsToTheCart"> + <argument name="urlKey" value="$$product.custom_attributes[url_key]$$"/> + <argument name="product1" value="$$simple1.name$$"/> + <argument name="product2" value="$$simple2.name$$"/> + <argument name="product3" value="$$simple3.name$$"/> + <argument name="qty1" value="1"/> + <argument name="qty2" value="2"/> + <argument name="qty3" value="3"/> + </actionGroup> + + <!-- Select Mini Cart and select 'View And Edit Cart' --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="selectViewAndEditCart"/> + + <!--Assert Product1 items in cart --> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> + <argument name="productName" value="$$simple1.name$$"/> + <argument name="productPrice" value="$100.00"/> + <argument name="subtotal" value="$100.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!--Assert Product2 items in cart --> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct2ItemsInCheckOutCart"> + <argument name="productName" value="$$simple2.name$$"/> + <argument name="productPrice" value="$200.00"/> + <argument name="subtotal" value="$400.00" /> + <argument name="qty" value="2"/> + </actionGroup> + + <!--Assert Product3 items in cart --> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct3ItemsInCheckOutCart"> + <argument name="productName" value="$$simple3.name$$"/> + <argument name="productPrice" value="$300.00"/> + <argument name="subtotal" value="$900.00" /> + <argument name="qty" value="3"/> + </actionGroup> + + <!--Assert Shopping Cart Summary--> + <actionGroup ref="AssertStorefrontShoppingCartSummaryWithShippingActionGroup" stepKey="AssertCartSummary" > + <argument name="subtotal" value="$1,400.00"/> + <argument name="shipping" value="$30.00"/> + <argument name="total" value="$1,430.00"/> + </actionGroup> + + <!-- Assert product1 details in Mini Cart --> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct3MiniCart"> + <argument name="productName" value="$$simple3.name$$"/> + <argument name="productPrice" value="$300.00"/> + <argument name="cartSubtotal" value="$1,400.00" /> + <argument name="qty" value="3"/> + </actionGroup> + + <!-- Assert product2 details in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct2MiniCart"> + <argument name="productName" value="$$simple2.name$$"/> + <argument name="productPrice" value="$200.00"/> + <argument name="cartSubtotal" value="$1,400.00" /> + <argument name="qty" value="2"/> + </actionGroup> + + <!-- Assert product3 details in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct1MiniCart"> + <argument name="productName" value="$$simple1.name$$"/> + <argument name="productPrice" value="$100.00"/> + <argument name="cartSubtotal" value="$1,400.00" /> + <argument name="qty" value="1"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml new file mode 100644 index 0000000000000..3cacb5b76b503 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="AddOneBundleMultiSelectOptionToTheShoppingCart"/> + <description value="Select one multi select option of a bundle product and add to the shopping cart "/> + <testCaseId value="MC-14727"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> + <createData entity="SimpleSubCategory" stepKey="createSubCategory"/> + <!--Create simple product--> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">50.00</field> + </createData> + <!--Create Bundle product with Multi Select option--> + <createData entity="BundleProductPriceViewRange" stepKey="createBundleProduct"> + <requiredEntity createDataKey="createSubCategory"/> + </createData> + <createData entity="MultipleSelectOption" stepKey="createBundleOption1_1"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="required">True</field> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> + <deleteData createDataKey="createSubCategory" stepKey="deleteCategory"/> + </after> + + <!--Open Product page in StoreFront and assert product details --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$createBundleProduct$$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.priceFrom}}"/> + <argument name="userInput" value="From $10.00"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible1"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.priceTo}}"/> + <argument name="userInput" value="To $60.00"/> + </actionGroup> + + <!-- Click on customize And Add To Cart Button --> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickOnCustomizeAndAddtoCartButton"/> + + <!-- Select One Product Option from MultiSelect option --> + <selectOption selector="{{StorefrontBundledSection.multiSelectOption}}" userInput="$$simpleProduct2.name$$ +$50.00" stepKey="selectOption2Product"/> + + <!--Enter product Quantity and add to the cart --> + <actionGroup ref="StorefrontEnterProductQuantityAndAddToTheCartActionGroup" stepKey="enterProductQuantityAndAddToTheCart"> + <argument name="quantity" value="1"/> + </actionGroup> + + <!-- Select Mini Cart and select 'View And Edit Cart' --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="selectViewAndEditCart"/> + + <!--Assert Shopping Cart Summary--> + <actionGroup ref="AssertStorefrontShoppingCartSummaryWithShippingActionGroup" stepKey="AssertCartSummary" > + <argument name="subtotal" value="$50.00"/> + <argument name="shipping" value="$5.00"/> + <argument name="total" value="$55.00"/> + </actionGroup> + + <!--Assert Product items in cart --> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> + <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="subtotal" value="$50.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Grouped product options is displayed in cart --> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionTitle"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="$$createBundleOption1_1.title$$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionInCart"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="1 x $$simpleProduct2.name$$ $50.00"/> + </actionGroup> + + <!-- Assert Product in Mini Cart --> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProductInMiniCart"> + <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="cartSubtotal" value="$50.00" /> + <argument name="qty" value="1"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml new file mode 100644 index 0000000000000..0f74032303eb9 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="AddSimpleProductsWithAllTypesOfCustomOptionsToTheShoppingCart"/> + <description value="Create a simple products with all types of oprtions and add it to the cart"/> + <testCaseId value="MC-14726"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <updateData createDataKey="createProduct" entity="productWithOptions" stepKey="updateProductWithCustomOptions"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + </before> + <after> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + </after> + <!-- Open Product page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct1PageAndVerifyProduct"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + + <!-- Fill Option Input field --> + <actionGroup ref="StorefrontFillOptionFieldInputActionGroup" stepKey="fillTheOptionFieldInput"> + <argument name="fieldInput" value="1"/> + </actionGroup> + + <!-- Fill Option Text Area --> + <actionGroup ref="StorefrontFillOptionTextAreaActionGroup" stepKey="fillTheOptionTextAreaInput"> + <argument name="fieldInput" value="1"/> + </actionGroup> + + <!-- Attach file option--> + <actionGroup ref="StorefrontAttachOptionFileActionGroup" stepKey="selectAndAttachFile"/> + + <!--Select Option From DropDown option --> + <actionGroup ref="StorefrontSelectOptionDropDownActionGroup" stepKey="selectDropDownOption"/> + <scrollTo selector="{{StorefrontProductInfoMainSection.customOptionLabel(ProductOptionMultiSelect.title)}}" stepKey="scrollToMultiSelect"/> + + <!-- Select CheckBox From CheckBox option --> + <actionGroup ref="StorefrontSelectOptionCheckBoxActionGroup" stepKey="selectCheckBoxOption"/> + + <!-- Select RadioButton From Radio Button option --> + <actionGroup ref="StorefrontSelectOptionRadioButtonActionGroup" stepKey="selectRadioButtonOption"/> + + <!-- Select option From MultiSelect option --> + <actionGroup ref="StorefrontSelectOptionMultiSelectActionGroup" stepKey="selectOptionFromMultiSelect"/> + + <!-- Generate Date --> + <generateDate date="Now" format="Y" stepKey="year"/> + + <!-- Select Month,Day and Year From Date option --> + <actionGroup ref="StorefrontSelectOptionDateActionGroup" stepKey="fillOptionDate"> + <argument name="month" value="11"/> + <argument name="day" value="10"/> + <argument name="year" value="$year"/> + </actionGroup> + + <!-- Select Month, Day, Year, Hour,Minute and DayPart from DateTime option --> + <actionGroup ref="StorefrontSelectOptionDateTimeActionGroup" stepKey="fillOptionDateAndTime"> + <argument name="month" value="11"/> + <argument name="day" value="10"/> + <argument name="year" value="$year"/> + <argument name="hour" value="10"/> + <argument name="minute" value="20"/> + <argument name="dayPart" value="AM"/> + </actionGroup> + + <!-- Select Hour,Minute and DayPart from Time option --> + <actionGroup ref="StorefrontSelectOptionTimeActionGroup" stepKey="fillOptionTime"> + <argument name="hour" value="10"/> + <argument name="minute" value="20"/> + <argument name="dayPart" value="AM"/> + </actionGroup> + + <!-- Add product to the cart --> + <fillField selector="{{StorefrontProductInfoMainSection.qty}}" userInput="2" stepKey="fillQuantity"/> + <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToTheCart"> + <argument name="product" value="$$createProduct$$"/> + <argument name="productCount" value="2"/> + </actionGroup> + + <!-- Open Mini Cart --> + <actionGroup ref="StorefrontOpenMiniCartActionGroup" stepKey="openMiniCart"/> + + <!-- Assert Product Count in Mini Cart --> + <actionGroup ref="StorefrontAssertMiniCartItemCountActionGroup" stepKey="assertProductCountAndTextInMiniCart"> + <argument name="productCount" value="2"/> + <argument name="productCountText" value="1 Item in Cart"/> + </actionGroup> + + <!--Assert Product Items in Mini cart--> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct3MiniCart"> + <argument name="productName" value="$$createProduct.name$$"/> + <argument name="productPrice" value="$1,642.58"/> + <argument name="cartSubtotal" value="$3,285.16" /> + <argument name="qty" value="2"/> + </actionGroup> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml new file mode 100644 index 0000000000000..232ac15f6be56 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="AddTwoBundleMultiSelectOptionsToTheShoppingCart"/> + <description value="Add two products to the cart from multi select options of a bundle product."/> + <testCaseId value="MC-14728"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> + <createData entity="SimpleSubCategory" stepKey="createSubCategory"/> + <!--Create simple product--> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">50.00</field> + </createData> + <!--Create Bundle product with multi select option--> + <createData entity="BundleProductPriceViewRange" stepKey="createBundleProduct"> + <requiredEntity createDataKey="createSubCategory"/> + </createData> + <createData entity="MultipleSelectOption" stepKey="createBundleOption1_1"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="required">True</field> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> + <deleteData createDataKey="createSubCategory" stepKey="deleteCategory"/> + </after> + + <!--Open Product page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$createBundleProduct$$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.priceFrom}}"/> + <argument name="userInput" value="From $10.00"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible1"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.priceTo}}"/> + <argument name="userInput" value="To $60.00"/> + </actionGroup> + + <!-- Click on customize And Add To Cart Button --> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickOnCustomizeAndAddtoCartButton"/> + + <!-- Select Two Products, enter the quantity and add product to the cart --> + <selectOption selector="{{StorefrontBundledSection.multiSelectOption}}" parameterArray="[$$simpleProduct1.name$$ +$10.00, $$simpleProduct2.name$$ +$50.00]" stepKey="selectOptions"/> + <actionGroup ref="StorefrontEnterProductQuantityAndAddToTheCartActionGroup" stepKey="enterProductQuantityAndAddToTheCart"> + <argument name="quantity" value="1"/> + </actionGroup> + + <!-- Select Mini Cart and select 'View And Edit Cart' --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="selectViewAndEditCart"/> + + <!--Assert Shopping Cart Summary--> + <actionGroup ref="AssertStorefrontShoppingCartSummaryWithShippingActionGroup" stepKey="AssertCartSummary" > + <argument name="subtotal" value="$60.00"/> + <argument name="shipping" value="$5.00"/> + <argument name="total" value="$65.00"/> + </actionGroup> + + <!--Assert Product items in cart --> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> + <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productPrice" value="$60.00"/> + <argument name="subtotal" value="$60.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Grouped product options is displayed in cart --> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionTitle"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="$$createBundleOption1_1.title$$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOption1InCart"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="1 x $$simpleProduct1.name$$ $10.00"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOption2InCart"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="1 x $$simpleProduct2.name$$ $50.00"/> + </actionGroup> + + <!-- Assert Product in Mini Cart --> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct3MiniCart"> + <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productPrice" value="$60.00"/> + <argument name="cartSubtotal" value="$60.00" /> + <argument name="qty" value="1"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndSummaryBlockItemDisplayWithDefaultDisplayLimitationTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndSummaryBlockItemDisplayWithDefaultDisplayLimitationTest.xml new file mode 100644 index 0000000000000..4acd8a232058a --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndSummaryBlockItemDisplayWithDefaultDisplayLimitationTest.xml @@ -0,0 +1,342 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCheckCartAndSummaryBlockItemDisplayWithDefaultDisplayLimitationTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="CheckCartAndSummaryBlockDisplayWithDefaultDisplayLimitation"/> + <description value="Add 10 items to the cart and check cart and summary block display with default display limit"/> + <testCaseId value="MC-14722"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> + <!--Create simple product--> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">20.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct3"> + <field key="price">30.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct4"> + <field key="price">40.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct5"> + <field key="price">50.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct6"> + <field key="price">60.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct7"> + <field key="price">70.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct8"> + <field key="price">80.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct9"> + <field key="price">90.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct10"> + <field key="price">100.00</field> + </createData> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="simpleProduct3" stepKey="deleteProduct3"/> + <deleteData createDataKey="simpleProduct4" stepKey="deleteProduct4"/> + <deleteData createDataKey="simpleProduct5" stepKey="deleteProduct5"/> + <deleteData createDataKey="simpleProduct6" stepKey="deleteProduct6"/> + <deleteData createDataKey="simpleProduct7" stepKey="deleteProduct7"/> + <deleteData createDataKey="simpleProduct8" stepKey="deleteProduct8"/> + <deleteData createDataKey="simpleProduct9" stepKey="deleteProduct9"/> + <deleteData createDataKey="simpleProduct10" stepKey="deleteProduct10"/> + </after> + + <!-- Open Product1 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct1PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct1$$"/> + </actionGroup> + + <!-- Add Product1 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct1ToTheCart"> + <argument name="productName" value="$$simpleProduct1.name$$"/> + </actionGroup> + + <!-- Open Product2 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct2PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct2$$"/> + </actionGroup> + + <!-- Add Product2 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct2ToTheCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + </actionGroup> + + <!-- Open Product3 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct3PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct3$$"/> + </actionGroup> + + <!-- Add Product3 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct3ToTheCart"> + <argument name="productName" value="$$simpleProduct3.name$$"/> + </actionGroup> + + <!-- Open Product4 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct4PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct4$$"/> + </actionGroup> + + <!-- Add Product4 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct4ToTheCart"> + <argument name="productName" value="$$simpleProduct4.name$$"/> + </actionGroup> + + <!-- Open Product5 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct5PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct5$$"/> + </actionGroup> + + <!-- Add Product5 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct5ToTheCart"> + <argument name="productName" value="$$simpleProduct5.name$$"/> + </actionGroup> + + <!-- Open Product6 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct6PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct6$$"/> + </actionGroup> + + <!-- Add Product6 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct6ToTheCart"> + <argument name="productName" value="$$simpleProduct6.name$$"/> + </actionGroup> + + <!-- Open Product7 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct7PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct7$$"/> + </actionGroup> + + <!-- Add Product7 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct7ToTheCart"> + <argument name="productName" value="$$simpleProduct7.name$$"/> + </actionGroup> + + <!-- Open Product8 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct8PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct8$$"/> + </actionGroup> + + <!-- Add Product8 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct8ToTheCart"> + <argument name="productName" value="$$simpleProduct8.name$$"/> + </actionGroup> + + <!-- Open Product9 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct9PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct9$$"/> + </actionGroup> + + <!-- Add Product9 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct9ToTheCart"> + <argument name="productName" value="$$simpleProduct9.name$$"/> + </actionGroup> + + <!-- Open Product10 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPage10AndVerifyProduct"> + <argument name="product" value="$$simpleProduct10$$"/> + </actionGroup> + + <!-- Add Product10 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct10ToTheCart"> + <argument name="productName" value="$$simpleProduct10.name$$"/> + </actionGroup> + + <!-- Open Mini Cart --> + <actionGroup ref="StorefrontOpenMiniCartActionGroup" stepKey="openMiniCart"/> + + <!-- Assert Product Count in Mini Cart --> + <actionGroup ref="StorefrontAssertMiniCartItemCountActionGroup" stepKey="assertProductCountAndTextInMiniCart"> + <argument name="productCount" value="10"/> + <argument name="productCountText" value="10 Items in Cart"/> + </actionGroup> + + <!-- Assert Product1 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct11MiniCart"> + <argument name="productName" value="$$simpleProduct1.name$$"/> + <argument name="productPrice" value="$10.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product2 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct2MiniCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + <argument name="productPrice" value="$20.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product3 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct3MiniCart"> + <argument name="productName" value="$$simpleProduct3.name$$"/> + <argument name="productPrice" value="$30.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product4 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct4MiniCart"> + <argument name="productName" value="$$simpleProduct4.name$$"/> + <argument name="productPrice" value="$40.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product5 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct5MiniCart"> + <argument name="productName" value="$$simpleProduct5.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product6 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct6MiniCart"> + <argument name="productName" value="$$simpleProduct6.name$$"/> + <argument name="productPrice" value="$60.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product7 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct7MiniCart"> + <argument name="productName" value="$$simpleProduct7.name$$"/> + <argument name="productPrice" value="$70.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product8 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct8MiniCart"> + <argument name="productName" value="$$simpleProduct8.name$$"/> + <argument name="productPrice" value="$80.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product9 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct9MiniCart"> + <argument name="productName" value="$$simpleProduct9.name$$"/> + <argument name="productPrice" value="$90.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product10 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct10MiniCart"> + <argument name="productName" value="$$simpleProduct10.name$$"/> + <argument name="productPrice" value="$100.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Order Summary --> + <actionGroup ref="StorefrontCheckoutAndAssertOrderSummaryDisplayActionGroup" stepKey="AssertOrderSummary"> + <argument name="itemsText" value="10 Items in Cart"/> + </actionGroup> + + <!-- Assert Shipping Page --> + <actionGroup ref="StorefrontAssertShippingAddressPageDisplayActionGroup" stepKey="assertShippingPageDisplay"/> + + <!--Click on order summary tab --> + <conditionalClick selector="{{CheckoutOrderSummarySection.miniCartTab}}" dependentSelector="{{CheckoutOrderSummarySection.miniCartTabClosed}}" visible="true" stepKey="clickOnOrderSummaryTab"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Assert Product1 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct1InOrderSummary"> + <argument name="productName" value="$$simpleProduct1.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$10.00"/> + </actionGroup> + + <!-- Assert Product2 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct2InOrderSummary"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$20.00"/> + </actionGroup> + + <!-- Assert Product3 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct3InOrderSummary"> + <argument name="productName" value="$$simpleProduct3.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$30.00"/> + </actionGroup> + + <!-- Assert Product4 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct4InOrderSummary"> + <argument name="productName" value="$$simpleProduct4.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$40.00"/> + </actionGroup> + + <!-- Assert Product5 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct5InOrderSummary"> + <argument name="productName" value="$$simpleProduct5.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$50.00"/> + </actionGroup> + + <!-- Assert Product6 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct6InOrderSummary"> + <argument name="productName" value="$$simpleProduct6.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$60.00"/> + </actionGroup> + + <!-- Assert Product7 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct7InOrderSummary"> + <argument name="productName" value="$$simpleProduct7.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$70.00"/> + </actionGroup> + + <!-- Assert Product8 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct8InOrderSummary"> + <argument name="productName" value="$$simpleProduct8.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$80.00"/> + </actionGroup> + + <!-- Assert Product9 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct9InOrderSummary"> + <argument name="productName" value="$$simpleProduct9.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$90.00"/> + </actionGroup> + + <!-- Assert Product10 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct10InOrderSummary"> + <argument name="productName" value="$$simpleProduct10.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$100.00"/> + </actionGroup> + + <!-- Verify View and Edit Cart is not displayed in Order Summary --> + <dontSeeElement selector="{{StorefrontMinicartSection.viewAndEditCart}}" stepKey="dontSeeViewAndEditLink"/> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimitTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimitTest.xml new file mode 100644 index 0000000000000..f1c50d04e460e --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimitTest.xml @@ -0,0 +1,282 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimitTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="CheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimit"/> + <description value="Add 11 Simple product to the cart and check cart display with default display limit"/> + <testCaseId value="MC-14720"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> + <!--Create simple product--> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">20.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct3"> + <field key="price">30.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct4"> + <field key="price">40.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct5"> + <field key="price">50.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct6"> + <field key="price">60.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct7"> + <field key="price">70.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct8"> + <field key="price">80.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct9"> + <field key="price">90.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct10"> + <field key="price">100.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct11"> + <field key="price">110.00</field> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="simpleProduct3" stepKey="deleteProduct3"/> + <deleteData createDataKey="simpleProduct4" stepKey="deleteProduct4"/> + <deleteData createDataKey="simpleProduct5" stepKey="deleteProduct5"/> + <deleteData createDataKey="simpleProduct6" stepKey="deleteProduct6"/> + <deleteData createDataKey="simpleProduct7" stepKey="deleteProduct7"/> + <deleteData createDataKey="simpleProduct8" stepKey="deleteProduct8"/> + <deleteData createDataKey="simpleProduct9" stepKey="deleteProduct9"/> + <deleteData createDataKey="simpleProduct10" stepKey="deleteProduct10"/> + <deleteData createDataKey="simpleProduct11" stepKey="deleteProduct11"/> + </after> + + <!-- Open Product1 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct1PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct1$$"/> + </actionGroup> + + <!-- Add Product1 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct1ToTheCart"> + <argument name="productName" value="$$simpleProduct1.name$$"/> + </actionGroup> + + <!-- Open Product2 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct2PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct2$$"/> + </actionGroup> + + <!-- Add Product2 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct2ToTheCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + </actionGroup> + + <!-- Open Product3 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct3PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct3$$"/> + </actionGroup> + + <!-- Add Product3 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct3ToTheCart"> + <argument name="productName" value="$$simpleProduct3.name$$"/> + </actionGroup> + + <!-- Open Product4 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct4PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct4$$"/> + </actionGroup> + + <!-- Add Product4 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct4ToTheCart"> + <argument name="productName" value="$$simpleProduct4.name$$"/> + </actionGroup> + + <!-- Open Product5 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct5PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct5$$"/> + </actionGroup> + + <!-- Add Product5 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct5ToTheCart"> + <argument name="productName" value="$$simpleProduct5.name$$"/> + </actionGroup> + + <!-- Open Product6 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct6PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct6$$"/> + </actionGroup> + + <!-- Add Product6 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct6ToTheCart"> + <argument name="productName" value="$$simpleProduct6.name$$"/> + </actionGroup> + + <!-- Open Product7 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct7PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct7$$"/> + </actionGroup> + + <!-- Add Product7 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct7ToTheCart"> + <argument name="productName" value="$$simpleProduct7.name$$"/> + </actionGroup> + + <!-- Open Product8 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct8PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct8$$"/> + </actionGroup> + + <!-- Add Product8 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct8ToTheCart"> + <argument name="productName" value="$$simpleProduct8.name$$"/> + </actionGroup> + + <!-- Open Product9 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct9PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct9$$"/> + </actionGroup> + + <!-- Add Product9 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct9ToTheCart"> + <argument name="productName" value="$$simpleProduct9.name$$"/> + </actionGroup> + + <!-- Open Product10 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPage10AndVerifyProduct"> + <argument name="product" value="$$simpleProduct10$$"/> + </actionGroup> + + <!-- Add Product10 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct10ToTheCart"> + <argument name="productName" value="$$simpleProduct10.name$$"/> + </actionGroup> + + <!-- Open Product11 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPage11AndVerifyProduct"> + <argument name="product" value="$$simpleProduct11$$"/> + </actionGroup> + + <!-- Add Product11 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct11ToTheCart"> + <argument name="productName" value="$$simpleProduct11.name$$"/> + </actionGroup> + + + <!-- Assert Product details in Mini Cart --> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductCountInMiniCart"> + <argument name="selector" value="{{StorefrontMinicartSection.productCount}}"/> + <argument name="userInput" value="11"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeTotalNumberOfItemDisplayed"> + <argument name="selector" value="{{StorefrontMinicartSection.visibleItemsCountText}}"/> + <argument name="userInput" value="10 of 11 Items in Cart"/> + </actionGroup> + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="seeViewAndEditLink"> + <argument name="selector" value="{{StorefrontMinicartSection.viewAndEditCart}}"/> + </actionGroup> + + <!-- Assert Product1 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct1InMiniCart"> + <argument name="productName" value="$$simpleProduct1.name$$"/> + <argument name="productPrice" value="$10.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product2 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct2InMiniCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + <argument name="productPrice" value="$20.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product3 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct3MiniCart"> + <argument name="productName" value="$$simpleProduct3.name$$"/> + <argument name="productPrice" value="$30.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product4 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct4InMiniCart"> + <argument name="productName" value="$$simpleProduct4.name$$"/> + <argument name="productPrice" value="$40.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product5 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct5InMiniCart"> + <argument name="productName" value="$$simpleProduct5.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product6 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct6InMiniCart"> + <argument name="productName" value="$$simpleProduct6.name$$"/> + <argument name="productPrice" value="$60.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product7 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct7InMiniCart"> + <argument name="productName" value="$$simpleProduct7.name$$"/> + <argument name="productPrice" value="$70.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product8 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct8InMiniCart"> + <argument name="productName" value="$$simpleProduct8.name$$"/> + <argument name="productPrice" value="$80.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product9 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct9InMiniCart"> + <argument name="productName" value="$$simpleProduct9.name$$"/> + <argument name="productPrice" value="$90.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product10 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct10InMiniCart"> + <argument name="productName" value="$$simpleProduct10.name$$"/> + <argument name="productPrice" value="$100.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Verify Product11 is not displayed in Mini Cart --> + <dontSee selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="$$simpleProduct11.name$$" stepKey="dontSeeProduct11NameInMiniCart"/> + <dontSee selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="110" stepKey="dontSeeProduct11PriceInMiniCart"/> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantityTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantityTest.xml new file mode 100644 index 0000000000000..53fbb8eeef513 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantityTest.xml @@ -0,0 +1,256 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantityTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="CheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantity"/> + <description value="Add 10 itemsto the cart and check cart display with default display limit"/> + <testCaseId value="MC-14721"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <!--Create simple product--> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">20.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct3"> + <field key="price">30.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct4"> + <field key="price">40.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct5"> + <field key="price">50.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct6"> + <field key="price">60.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct7"> + <field key="price">70.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct8"> + <field key="price">80.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct9"> + <field key="price">90.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct10"> + <field key="price">100.00</field> + </createData> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="simpleProduct3" stepKey="deleteProduct3"/> + <deleteData createDataKey="simpleProduct4" stepKey="deleteProduct4"/> + <deleteData createDataKey="simpleProduct5" stepKey="deleteProduct5"/> + <deleteData createDataKey="simpleProduct6" stepKey="deleteProduct6"/> + <deleteData createDataKey="simpleProduct7" stepKey="deleteProduct7"/> + <deleteData createDataKey="simpleProduct8" stepKey="deleteProduct8"/> + <deleteData createDataKey="simpleProduct9" stepKey="deleteProduct9"/> + <deleteData createDataKey="simpleProduct10" stepKey="deleteProduct10"/> + </after> + + <!-- Open Product1 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct1PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct1$$"/> + </actionGroup> + + <!-- Add Product1 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct1ToTheCart"> + <argument name="productName" value="$$simpleProduct1.name$$"/> + </actionGroup> + + <!-- Open Product2 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct2PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct2$$"/> + </actionGroup> + + <!-- Add Product2 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct2ToTheCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + </actionGroup> + + <!-- Open Product3 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct3PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct3$$"/> + </actionGroup> + + <!-- Add Product3 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct3ToTheCart"> + <argument name="productName" value="$$simpleProduct3.name$$"/> + </actionGroup> + + <!-- Open Product4 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct4PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct4$$"/> + </actionGroup> + + <!-- Add Product4 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct4ToTheCart"> + <argument name="productName" value="$$simpleProduct4.name$$"/> + </actionGroup> + + <!-- Open Product5 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct5PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct5$$"/> + </actionGroup> + + <!-- Add Product5 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct5ToTheCart"> + <argument name="productName" value="$$simpleProduct5.name$$"/> + </actionGroup> + + <!-- Open Product6 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct6PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct6$$"/> + </actionGroup> + + <!-- Add Product6 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct6ToTheCart"> + <argument name="productName" value="$$simpleProduct6.name$$"/> + </actionGroup> + + <!-- Open Product7 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct7PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct7$$"/> + </actionGroup> + + <!-- Add Product7 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct7ToTheCart"> + <argument name="productName" value="$$simpleProduct7.name$$"/> + </actionGroup> + + <!-- Open Product8 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct8PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct8$$"/> + </actionGroup> + + <!-- Add Product8 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct8ToTheCart"> + <argument name="productName" value="$$simpleProduct8.name$$"/> + </actionGroup> + + <!-- Open Product9 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct9PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct9$$"/> + </actionGroup> + + <!-- Add Product9 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct9ToTheCart"> + <argument name="productName" value="$$simpleProduct9.name$$"/> + </actionGroup> + + <!-- Open Product10 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPage10AndVerifyProduct"> + <argument name="product" value="$$simpleProduct10$$"/> + </actionGroup> + + <!-- Add Product10 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct10ToTheCart"> + <argument name="productName" value="$$simpleProduct10.name$$"/> + </actionGroup> + + <!-- Open Mini Cart --> + <actionGroup ref="StorefrontOpenMiniCartActionGroup" stepKey="openMiniCart"/> + + <!-- Assert Product Count in Mini Cart --> + <actionGroup ref="StorefrontAssertMiniCartItemCountActionGroup" stepKey="assertProductCountAndTextInMiniCart"> + <argument name="productCount" value="10"/> + <argument name="productCountText" value="10 Items in Cart"/> + </actionGroup> + + <!-- Assert Product1 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct11MiniCart"> + <argument name="productName" value="$$simpleProduct1.name$$"/> + <argument name="productPrice" value="$10.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product2 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct2MiniCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + <argument name="productPrice" value="$20.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product3 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct3MiniCart"> + <argument name="productName" value="$$simpleProduct3.name$$"/> + <argument name="productPrice" value="$30.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product4 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct4MiniCart"> + <argument name="productName" value="$$simpleProduct4.name$$"/> + <argument name="productPrice" value="$40.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product5 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct5MiniCart"> + <argument name="productName" value="$$simpleProduct5.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product6 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct6MiniCart"> + <argument name="productName" value="$$simpleProduct6.name$$"/> + <argument name="productPrice" value="$60.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product7 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct7MiniCart"> + <argument name="productName" value="$$simpleProduct7.name$$"/> + <argument name="productPrice" value="$70.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product8 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct8MiniCart"> + <argument name="productName" value="$$simpleProduct8.name$$"/> + <argument name="productPrice" value="$80.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product9 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct9MiniCart"> + <argument name="productName" value="$$simpleProduct9.name$$"/> + <argument name="productPrice" value="$90.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product10 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct10MiniCart"> + <argument name="productName" value="$$simpleProduct10.name$$"/> + <argument name="productPrice" value="$100.00"/> + <argument name="cartSubtotal" value="$550.00" /> + <argument name="qty" value="1"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckSimpleProductCartItemDisplayWithDefaultLimitationTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckSimpleProductCartItemDisplayWithDefaultLimitationTest.xml new file mode 100644 index 0000000000000..9ef8856f401e1 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckSimpleProductCartItemDisplayWithDefaultLimitationTest.xml @@ -0,0 +1,356 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCheckSimpleProductCartItemDisplayWithDefaultLimitationTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="CheckSimpleProductCartItemDisplayWithDefaultLimitation"/> + <description value="Add 10 SimpleProducts to the cart and check cart display with default display limit"/> + <testCaseId value="MC-14723"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> + <!--Create simple product--> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">20.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct3"> + <field key="price">30.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct4"> + <field key="price">40.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct5"> + <field key="price">50.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct6"> + <field key="price">60.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct7"> + <field key="price">70.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct8"> + <field key="price">80.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct9"> + <field key="price">90.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct10"> + <field key="price">100.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct11"> + <field key="price">110.00</field> + </createData> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="simpleProduct3" stepKey="deleteProduct3"/> + <deleteData createDataKey="simpleProduct4" stepKey="deleteProduct4"/> + <deleteData createDataKey="simpleProduct5" stepKey="deleteProduct5"/> + <deleteData createDataKey="simpleProduct6" stepKey="deleteProduct6"/> + <deleteData createDataKey="simpleProduct7" stepKey="deleteProduct7"/> + <deleteData createDataKey="simpleProduct8" stepKey="deleteProduct8"/> + <deleteData createDataKey="simpleProduct9" stepKey="deleteProduct9"/> + <deleteData createDataKey="simpleProduct10" stepKey="deleteProduct10"/> + <deleteData createDataKey="simpleProduct11" stepKey="deleteProduct11"/> + </after> + + <!-- Open Product1 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct1PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct1$$"/> + </actionGroup> + + <!-- Add Product1 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct1ToTheCart"> + <argument name="productName" value="$$simpleProduct1.name$$"/> + </actionGroup> + + <!-- Open Product2 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct2PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct2$$"/> + </actionGroup> + + <!-- Add Product2 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct2ToTheCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + </actionGroup> + + <!-- Open Product3 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct3PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct3$$"/> + </actionGroup> + + <!-- Add Product3 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct3ToTheCart"> + <argument name="productName" value="$$simpleProduct3.name$$"/> + </actionGroup> + + <!-- Open Product4 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct4PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct4$$"/> + </actionGroup> + + <!-- Add Product4 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct4ToTheCart"> + <argument name="productName" value="$$simpleProduct4.name$$"/> + </actionGroup> + + <!-- Open Product5 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct5PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct5$$"/> + </actionGroup> + + <!-- Add Product5 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct5ToTheCart"> + <argument name="productName" value="$$simpleProduct5.name$$"/> + </actionGroup> + + <!-- Open Product6 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct6PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct6$$"/> + </actionGroup> + + <!-- Add Product6 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct6ToTheCart"> + <argument name="productName" value="$$simpleProduct6.name$$"/> + </actionGroup> + + <!-- Open Product7 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct7PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct7$$"/> + </actionGroup> + + <!-- Add Product7 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct7ToTheCart"> + <argument name="productName" value="$$simpleProduct7.name$$"/> + </actionGroup> + + <!-- Open Product8 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct8PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct8$$"/> + </actionGroup> + + <!-- Add Product8 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct8ToTheCart"> + <argument name="productName" value="$$simpleProduct8.name$$"/> + </actionGroup> + + <!-- Open Product9 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct9PageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct9$$"/> + </actionGroup> + + <!-- Add Product9 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct9ToTheCart"> + <argument name="productName" value="$$simpleProduct9.name$$"/> + </actionGroup> + + <!-- Open Product10 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPage10AndVerifyProduct"> + <argument name="product" value="$$simpleProduct10$$"/> + </actionGroup> + + <!-- Add Product10 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct10ToTheCart"> + <argument name="productName" value="$$simpleProduct10.name$$"/> + </actionGroup> + + <!-- Open Product11 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPage11AndVerifyProduct"> + <argument name="product" value="$$simpleProduct11$$"/> + </actionGroup> + + <!-- Add Product11 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct11ToTheCart"> + <argument name="productName" value="$$simpleProduct11.name$$"/> + </actionGroup> + + <!-- Open Mini Cart --> + <actionGroup ref="StorefrontOpenMiniCartActionGroup" stepKey="openMiniCart"/> + + <!-- Assert Product Count in Mini Cart --> + <actionGroup ref="StorefrontAssertMiniCartItemCountActionGroup" stepKey="assertProductCountAndTextInMiniCart"> + <argument name="productCount" value="11"/> + <argument name="productCountText" value="10 of 11 Items in Cart"/> + </actionGroup> + + <!-- Assert Product1 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct11MiniCart"> + <argument name="productName" value="$$simpleProduct1.name$$"/> + <argument name="productPrice" value="$10.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product2 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct2MiniCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + <argument name="productPrice" value="$20.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product3 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct3MiniCart"> + <argument name="productName" value="$$simpleProduct3.name$$"/> + <argument name="productPrice" value="$30.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product4 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct4MiniCart"> + <argument name="productName" value="$$simpleProduct4.name$$"/> + <argument name="productPrice" value="$40.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product5 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct5MiniCart"> + <argument name="productName" value="$$simpleProduct5.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product6 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct6MiniCart"> + <argument name="productName" value="$$simpleProduct6.name$$"/> + <argument name="productPrice" value="$60.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product7 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct7MiniCart"> + <argument name="productName" value="$$simpleProduct7.name$$"/> + <argument name="productPrice" value="$70.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product8 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct8MiniCart"> + <argument name="productName" value="$$simpleProduct8.name$$"/> + <argument name="productPrice" value="$80.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product9 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct9MiniCart"> + <argument name="productName" value="$$simpleProduct9.name$$"/> + <argument name="productPrice" value="$90.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product10 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct10MiniCart"> + <argument name="productName" value="$$simpleProduct10.name$$"/> + <argument name="productPrice" value="$100.00"/> + <argument name="cartSubtotal" value="$660.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Order Summary --> + <actionGroup ref="StorefrontCheckoutAndAssertOrderSummaryDisplayActionGroup" stepKey="AssertItemsCountInOrderSummary"> + <argument name="itemsText" value="10 of 11 Items in Cart"/> + </actionGroup> + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="seeViewAndEditLinkInOrderSummary"> + <argument name="selector" value="{{StorefrontMinicartSection.viewAndEditCart}}"/> + </actionGroup> + + <!-- Click and open order summary tab--> + <conditionalClick selector="{{CheckoutOrderSummarySection.miniCartTab}}" dependentSelector="{{CheckoutOrderSummarySection.miniCartTabClosed}}" visible="true" stepKey="clickOnOrderSummaryTab"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Assert Shipping Page --> + <actionGroup ref="StorefrontAssertShippingAddressPageDisplayActionGroup" stepKey="assertShippingPageDisplay"/> + + <!-- Assert Product2 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct2InOrderSummary"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$20.00"/> + </actionGroup> + + <!-- Assert Product3 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct3InOrderSummary"> + <argument name="productName" value="$$simpleProduct3.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$30.00"/> + </actionGroup> + + <!-- Assert Product4 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct4InOrderSummary"> + <argument name="productName" value="$$simpleProduct4.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$40.00"/> + </actionGroup> + + <!-- Assert Product5 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct5InOrderSummary"> + <argument name="productName" value="$$simpleProduct5.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$50.00"/> + </actionGroup> + + <!-- Assert Product6 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct6InOrderSummary"> + <argument name="productName" value="$$simpleProduct6.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$60.00"/> + </actionGroup> + + <!-- Assert Product7 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct7InOrderSummary"> + <argument name="productName" value="$$simpleProduct7.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$70.00"/> + </actionGroup> + + <!-- Assert Product8 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct8InOrderSummary"> + <argument name="productName" value="$$simpleProduct8.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$80.00"/> + </actionGroup> + + <!-- Assert Product9 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct9InOrderSummary"> + <argument name="productName" value="$$simpleProduct9.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$90.00"/> + </actionGroup> + + <!-- Assert Product10 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct10InOrderSummary"> + <argument name="productName" value="$$simpleProduct10.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$100.00"/> + </actionGroup> + + <!-- Assert Product11 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct11InOrderSummary"> + <argument name="productName" value="$$simpleProduct11.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$110.00"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckVirtualProductCountDisplayWithCustomDisplayConfigurationTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckVirtualProductCountDisplayWithCustomDisplayConfigurationTest.xml new file mode 100644 index 0000000000000..c8e343e695f10 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckVirtualProductCountDisplayWithCustomDisplayConfigurationTest.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCheckVirtualProductCountDisplayWithCustomDisplayConfigurationTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="CheckVirtualProductCountDisplayWithCustomDisplayConfiguration"/> + <description value="Verify virtual products count in mini cart and summary block with custom display configuration"/> + <testCaseId value="MC-14724"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <!--Set Mini Cart and Summary Block Display --> + <magentoCLI stepKey="setMaxDisplayCountForMiniCart" command="config:set checkout/options/max_items_display_count 2"/> + <magentoCLI stepKey="setMaxDisplayCountForOrderSummary" command="config:set checkout/sidebar/max_items_display_count 3"/> + <!--Create simple product--> + <createData entity="VirtualProduct" stepKey="virtualProduct1"> + <field key="price">10.00</field> + </createData> + <createData entity="VirtualProduct" stepKey="virtualProduct2"> + <field key="price">20.00</field> + </createData> + <createData entity="VirtualProduct" stepKey="virtualProduct3"> + <field key="price">30.00</field> + </createData> + <createData entity="VirtualProduct" stepKey="virtualProduct4"> + <field key="price">40.00</field> + </createData> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="virtualProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="virtualProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="virtualProduct3" stepKey="deleteProduct3"/> + <deleteData createDataKey="virtualProduct4" stepKey="deleteProduct4"/> + <magentoCLI stepKey="setMaxDisplayCountForMiniCart" command="config:set checkout/options/max_items_display_count 10"/> + <magentoCLI stepKey="setMaxDisplayCountForOrderSummary" command="config:set checkout/sidebar/max_items_display_count 10"/> + </after> + + <!-- Open Product1 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct1PageAndVerifyProduct"> + <argument name="product" value="$$virtualProduct1$$"/> + </actionGroup> + + <!-- Add Product1 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct1ToTheCart"> + <argument name="productName" value="$$virtualProduct1.name$$"/> + </actionGroup> + + <!-- Open Product2 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct2PageAndVerifyProduct"> + <argument name="product" value="$$virtualProduct2$$"/> + </actionGroup> + + <!-- Add Product2 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct2ToTheCart"> + <argument name="productName" value="$$virtualProduct2.name$$"/> + </actionGroup> + + <!-- Open Product3 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct3PageAndVerifyProduct"> + <argument name="product" value="$$virtualProduct3$$"/> + </actionGroup> + + <!-- Add Product3 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct3ToTheCart"> + <argument name="productName" value="$$virtualProduct3.name$$"/> + </actionGroup> + + <!-- Open Product4 page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct4PageAndVerifyProduct"> + <argument name="product" value="$$virtualProduct4$$"/> + </actionGroup> + + <!-- Add Product4 to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct4ToTheCart"> + <argument name="productName" value="$$virtualProduct4.name$$"/> + </actionGroup> + + <!-- Open Mini Cart --> + <actionGroup ref="StorefrontOpenMiniCartActionGroup" stepKey="openMiniCart"/> + + <!-- Assert Product Count in Mini Cart --> + <actionGroup ref="StorefrontAssertMiniCartItemCountActionGroup" stepKey="assertProductCountAndTextInMiniCart"> + <argument name="productCount" value="4"/> + <argument name="productCountText" value="3 of 4 Items in Cart"/> + </actionGroup> + + <!-- Assert Product1 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct11MiniCart"> + <argument name="productName" value="$$virtualProduct1.name$$"/> + <argument name="productPrice" value="$10.00"/> + <argument name="cartSubtotal" value="$100.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product2 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct2MiniCart"> + <argument name="productName" value="$$virtualProduct2.name$$"/> + <argument name="productPrice" value="$20.00"/> + <argument name="cartSubtotal" value="$100.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Product3 in Mini Cart --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProduct3MiniCart"> + <argument name="productName" value="$$virtualProduct3.name$$"/> + <argument name="productPrice" value="$30.00"/> + <argument name="cartSubtotal" value="$100.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Assert Order Summary --> + <actionGroup ref="StorefrontCheckoutAndAssertOrderSummaryDisplayActionGroup" stepKey="AssertItemCountInOrderSummary"> + <argument name="itemsText" value="2 of 4 Items in Cart"/> + </actionGroup> + <actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="seeViewAndEditLinkInOrderSummary"> + <argument name="selector" value="{{StorefrontMinicartSection.viewAndEditCart}}"/> + </actionGroup> + + <!-- Click and open order summary tab--> + <conditionalClick selector="{{CheckoutOrderSummarySection.miniCartTab}}" dependentSelector="{{CheckoutOrderSummarySection.miniCartTabClosed}}" visible="true" stepKey="clickOnOrderSummaryTab"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Assert Product3 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct3InOrderSummary"> + <argument name="productName" value="$$virtualProduct3.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$30.00"/> + </actionGroup> + + <!-- Assert Product4 displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct4InOrderSummary"> + <argument name="productName" value="$$virtualProduct4.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$40.00"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontAddConfigurableProductToTheCartActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontAddConfigurableProductToTheCartActionGroup.xml new file mode 100644 index 0000000000000..9e3935501adee --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontAddConfigurableProductToTheCartActionGroup.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAddConfigurableProductToTheCartActionGroup"> + <arguments> + <argument name="urlKey" type="string"/> + <argument name="productAttribute" type="string"/> + <argument name="productOption" type="string" /> + <argument name="qty" type="string"/> + </arguments> + <amOnPage url="{{urlKey}}.html" stepKey="goToStorefrontPage"/> + <waitForPageLoad stepKey="waitForProductFrontPageToLoad"/> + <selectOption selector="{{StorefrontProductInfoMainSection.productOptionSelect(productAttribute)}}" userInput="{{productOption}}" stepKey="selectOption1"/> + <fillField selector="{{StorefrontProductPageSection.qtyInput}}" userInput="{{qty}}" stepKey="fillProductQuantity"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="clickOnAddToCartButton"/> + <waitForPageLoad stepKey="waitForProductToAddInCart"/> + <seeElement selector="{{StorefrontProductPageSection.successMsg}}" stepKey="seeSuccessSaveMessage"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/StorefrontAddThreeGroupedProductToTheCartActionGroup.xml b/app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/StorefrontAddThreeGroupedProductToTheCartActionGroup.xml new file mode 100644 index 0000000000000..ba198ea9992d7 --- /dev/null +++ b/app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/StorefrontAddThreeGroupedProductToTheCartActionGroup.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!--Check that required fields are actually required--> + <actionGroup name="StorefrontAddThreeGroupedProductToTheCartActionGroup"> + <arguments> + <argument name="urlKey" type="string"/> + <argument name="product1" type="string"/> + <argument name="product2" type="string"/> + <argument name="product3" type="string"/> + <argument name="qty1" type="string"/> + <argument name="qty2" type="string"/> + <argument name="qty3" type="string"/> + </arguments> + <amOnPage url="{{StorefrontProductPage.url(urlKey)}}" stepKey="OpenStoreFrontProductPage"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <fillField stepKey="fillQuantityForProduct1" selector="{{StorefrontProductPageSection.qtyInputWithProduct(product1)}}" userInput="{{qty1}}"/> + <fillField stepKey="fillQuantityForProduct2" selector="{{StorefrontProductPageSection.qtyInputWithProduct(product2)}}" userInput="{{qty2}}"/> + <fillField stepKey="fillQuantityForProduct3" selector="{{StorefrontProductPageSection.qtyInputWithProduct(product3)}}" userInput="{{qty3}}"/> + <click selector="{{StorefrontProductPageSection.addToCartBtn}}" stepKey="clickOnAddToCartButton"/> + </actionGroup> +</actionGroups> + From 61830fd266666bcfbfdc588e854419fc6c235129 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 23 Mar 2019 18:33:44 +0100 Subject: [PATCH 078/585] Convert ResetUserPasswordFailedTest to MFTF --- .../Mftf/Page/AdminForgotPasswordPage.xml | 14 +++++++ .../Backend/Test/Mftf/Page/AdminLoginPage.xml | 1 + .../AdminForgotPasswordFormSection.xml | 15 ++++++++ .../Mftf/Section/AdminLoginFormSection.xml | 1 + .../Section/AdminUserLoginMessagesSection.xml | 15 ++++++++ .../Mftf/Test/ResetUserPasswordFailedTest.xml | 37 +++++++++++++++++++ .../TestCase/ResetUserPasswordFailedTest.xml | 1 + 7 files changed, 84 insertions(+) create mode 100644 app/code/Magento/Backend/Test/Mftf/Page/AdminForgotPasswordPage.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml create mode 100644 app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Page/AdminForgotPasswordPage.xml b/app/code/Magento/Backend/Test/Mftf/Page/AdminForgotPasswordPage.xml new file mode 100644 index 0000000000000..84af56d102d84 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Page/AdminForgotPasswordPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminForgotPasswordPage" url="admin/auth/forgotpassword/" area="admin" module="Magento_Backend"> + <section name="AdminForgotPasswordFormSection"/> + </page> +</pages> diff --git a/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml b/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml index b68b9914186f6..a499c8f5ed7a7 100644 --- a/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml +++ b/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml @@ -9,6 +9,7 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminLoginPage" url="admin" area="admin" module="Magento_Backend"> + <section name="AdminUserLoginMessagesSection"/> <section name="AdminLoginFormSection"/> </page> </pages> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml new file mode 100644 index 0000000000000..5c33369b38767 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminForgotPasswordFormSection"> + <element name="email" type="input" selector="#email"/> + <element name="retrievePasswordButton" type="button" selector=".action-retrieve" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 3b10fac7bb9dc..9092ef31bbdca 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,5 +12,6 @@ <element name="username" type="input" selector="#username"/> <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> + <element name="forgotPasswordLink" type="link" selector=".action-forgotpassword" timeout="10"/> </section> </sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml new file mode 100644 index 0000000000000..209a795dc48ae --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminUserLoginMessagesSection"> + <element name="successMessage" type="text" selector=".message-success"/> + <element name="errorMessage" type="text" selector=".message-error"/> + </section> +</sections> diff --git a/app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml b/app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml new file mode 100644 index 0000000000000..3a614c91aeebc --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ResetUserPasswordFailedTest"> + <annotations> + <features value="User"/> + <title value="Admin user should not be able to trigger the password reset procedure twice"/> + <description value="Admin user should not be able to trigger the password reset procedure twice"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <magentoCLI command="config:set admin/captcha/enable 0" stepKey="disableAdminCaptcha"/> + </before> + + <amOnPage url="{{AdminLoginPage.url}}" stepKey="amOnAdminLoginPage"/> + <waitForPageLoad stepKey="waitForAdminLoginPage1"/> + <click stepKey="clickForgotPasswordLink1" selector="{{AdminLoginFormSection.forgotPasswordLink}}"/> + <fillField selector="{{AdminForgotPasswordFormSection.email}}" userInput="some@example.com" stepKey="fillAdminEmail1"/> + <click selector="{{AdminForgotPasswordFormSection.retrievePasswordButton}}" stepKey="clickOnRetrievePasswordButton1"/> + <waitForElementVisible selector="{{AdminUserLoginMessagesSection.successMessage}}" stepKey="waitForSuccessMessage" /> + <see stepKey="seeSuccessMessage" selector="{{AdminUserLoginMessagesSection.successMessage}}" userInput="We'll email you a link to reset your password."/> + <click stepKey="clickForgotPasswordLink2" selector="{{AdminLoginFormSection.forgotPasswordLink}}"/> + <waitForPageLoad stepKey="waitForAdminForgotPasswordPage2"/> + <fillField selector="{{AdminForgotPasswordFormSection.email}}" userInput="some@example.com" stepKey="fillAdminEmail2"/> + <click selector="{{AdminForgotPasswordFormSection.retrievePasswordButton}}" stepKey="clickOnRetrievePasswordButton2"/> + <waitForElementVisible selector="{{AdminUserLoginMessagesSection.errorMessage}}" stepKey="waitForFailMessage" /> + <see stepKey="seeErrorMessage" selector="{{AdminUserLoginMessagesSection.errorMessage}}" userInput="We received too many requests for password resets. Please wait and try again later or contact hello@example.com."/> + </test> +</tests> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml index 55f1b69504363..229e980fed91f 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml @@ -11,6 +11,7 @@ <data name="tag" xsi:type="string">severity:S1</data> <data name="customAdmin/dataset" xsi:type="string">custom_admin_with_default_role</data> <data name="attempts" xsi:type="string">2</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserPasswordResetFailed" /> </variation> </testCase> From 1688e1e9edadcfe189bffd272283e569bfe81d29 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 25 Mar 2019 10:57:14 +0200 Subject: [PATCH 079/585] MC-15406: [FT] [MFTF] StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest fails because of bad design --- .../Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml index 15fc413c7ec92..b0c00f56b6d3b 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml @@ -31,7 +31,7 @@ </actionGroup> <actionGroup name="AdminCreateStoreViewWithoutCheckActionGroup" extends="AdminCreateStoreViewActionGroup"> - <remove keyForRemoval="waitForPageReolad"/> + <remove keyForRemoval="waitForPageReload"/> <remove keyForRemoval="seeSavedMessage"/> </actionGroup> From 12674368b0ae77c3a0e4b72e4ee0fa91fa028395 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Mon, 25 Mar 2019 16:14:17 +0200 Subject: [PATCH 080/585] magento/graphql-ce#530: [Cart Operations] Update Cart Items validation messages --- .../Model/Resolver/UpdateCartItems.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php index 78a07506556c0..50d16360dd55d 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -111,6 +111,25 @@ private function processCartItems(Quote $cart, array $items): void $this->cartItemRepository->deleteById((int)$cart->getId(), $itemId); } else { $cartItem->setQty($qty); + + if ($cartItem->getHasError()) { + $errors = []; + foreach ($cartItem->getMessage(false) as $message) { + if (!in_array($message, $errors)) { + $errors[] = $message; + } + } + + if (!empty($errors)) { + throw new GraphQlInputException( + __( + 'Could not update the product with SKU %sku: %message', + ['sku' => $cartItem->getSku(), 'message' => __(implode("\n", $errors))] + ) + ); + } + } + $this->cartItemRepository->save($cartItem); } } From 43bb3211265fd71b663c00c37dd2942763fadb62 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 25 Mar 2019 17:46:35 -0500 Subject: [PATCH 081/585] Issue-230: implementing cache --- .../Controller/GraphQl/Plugin.php | 15 +++++- .../Model/App/CacheIdentifierPlugin.php | 52 +++++++++++++++++++ .../Magento/GraphQlCache/etc/graphql/di.xml | 4 ++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php index e1109da0ea9bf..582fa93e5532c 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -11,6 +11,7 @@ use Magento\Framework\App\RequestInterface; use Magento\Framework\App\ResponseInterface; use Magento\GraphQlCache\Model\CacheTags; +use Magento\Framework\App\State as AppState; class Plugin { @@ -19,12 +20,19 @@ class Plugin */ private $cacheTags; + /** + * @var AppState + */ + private $state; + /** * @param CacheTags $cacheTags + * @param AppState $state */ - public function __construct(CacheTags $cacheTags) + public function __construct(CacheTags $cacheTags, AppState $state) { $this->cacheTags = $cacheTags; + $this->state = $state; } public function afterDispatch( @@ -42,6 +50,11 @@ public function afterDispatch( $response->setHeader('Cache-Control', 'max-age=86400, public, s-maxage=86400', true); $response->setHeader('X-Magento-Tags', implode(',', $cacheTags), true); } + + if ($request->isGet() && $this->state->getMode() == AppState::MODE_DEVELOPER) { + $response->setHeader('X-Magento-Debug', 1); + } + return $response; } } diff --git a/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php b/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php new file mode 100644 index 0000000000000..e279395e43d43 --- /dev/null +++ b/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\GraphQlCache\Model\App; + +/** + * Class CachePlugin + * Should add unique identifier for graphql query + */ +class CacheIdentifierPlugin +{ + /** + * Constructor + * + * @param \Magento\Framework\App\RequestInterface $request + * @param \Magento\PageCache\Model\Config $config + */ + public function __construct( + \Magento\Framework\App\RequestInterface $request, + \Magento\PageCache\Model\Config $config + ) { + $this->request = $request; + $this->config = $config; + } + + /** + * Adds a unique key identifier for graphql specific query and variables + * + * @param \Magento\Framework\App\PageCache\Identifier $identifier + * @param string $result + * @return string + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetValue(\Magento\Framework\App\PageCache\Identifier $identifier, $result) + { + //If full page cache is enabled + if ($this->config->isEnabled()) { + //we need to compute unique query identifier from the 3 variables and removing whitespaces + $data = [ + $this->request->isSecure(), + $this->request->getUriString(), + $this->request->get(\Magento\Framework\App\Response\Http::COOKIE_VARY_STRING) + ?: $this->context->getVaryString() + ]; + $result = sha1($this->serializer->serialize($data)); + } + return $result; + } +} diff --git a/app/code/Magento/GraphQlCache/etc/graphql/di.xml b/app/code/Magento/GraphQlCache/etc/graphql/di.xml index 7dbc54fd06731..6007bdd173aa9 100644 --- a/app/code/Magento/GraphQlCache/etc/graphql/di.xml +++ b/app/code/Magento/GraphQlCache/etc/graphql/di.xml @@ -12,4 +12,8 @@ <type name="Magento\Framework\GraphQl\Query\ResolverInterface"> <plugin name="cache" type="Magento\GraphQlCache\Query\Resolver\Plugin"/> </type> + <type name="Magento\Framework\App\PageCache\Identifier"> + <plugin name="core-app-area-design-exception-plugin" + type="Magento\GraphQl\Model\App\CacheIdentifierPlugin" sortOrder="1"/> + </type> </config> From 2f936804e61b21ed305074e27418577a785de331 Mon Sep 17 00:00:00 2001 From: Yuliya Labudova <Yuliya_Labudova@epam.com> Date: Tue, 26 Mar 2019 10:19:05 +0300 Subject: [PATCH 082/585] MAGETWO-98522: Adding out of stock items to comparison shows success message but fails - Fix CR comments --- .../ViewModel/Product/Checker/AddToCompareAvailability.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php b/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php index fde621a395fbf..27829155af292 100644 --- a/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php +++ b/app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php @@ -37,8 +37,7 @@ public function __construct(StockConfigurationInterface $stockConfiguration) */ public function isAvailableForCompare(ProductInterface $product): bool { - return $this->isInStock($product) || - !$this->isInStock($product) && $this->stockConfiguration->isShowOutOfStock(); + return $this->isInStock($product) || $this->stockConfiguration->isShowOutOfStock(); } /** @@ -54,8 +53,6 @@ private function isInStock(ProductInterface $product): bool return $product->isSalable(); } - return isset($quantityAndStockStatus['is_in_stock']) - ? $quantityAndStockStatus['is_in_stock'] - : false; + return isset($quantityAndStockStatus['is_in_stock']) && $quantityAndStockStatus['is_in_stock']; } } From 8b34651f94d3bcee7dd35689441069e10a85ee2c Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Tue, 26 Mar 2019 11:53:22 +0300 Subject: [PATCH 083/585] MAGETWO-98584: Google chart API used by Magento dashboard scheduled to be turned off --- .../testsuite/Magento/Backend/Block/Dashboard/GraphTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php b/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php index 17863cd709580..215fd85d33167 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php @@ -27,6 +27,6 @@ protected function setUp() public function testGetChartUrl() { - $this->assertStringStartsWith('http://chart.apis.google.com/chart', $this->_block->getChartUrl()); + $this->assertStringStartsWith('https://image-charts.com/chart', $this->_block->getChartUrl()); } } From 04f87ecddc21a9f681903a21794cb6de5ff446e4 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Tue, 26 Mar 2019 10:57:20 +0100 Subject: [PATCH 084/585] Convert AccessAdminWithStoreCodeInUrlTest to MFTF --- .../AdminUserLoginWithStoreCodeInUrlTest.xml | 29 +++++++++++++++++ .../Test/StorefrontAddStoreCodeInUrlTest.xml | 32 +++++++++++++++++++ .../Mftf/Section/StorefrontHeaderSection.xml | 1 + .../AccessAdminWithStoreCodeInUrlTest.xml | 1 + 4 files changed, 63 insertions(+) create mode 100644 app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml create mode 100644 app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml new file mode 100644 index 0000000000000..a8f86f3309b5c --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminUserLoginWithStoreCodeInUrlTest"> + <annotations> + <features value="Backend"/> + <title value="Admin panel should be accessible with Add Store Code to URL setting enabled"/> + <description value="Admin panel should be accessible with Add Store Code to URL setting enabled"/> + <group value="backend"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <magentoCLI command="config:set web/url/use_store 1" stepKey="addStoreCodeToUrl"/> + </before> + <after> + <magentoCLI command="config:set web/url/use_store 0" stepKey="addStoreCodeToUrlDisable"/> + </after> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <see userInput="Dashboard" selector="{{AdminHeaderSection.pageTitle}}" stepKey="seeDashboardTitle"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml new file mode 100644 index 0000000000000..b04267ef83d60 --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddStoreCodeInUrlTest"> + <annotations> + <features value="Backend"/> + <title value="Store code should be added to storefront URL if the corresponding configuration is enabled"/> + <description value="Store code should be added to storefront URL if the corresponding configuration is enabled"/> + <group value="store"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <magentoCLI command="config:set web/url/use_store 1" stepKey="addStoreCodeToUrl"/> + </before> + <after> + <magentoCLI command="config:set web/url/use_store 0" stepKey="addStoreCodeToUrlDisable"/> + </after> + + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="gotToHomePage"/> + <waitForPageLoad stepKey="waitForHomePageLoaded1"/> + <click selector="{{StorefrontHeaderSection.logoLink}}" stepKey="clickOnLogo"/> + <waitForPageLoad stepKey="waitForHomePageLoaded2"/> + <seeInCurrentUrl url="{{StorefrontHomePage.url}}{{_defaultStore.code}}" stepKey="seeStoreCodeInURL"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Theme/Test/Mftf/Section/StorefrontHeaderSection.xml b/app/code/Magento/Theme/Test/Mftf/Section/StorefrontHeaderSection.xml index a4088c7a4a0b7..e2f0a01fc733b 100644 --- a/app/code/Magento/Theme/Test/Mftf/Section/StorefrontHeaderSection.xml +++ b/app/code/Magento/Theme/Test/Mftf/Section/StorefrontHeaderSection.xml @@ -9,5 +9,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontHeaderSection"> <element name="welcomeMessage" type="text" selector=".greet.welcome"/> + <element name="logoLink" type="button" selector=".header .logo"/> </section> </sections> diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/AccessAdminWithStoreCodeInUrlTest.xml b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/AccessAdminWithStoreCodeInUrlTest.xml index a4abfc5daf29e..4d3677076d303 100644 --- a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/AccessAdminWithStoreCodeInUrlTest.xml +++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/AccessAdminWithStoreCodeInUrlTest.xml @@ -11,6 +11,7 @@ <data name="configData" xsi:type="string">add_store_code_to_urls</data> <data name="user/dataset" xsi:type="string">default</data> <data name="storeCode" xsi:type="string">default</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\User\Test\Constraint\AssertUserSuccessLogin" /> <constraint name="Magento\Store\Test\Constraint\AssertStoreCodeInUrl" /> </variation> From 47233d8cd6f62ec8e233679c3fbab185de00009a Mon Sep 17 00:00:00 2001 From: RomanKis <roman.kis.y@gmail.com> Date: Tue, 26 Mar 2019 14:27:31 +0200 Subject: [PATCH 085/585] #21907 Place order button disabled after failed email address validation check with braintree credit card --- .../web/js/view/payment/method-renderer/hosted-fields.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js index 05c09abdb7b2e..9e496e43b27c5 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js @@ -10,8 +10,9 @@ define([ 'Magento_Braintree/js/view/payment/method-renderer/cc-form', 'Magento_Braintree/js/validator', 'Magento_Vault/js/view/payment/vault-enabler', - 'mage/translate' -], function ($, Component, validator, VaultEnabler, $t) { + 'mage/translate', + 'Magento_Checkout/js/model/payment/additional-validators' +], function ($, Component, validator, VaultEnabler, $t, additionalValidators) { 'use strict'; return Component.extend({ @@ -154,7 +155,7 @@ define([ * Trigger order placing */ placeOrderClick: function () { - if (this.validateCardType()) { + if (this.validateCardType() && additionalValidators.validate()) { this.isPlaceOrderActionAllowed(false); $(this.getSelector('submit')).trigger('click'); } From 99779f89e7ea86215cdabb7eb6dd7f82d1b35c29 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Tue, 26 Mar 2019 09:28:01 -0500 Subject: [PATCH 086/585] MC-4589: Convert CreateGiftCardProductEntityTest to MFTF --- ...AdminAddProductCustomOptionActionGroup.xml | 24 +++++++++++++++++++ ...AndPriceValueToCustomOptionActionGroup.xml | 18 ++++++++++++++ ...ntAssertCustomOptionByTitleActionGroup.xml | 16 +++++++++++++ ...AdminProductCustomizableOptionsSection.xml | 2 ++ .../StorefrontProductInfoMainSection.xml | 1 + 5 files changed, 61 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddProductCustomOptionActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddTitleAndPriceValueToCustomOptionActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertCustomOptionByTitleActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddProductCustomOptionActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddProductCustomOptionActionGroup.xml new file mode 100644 index 0000000000000..8e50ac6edc68e --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddProductCustomOptionActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Add custom option, title and type --> + <actionGroup name="AdminAddProductCustomOptionActionGroup"> + <arguments> + <argument name="customOptionTitle" type="string"/> + <argument name="customOptionType" type="string"/> + </arguments> + <scrollTo selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" stepKey="scrollToCustomizableOptionsSection"/> + <waitForPageLoad stepKey="waitForScrolling"/> + <click stepKey="clickAddOptions" selector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}"/> + <waitForPageLoad stepKey="waitForAddProductPageLoad"/> + <fillField stepKey="fillInOptionTitle" selector="{{AdminProductCustomizableOptionsSection.lastOptionTitle}}" userInput="{{customOptionTitle}}"/> + <click stepKey="clickOptionTypeParent" selector="{{AdminProductCustomizableOptionsSection.lastOptionTypeParent}}"/> + <waitForPageLoad stepKey="waitForDropdownOpen"/> + <click stepKey="clickOptionType" selector="{{AdminProductCustomizableOptionsSection.optionType(customOptionType)}}"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddTitleAndPriceValueToCustomOptionActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddTitleAndPriceValueToCustomOptionActionGroup.xml new file mode 100644 index 0000000000000..3a03eb60555a3 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddTitleAndPriceValueToCustomOptionActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Add value, value title and value price to custom options (type: drop-down, checkbox, multiple select, radio buttons) --> + <actionGroup name="AdminAddTitleAndPriceValueToCustomOptionActionGroup"> + <arguments> + <argument name="optionValue" type="entity"/> + </arguments> + <click stepKey="clickAddValue" selector="{{AdminProductCustomizableOptionsSection.addValue}}"/> + <fillField stepKey="fillInValueTitle" selector="{{AdminProductCustomizableOptionsSection.valueTitle}}" userInput="{{optionValue.title}}"/> + <fillField stepKey="fillInValuePrice" selector="{{AdminProductCustomizableOptionsSection.valuePrice}}" userInput="{{optionValue.price}}"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertCustomOptionByTitleActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertCustomOptionByTitleActionGroup.xml new file mode 100644 index 0000000000000..bc922a40b05b7 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertCustomOptionByTitleActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertCustomOptionByTitleActionGroup"> + <arguments> + <argument name="title" type="string"/> + </arguments> + <seeElement selector="{{StorefrontProductInfoMainSection.customOptionByTitle(title)}}" stepKey="seeCustomOption"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml index fc78c25ec49fa..9204b71e23893 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml @@ -36,6 +36,8 @@ <!-- Elements that make it easier to select the most recently added element --> <element name="lastOptionTitle" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[contains(@class, '_required')]//input" /> <element name="lastOptionTypeParent" type="block" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[contains(@class, 'admin__action-multiselect-text')]" /> + <element name="lastOptionPrice" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[contains(@name, '[price]')]"/> + <element name="lastOptionPriceType" type="select" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[contains(@name, '[price_type]')]"/> <!-- var 1 represents the option type that you want to select, i.e "radio buttons" --> <element name="optionType" type="block" selector="//*[@data-index='custom_options']//label[text()='{{var1}}'][ancestor::*[contains(@class, '_active')]]" parameterized="true" /> <element name="addValue" type="button" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[@data-action='add_new_row']" timeout="30"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index 8393cee57996f..7bad1d27d17a8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -40,6 +40,7 @@ <!-- The 1st parameter is the nth custom option, the 2nd parameter is the nth value in the option --> <element name="nthCustomOptionInput" type="radio" selector="//*[@id='product-options-wrapper']/*[@class='fieldset']/*[contains(@class, 'field')][{{customOptionNum}}]//*[contains(@class, 'admin__field-option')][{{customOptionValueNum}}]//input" parameterized="true" /> + <element name="customOptionByTitle" type="text" selector="//span[text()='{{title}}']/ancestor::div[contains(@class, 'field ') and contains(@class, 'required')]" parameterized="true" timeout="30"/> <element name="productOptionRadioButtonsCheckbox" type="checkbox" selector="//*[@id='product-options-wrapper']//div[@class='fieldset']//label[contains(.,'{{var1}}')]/../div[@class='control']//input[@price='{{var2}}']" parameterized="true"/> <element name="productOptionDataMonth" type="date" selector="//*[@id='product-options-wrapper']//div[@class='fieldset']//legend[contains(.,'{{var1}}')]/../div[@class='control']//select[@data-calendar-role='month']" parameterized="true"/> <element name="productOptionDataDay" type="date" selector="//*[@id='product-options-wrapper']//div[@class='fieldset']//legend[contains(.,'{{var1}}')]/../div[@class='control']//select[@data-calendar-role='day']" parameterized="true"/> From f8b50c499996e7299b9d0f9725ba4c2b2d4acc84 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Tue, 26 Mar 2019 11:08:33 -0500 Subject: [PATCH 087/585] MC-4330: Convert AddProductsToCartBySkuFromWidgetTest to MFTF --- .../Catalog/Test/Mftf/Data/ProductData.xml | 4 ++++ .../Test/Mftf/Data/ProductOptionData.xml | 8 +++++++ .../Test/Mftf/Data/ProductOptionValueData.xml | 7 +++++++ ...refrontCheckThatCartIsEmptyActionGroup.xml | 15 +++++++++++++ ...ckoutCheckOutOfStockProductActionGroup.xml | 19 +++++++++++++++++ ...refrontCheckoutCheckProductActionGroup.xml | 21 +++++++++++++++++++ .../Test/Mftf/Page/CheckoutCartPage.xml | 1 + .../Section/CheckoutCartMessageSection.xml | 16 ++++++++++++++ .../Section/CheckoutCartProductSection.xml | 3 +++ .../Section/StorefrontMiniCartSection.xml | 1 + .../Page/StorefrontCustomerDashboardPage.xml | 1 + .../Quote/Test/Mftf/Data/CartItemData.xml | 10 +++++++++ .../AdminCreateAndSaveWidgetActionGroup.xml | 15 +++++++++++++ .../Widget/Test/Mftf/Data/WidgetsData.xml | 11 ++++++++++ 14 files changed, 132 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckThatCartIsEmptyActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckOutOfStockProductActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckProductActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartMessageSection.xml create mode 100644 app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateAndSaveWidgetActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 1aca63b28c95d..9f621d9a41e09 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -982,4 +982,8 @@ <data key="tax_class_id">2</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> </entity> + <entity name="SimpleProductWithOption" type="product"> + <var key="sku" entityType="product" entityKey="sku" /> + <requiredEntity type="product_option">ProductOptionPercentPriceDropDown</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml index ca5024920ad40..41504e795dabc 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml @@ -121,4 +121,12 @@ <data key="price">0.00</data> <data key="price_type">percent</data> </entity> + <entity name="ProductOptionPercentPriceDropDown" type="product_option"> + <var key="product_sku" entityType="product" entityKey="sku" /> + <data key="title">OptionDropDown</data> + <data key="type">drop_down</data> + <data key="sort_order">4</data> + <data key="is_require">true</data> + <requiredEntity type="product_option_value">ProductOptionPercentPriceValueDropdown</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml index d16a201cd9ecc..5323314605e6a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml @@ -62,4 +62,11 @@ <data key="price">20</data> <data key="price_type">percent</data> </entity> + <entity name="ProductOptionPercentPriceValueDropdown" type="product_option_value"> + <data key="title">40 Percent</data> + <data key="sort_order">0</data> + <data key="price">40</data> + <data key="price_type">percent</data> + <data key="sku">sku_drop_down_row_1</data> + </entity> </entities> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckThatCartIsEmptyActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckThatCartIsEmptyActionGroup.xml new file mode 100644 index 0000000000000..e5fbb9065f976 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckThatCartIsEmptyActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontCheckThatCartIsEmptyActionGroup"> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <see selector="{{StorefrontMinicartSection.messageEmptyCart}}" userInput="You have no items in your shopping cart." stepKey="seeNoItemsInShoppingCart"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckOutOfStockProductActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckOutOfStockProductActionGroup.xml new file mode 100644 index 0000000000000..5fad9f12ca572 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckOutOfStockProductActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontCheckoutCheckOutOfStockProductActionGroup"> + <arguments> + <argument name="product"/> + </arguments> + <see selector="{{CheckoutCartMessageSection.errorMessage}}" userInput="1 product requires your attention." stepKey="seeErrorMessage"/> + <see selector="{{CheckoutCartProductSection.productName}}" userInput="{{product.name}}" stepKey="seeProductName"/> + <see selector="{{CheckoutCartProductSection.messageErrorItem}}" userInput="Availability: Out of stock" stepKey="seeProductOutOfStock"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckProductActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckProductActionGroup.xml new file mode 100644 index 0000000000000..a994611869274 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckProductActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontCheckoutCheckProductActionGroup"> + <arguments> + <argument name="product" type="entity"/> + <argument name="cartItem" type="entity"/> + </arguments> + + <see selector="{{CheckoutCartProductSection.productName}}" userInput="{{product.name}}" stepKey="seeProductName"/> + <grabValueFrom selector="{{CheckoutCartProductSection.ProductQuantityByName(product.name)}}" stepKey="grabProductQty"/> + <assertEquals expected="{{cartItem.qty}}" actual="$grabProductQty" stepKey="assertQtyShoppingCart"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Page/CheckoutCartPage.xml b/app/code/Magento/Checkout/Test/Mftf/Page/CheckoutCartPage.xml index bf17800f29ad1..a77b07a129dce 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Page/CheckoutCartPage.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Page/CheckoutCartPage.xml @@ -12,5 +12,6 @@ <section name="CheckoutCartProductSection"/> <section name="CheckoutCartSummarySection"/> <section name="CheckoutCartCrossSellSection"/> + <section name="CheckoutCartMessageSection"/> </page> </pages> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartMessageSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartMessageSection.xml new file mode 100644 index 0000000000000..cf15cdf15cf15 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartMessageSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="CheckoutCartMessageSection"> + <element name="successMessage" type="text" selector=".message.message-success.success>div" /> + <element name="errorMessage" type="text" selector=".message-error.error.message>div" /> + <element name="emptyCartMessage" type="text" selector=".cart-empty>p"/> + </section> +</sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml index dcfb12fd4e965..18393da6738ca 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml @@ -33,5 +33,8 @@ <element name="productSubtotalByName" type="input" selector="//main//table[@id='shopping-cart-table']//tbody//tr[..//strong[contains(@class, 'product-item-name')]//a/text()='{{var1}}'][1]//td[contains(@class, 'subtotal')]//span[@class='price']" parameterized="true"/> <element name="updateShoppingCartButton" type="button" selector="#form-validate button[type='submit'].update" timeout="30"/> <element name="qty" type="input" selector="//input[@data-cart-item-id='{{var}}'][@title='Qty']" parameterized="true"/> + <element name="messageErrorItem" type="text" selector="//*[@id='sku-stock-failed-']"/> + <element name="messageErrorNeedChooseOptions" type="text" selector="//*[contains(@class, 'error')]/div"/> + <element name="productOptionsLink" type="text" selector="a.action.configure"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml index 38c88bf4f80bb..04ed03f8cb6e3 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml @@ -33,5 +33,6 @@ <element name="subtotal" type="text" selector="//tr[@class='totals sub']//td[@class='amount']/span"/> <element name="emptyCart" type="text" selector=".counter.qty.empty"/> <element name="minicartContent" type="block" selector="#minicart-content-wrapper"/> + <element name="messageEmptyCart" type="text" selector="//*[@id='minicart-content-wrapper']//*[contains(@class,'subtitle empty')]"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDashboardPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDashboardPage.xml index eaca1c820e49e..d4fe9106fbbad 100644 --- a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDashboardPage.xml +++ b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDashboardPage.xml @@ -11,5 +11,6 @@ <page name="StorefrontCustomerDashboardPage" url="/customer/account/" area="storefront" module="Magento_Customer"> <section name="StorefrontCustomerDashboardAccountInformationSection" /> <section name="StorefrontCustomerSidebarSection"/> + <section name="StorefrontMinicartSection"/> </page> </pages> diff --git a/app/code/Magento/Quote/Test/Mftf/Data/CartItemData.xml b/app/code/Magento/Quote/Test/Mftf/Data/CartItemData.xml index 4cc2c4f392419..a513b6747f612 100644 --- a/app/code/Magento/Quote/Test/Mftf/Data/CartItemData.xml +++ b/app/code/Magento/Quote/Test/Mftf/Data/CartItemData.xml @@ -13,4 +13,14 @@ <var key="quote_id" entityKey="return" entityType="GuestCart"/> <var key="sku" entityKey="sku" entityType="product"/> </entity> + <entity name="SimpleTwoCartItems" type="CartItem"> + <data key="qty">2</data> + <var key="quote_id" entityKey="return" entityType="GuestCart"/> + <var key="sku" entityKey="sku" entityType="product"/> + </entity> + <entity name="NotValidCartItems" type="CartItem"> + <data key="qty">abc</data> + <var key="quote_id" entityKey="return" entityType="GuestCart"/> + <var key="sku" entityKey="sku" entityType="product"/> + </entity> </entities> diff --git a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateAndSaveWidgetActionGroup.xml b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateAndSaveWidgetActionGroup.xml new file mode 100644 index 0000000000000..2f144894111bc --- /dev/null +++ b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateAndSaveWidgetActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateAndSaveWidgetActionGroup" extends="AdminCreateWidgetActionGroup"> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml index 27222298408de..ffd2d025548cf 100644 --- a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml +++ b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml @@ -32,4 +32,15 @@ <data key="display_mode">Cart Price Rule Related</data> <data key="restrict_type">Header</data> </entity> + <entity name="DefaultOrderBySKUWidget" type="widget"> + <data key="type">Order by SKU</data> + <data key="design_theme">Magento Luma</data> + <data key="name" unique="suffix">Test Widget</data> + <array key="store_ids"> + <item>All Store Views</item> + </array> + <data key="sort_order">0</data> + <data key="display_on">All Pages</data> + <data key="container">Sidebar Main</data> + </entity> </entities> From ca2ba261576ac2729b8220267d77bafac6864a01 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 26 Mar 2019 15:41:44 -0500 Subject: [PATCH 088/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- app/code/Magento/Authorization/Model/Role.php | 14 +- .../Magento/Backend/Model/Auth/Session.php | 197 ++++++++++++- .../Backend/Model/Auth/SessionAclHydrator.php | 36 +++ .../Model/Auth/SessionUserHydrator.php | 54 ++++ .../Spi/SessionAclHydratorInterface.php | 34 +++ .../Spi/SessionUserHydratorInterface.php | 34 +++ .../Test/Unit/Model/Auth/SessionTest.php | 273 ------------------ .../Model/Authorization/RoleLocatorTest.php | 36 --- .../Test/Unit/Model/Locale/ManagerTest.php | 127 -------- app/code/Magento/Backend/composer.json | 1 + app/code/Magento/Backend/etc/di.xml | 4 + .../Model/ResourceModel/Eav/Attribute.php | 10 + .../Config/Model/Config/Backend/Encrypted.php | 12 + .../Product/Type/Configurable/Attribute.php | 49 ++-- .../Configurable/Attribute/Collection.php | 14 + app/code/Magento/Customer/Model/Attribute.php | 10 + .../Magento/Eav/Model/Entity/Attribute.php | 14 +- .../Entity/Attribute/AbstractAttribute.php | 10 + .../Model/ResourceModel/Entity/Attribute.php | 10 + .../System/Config/Fieldset/GroupTest.php | 107 ------- .../Condition/CanViewNotificationTest.php | 16 +- app/code/Magento/Store/Model/Store.php | 10 + app/code/Magento/User/Model/User.php | 14 + .../AdminSessionUserContextTest.php | 89 ------ .../Magento/User/Test/Unit/Model/UserTest.php | 25 -- .../Backend/Model/Auth/SessionTest.php | 39 ++- .../Backend/Model/Locale/ResolverTest.php | 15 +- .../Spi/SessionAclHydratorInterfaceTest.php | 55 ++++ .../Spi/SessionUserHydratorInterfaceTest.php | 58 ++++ .../Rule/Design/SerializationAware.php | 34 +++ .../resources/rulesets/design.xml | 25 ++ .../Magento/Test/Php/_files/phpmd/ruleset.xml | 1 + .../Magento/Framework/App/AreaList/Proxy.php | 18 +- .../Magento/Framework/App/Response/Http.php | 23 +- .../App/Route/ConfigInterface/Proxy.php | 12 + .../App/Test/Unit/Response/HttpTest.php | 39 --- lib/internal/Magento/Framework/DB/Select.php | 22 +- .../Framework/DB/Select/RendererProxy.php | 14 +- .../Magento/Framework/Data/Collection.php | 10 + .../Framework/Data/Collection/AbstractDb.php | 10 + .../DataObject/Copy/Config/Data/Proxy.php | 18 +- .../Framework/Interception/Interceptor.php | 10 + .../Model/AbstractExtensibleModel.php | 18 +- .../Magento/Framework/Model/AbstractModel.php | 10 + .../Model/ResourceModel/Db/AbstractDb.php | 23 +- .../Db/Collection/AbstractCollection.php | 10 + .../Framework/Mview/Config/Data/Proxy.php | 16 +- .../Framework/Translate/Inline/Proxy.php | 12 + .../Magento/Framework/View/Layout/Proxy.php | 128 ++++---- 49 files changed, 994 insertions(+), 826 deletions(-) create mode 100644 app/code/Magento/Backend/Model/Auth/SessionAclHydrator.php create mode 100644 app/code/Magento/Backend/Model/Auth/SessionUserHydrator.php create mode 100644 app/code/Magento/Backend/Spi/SessionAclHydratorInterface.php create mode 100644 app/code/Magento/Backend/Spi/SessionUserHydratorInterface.php delete mode 100644 app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php delete mode 100644 app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php delete mode 100644 app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php delete mode 100644 app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php delete mode 100644 app/code/Magento/User/Test/Unit/Model/Authorization/AdminSessionUserContextTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Backend/Spi/SessionUserHydratorInterfaceTest.php create mode 100644 dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/SerializationAware.php diff --git a/app/code/Magento/Authorization/Model/Role.php b/app/code/Magento/Authorization/Model/Role.php index 2546df86d09dd..dcc46ee77ee12 100644 --- a/app/code/Magento/Authorization/Model/Role.php +++ b/app/code/Magento/Authorization/Model/Role.php @@ -51,19 +51,29 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritDoc + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $properties = parent::__sleep(); return array_diff($properties, ['_resource', '_resourceCollection']); } /** - * {@inheritdoc} + * @inheritDoc + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_resource = $objectManager->get(\Magento\Authorization\Model\ResourceModel\Role::class); diff --git a/app/code/Magento/Backend/Model/Auth/Session.php b/app/code/Magento/Backend/Model/Auth/Session.php index 593b4219d45f0..01f762de83de8 100644 --- a/app/code/Magento/Backend/Model/Auth/Session.php +++ b/app/code/Magento/Backend/Model/Auth/Session.php @@ -5,17 +5,20 @@ */ namespace Magento\Backend\Model\Auth; +use Magento\Framework\Acl; +use Magento\Framework\AclFactory; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory; use Magento\Framework\Stdlib\CookieManagerInterface; +use Magento\Backend\Spi\SessionUserHydratorInterface; +use Magento\Backend\Spi\SessionAclHydratorInterface; +use Magento\User\Model\User; +use Magento\User\Model\UserFactory; /** * Backend Auth session model * * @api - * @method \Magento\User\Model\User|null getUser() - * @method \Magento\Backend\Model\Auth\Session setUser(\Magento\User\Model\User $value) - * @method \Magento\Framework\Acl|null getAcl() - * @method \Magento\Backend\Model\Auth\Session setAcl(\Magento\Framework\Acl $value) * @method int getUpdatedAt() * @method \Magento\Backend\Model\Auth\Session setUpdatedAt(int $value) * @@ -55,6 +58,36 @@ class Session extends \Magento\Framework\Session\SessionManager implements \Mage */ protected $_config; + /** + * @var SessionUserHydratorInterface + */ + private $userHydrator; + + /** + * @var SessionAclHydratorInterface + */ + private $aclHydrator; + + /** + * @var UserFactory + */ + private $userFactory; + + /** + * @var AclFactory + */ + private $aclFactory; + + /** + * @var User|null + */ + private $user; + + /** + * @var Acl|null + */ + private $acl; + /** * @param \Magento\Framework\App\Request\Http $request * @param \Magento\Framework\Session\SidResolverInterface $sidResolver @@ -69,6 +102,10 @@ class Session extends \Magento\Framework\Session\SessionManager implements \Mage * @param \Magento\Backend\Model\UrlInterface $backendUrl * @param \Magento\Backend\App\ConfigInterface $config * @throws \Magento\Framework\Exception\SessionException + * @param SessionUserHydratorInterface|null $userHydrator + * @param SessionAclHydratorInterface|null $aclHydrator + * @param UserFactory|null $userFactory + * @param AclFactory|null $aclFactory * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -83,11 +120,19 @@ public function __construct( \Magento\Framework\App\State $appState, \Magento\Framework\Acl\Builder $aclBuilder, \Magento\Backend\Model\UrlInterface $backendUrl, - \Magento\Backend\App\ConfigInterface $config + \Magento\Backend\App\ConfigInterface $config, + ?SessionUserHydratorInterface $userHydrator = null, + ?SessionAclHydratorInterface $aclHydrator = null, + ?UserFactory $userFactory = null, + ?AclFactory $aclFactory = null ) { $this->_config = $config; $this->_aclBuilder = $aclBuilder; $this->_backendUrl = $backendUrl; + $this->userHydrator = $userHydrator ?? ObjectManager::getInstance()->get(SessionUserHydratorInterface::class); + $this->aclHydrator = $aclHydrator ?? ObjectManager::getInstance()->get(SessionAclHydratorInterface::class); + $this->userFactory = $userFactory ?? ObjectManager::getInstance()->get(UserFactory::class); + $this->aclFactory = $aclFactory ?? ObjectManager::getInstance()->get(AclFactory::class); parent::__construct( $request, $sidResolver, @@ -230,6 +275,16 @@ public function processLogin() return $this; } + /** + * @inheritDoc + */ + public function destroy(array $options = null) + { + $this->user = null; + $this->acl = null; + parent::destroy($options); + } + /** * Process of configuring of current auth storage when logout was performed * @@ -253,4 +308,136 @@ public function isValidForPath($path) { return true; } + + /** + * Logged-in user. + * + * @return User|null + */ + public function getUser(): ?User + { + if (!$this->user) { + $userData = $this->getUserData(); + if ($userData) { + /** @var User $user */ + $user = $this->userFactory->create(); + $this->userHydrator->hydrate($user, $userData); + $this->user = $user; + } + } + + return $this->user; + } + + /** + * Set logged-in user instance. + * + * @param User|null $user + * @return Session + */ + public function setUser(?User $user): self + { + $this->setUserData(null); + if ($user) { + $this->setUserData($this->userHydrator->extract($user)); + } + $this->user = $user; + + return $this; + } + + /** + * Is user logged in? + * + * @return bool + */ + public function hasUser(): bool + { + return $this->user || $this->hasUserData(); + } + + /** + * Remove logged-in user. + * + * @return Session + */ + public function unsUser(): self + { + $this->user = null; + $this->unsUserData(); + } + + /** + * Logged-in user's ACL data. + * + * @return Acl|null + */ + public function getAcl(): ?Acl + { + if (!$this->acl) { + $aclData = $this->getUserAclData(); + if ($aclData) { + /** @var Acl $acl */ + $acl = $this->aclFactory->create(); + $this->aclHydrator->hydrate($acl, $aclData); + $this->acl = $acl; + } + } + + return $this->acl; + } + + /** + * Set logged-in user's ACL data instance. + * + * @param Acl|null $acl + * @return Session + */ + public function setAcl(?Acl $acl): self + { + $this->setUserAclData(null); + if ($acl) { + $this->setUserAclData($this->aclHydrator->extract($acl)); + } + $this->acl = $acl; + + return $this; + } + + /** + * Whether ACL data is present. + * + * @return bool + */ + public function hasAcl(): bool + { + return $this->acl || $this->hasUserAclData(); + } + + /** + * Remove ACL data. + * + * @return Session + */ + public function unsAcl(): self + { + $this->acl = null; + $this->unsUserAclData(); + } + + /** + * @inheritDoc + */ + public function writeClose() + { + //Updating data in session in case these objects has been changed. + if ($this->user) { + $this->setUser($this->user); + } + if ($this->acl) { + $this->setAcl($this->acl); + } + + parent::writeClose(); + } } diff --git a/app/code/Magento/Backend/Model/Auth/SessionAclHydrator.php b/app/code/Magento/Backend/Model/Auth/SessionAclHydrator.php new file mode 100644 index 0000000000000..34e01be696672 --- /dev/null +++ b/app/code/Magento/Backend/Model/Auth/SessionAclHydrator.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Backend\Model\Auth; + +use Magento\Backend\Spi\SessionAclHydratorInterface; +use Magento\Framework\Acl; + +/** + * @inheritDoc + */ +class SessionAclHydrator extends Acl implements SessionAclHydratorInterface +{ + /** + * @inheritDoc + */ + public function extract(Acl $acl): array + { + return ['rules' => $acl->_rules, 'resources' => $acl->_resources, 'roles' => $acl->_roleRegistry]; + } + + /** + * @inheritDoc + */ + public function hydrate(Acl $target, array $data): void + { + $target->_rules = $data['rules']; + $target->_resources = $data['resources']; + $target->_roleRegistry = $data['roles']; + } +} diff --git a/app/code/Magento/Backend/Model/Auth/SessionUserHydrator.php b/app/code/Magento/Backend/Model/Auth/SessionUserHydrator.php new file mode 100644 index 0000000000000..6dee8b7b302c8 --- /dev/null +++ b/app/code/Magento/Backend/Model/Auth/SessionUserHydrator.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Backend\Model\Auth; + +use Magento\Backend\Spi\SessionUserHydratorInterface; +use Magento\User\Model\User; +use Magento\Authorization\Model\Role; +use Magento\Authorization\Model\RoleFactory; + +/** + * @inheritDoc + */ +class SessionUserHydrator implements SessionUserHydratorInterface +{ + /** + * @var RoleFactory + */ + private $roleFactory; + + /** + * @param RoleFactory $roleFactory + */ + public function __construct(RoleFactory $roleFactory) + { + $this->roleFactory = $roleFactory; + } + + /** + * @inheritDoc + */ + public function extract(User $user): array + { + return ['data' => $user->getData(), 'role_data' => $user->getRole()->getData()]; + } + + /** + * @inheritDoc + */ + public function hydrate(User $target, array $data): void + { + $target->setData($data['data']); + /** @var Role $role */ + $role = $this->roleFactory->create(); + $role->setData($data['role_data']); + $target->setData('extracted_role', $role); + $target->getRole(); + } +} diff --git a/app/code/Magento/Backend/Spi/SessionAclHydratorInterface.php b/app/code/Magento/Backend/Spi/SessionAclHydratorInterface.php new file mode 100644 index 0000000000000..7227cc92fcc8e --- /dev/null +++ b/app/code/Magento/Backend/Spi/SessionAclHydratorInterface.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Backend\Spi; + +use Magento\Framework\Acl; + +/** + * Extract/hydrate user's ACL data to/from session. + */ +interface SessionAclHydratorInterface +{ + /** + * Extract ACL data to store in session. + * + * @param Acl $acl + * @return array Array of scalars. + */ + public function extract(Acl $acl): array; + + /** + * Fill ACL object with data from session. + * + * @param Acl $target + * @param array $data Data from session. + * @return void + */ + public function hydrate(Acl $target, array $data): void; +} diff --git a/app/code/Magento/Backend/Spi/SessionUserHydratorInterface.php b/app/code/Magento/Backend/Spi/SessionUserHydratorInterface.php new file mode 100644 index 0000000000000..211c7b01df3be --- /dev/null +++ b/app/code/Magento/Backend/Spi/SessionUserHydratorInterface.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Backend\Spi; + +use Magento\User\Model\User; + +/** + * Extract/hydrate user data to/from session. + */ +interface SessionUserHydratorInterface +{ + /** + * Extract user data to store in session. + * + * @param User $user + * @return array Array of scalars. + */ + public function extract(User $user): array; + + /** + * Fill User object with data from session. + * + * @param User $target + * @param array $data Data from session. + * @return void + */ + public function hydrate(User $target, array $data): void; +} diff --git a/app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php b/app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php deleted file mode 100644 index f1a4bc355b08e..0000000000000 --- a/app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php +++ /dev/null @@ -1,273 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Backend\Test\Unit\Model\Auth; - -use Magento\Backend\Model\Auth\Session; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; - -/** - * Class SessionTest tests Magento\Backend\Model\Auth\Session - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class SessionTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Backend\App\Config | \PHPUnit_Framework_MockObject_MockObject - */ - protected $config; - - /** - * @var \Magento\Framework\Session\Config | \PHPUnit_Framework_MockObject_MockObject - */ - protected $sessionConfig; - - /** - * @var \Magento\Framework\Stdlib\CookieManagerInterface | \PHPUnit_Framework_MockObject_MockObject - */ - protected $cookieManager; - - /** - * @var \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory | \PHPUnit_Framework_MockObject_MockObject - */ - protected $cookieMetadataFactory; - - /** - * @var \Magento\Framework\Session\Storage | \PHPUnit_Framework_MockObject_MockObject - */ - protected $storage; - - /** - * @var \Magento\Framework\Acl\Builder | \PHPUnit_Framework_MockObject_MockObject - */ - protected $aclBuilder; - - /** - * @var Session - */ - protected $session; - - protected function setUp() - { - $this->cookieMetadataFactory = $this->createPartialMock( - \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory::class, - ['createPublicCookieMetadata'] - ); - - $this->config = $this->createPartialMock(\Magento\Backend\App\Config::class, ['getValue']); - $this->cookieManager = $this->createPartialMock( - \Magento\Framework\Stdlib\Cookie\PhpCookieManager::class, - ['getCookie', 'setPublicCookie'] - ); - $this->storage = $this->createPartialMock( - \Magento\Framework\Session\Storage::class, - ['getUser', 'getAcl', 'setAcl'] - ); - $this->sessionConfig = $this->createPartialMock( - \Magento\Framework\Session\Config::class, - ['getCookiePath', 'getCookieDomain', 'getCookieSecure', 'getCookieHttpOnly'] - ); - $this->aclBuilder = $this->getMockBuilder(\Magento\Framework\Acl\Builder::class) - ->disableOriginalConstructor() - ->getMock(); - $objectManager = new ObjectManager($this); - $this->session = $objectManager->getObject( - \Magento\Backend\Model\Auth\Session::class, - [ - 'config' => $this->config, - 'sessionConfig' => $this->sessionConfig, - 'cookieManager' => $this->cookieManager, - 'cookieMetadataFactory' => $this->cookieMetadataFactory, - 'storage' => $this->storage, - 'aclBuilder' => $this->aclBuilder - ] - ); - } - - protected function tearDown() - { - $this->config = null; - $this->sessionConfig = null; - $this->session = null; - } - - /** - * @dataProvider refreshAclDataProvider - * @param $isUserPassedViaParams - */ - public function testRefreshAcl($isUserPassedViaParams) - { - $aclMock = $this->getMockBuilder(\Magento\Framework\Acl::class)->disableOriginalConstructor()->getMock(); - $this->aclBuilder->expects($this->any())->method('getAcl')->willReturn($aclMock); - $userMock = $this->getMockBuilder(\Magento\User\Model\User::class) - ->setMethods(['getReloadAclFlag', 'setReloadAclFlag', 'unsetData', 'save']) - ->disableOriginalConstructor() - ->getMock(); - $userMock->expects($this->any())->method('getReloadAclFlag')->willReturn(true); - $userMock->expects($this->once())->method('setReloadAclFlag')->with('0')->willReturnSelf(); - $userMock->expects($this->once())->method('save'); - $this->storage->expects($this->once())->method('setAcl')->with($aclMock); - $this->storage->expects($this->any())->method('getAcl')->willReturn($aclMock); - if ($isUserPassedViaParams) { - $this->session->refreshAcl($userMock); - } else { - $this->storage->expects($this->once())->method('getUser')->willReturn($userMock); - $this->session->refreshAcl(); - } - $this->assertSame($aclMock, $this->session->getAcl()); - } - - /** - * @return array - */ - public function refreshAclDataProvider() - { - return [ - 'User set via params' => [true], - 'User set to session object' => [false] - ]; - } - - public function testIsLoggedInPositive() - { - $user = $this->createPartialMock(\Magento\User\Model\User::class, ['getId', '__wakeup']); - $user->expects($this->once()) - ->method('getId') - ->will($this->returnValue(1)); - - $this->storage->expects($this->any()) - ->method('getUser') - ->will($this->returnValue($user)); - - $this->assertTrue($this->session->isLoggedIn()); - } - - public function testProlong() - { - $name = session_name(); - $cookie = 'cookie'; - $lifetime = 900; - $path = '/'; - $domain = 'magento2'; - $secure = true; - $httpOnly = true; - - $this->config->expects($this->once()) - ->method('getValue') - ->with(\Magento\Backend\Model\Auth\Session::XML_PATH_SESSION_LIFETIME) - ->willReturn($lifetime); - $cookieMetadata = $this->createMock(\Magento\Framework\Stdlib\Cookie\PublicCookieMetadata::class); - $cookieMetadata->expects($this->once()) - ->method('setDuration') - ->with($lifetime) - ->will($this->returnSelf()); - $cookieMetadata->expects($this->once()) - ->method('setPath') - ->with($path) - ->will($this->returnSelf()); - $cookieMetadata->expects($this->once()) - ->method('setDomain') - ->with($domain) - ->will($this->returnSelf()); - $cookieMetadata->expects($this->once()) - ->method('setSecure') - ->with($secure) - ->will($this->returnSelf()); - $cookieMetadata->expects($this->once()) - ->method('setHttpOnly') - ->with($httpOnly) - ->will($this->returnSelf()); - - $this->cookieMetadataFactory->expects($this->once()) - ->method('createPublicCookieMetadata') - ->will($this->returnValue($cookieMetadata)); - - $this->cookieManager->expects($this->once()) - ->method('getCookie') - ->with($name) - ->will($this->returnValue($cookie)); - $this->cookieManager->expects($this->once()) - ->method('setPublicCookie') - ->with($name, $cookie, $cookieMetadata); - - $this->sessionConfig->expects($this->once()) - ->method('getCookiePath') - ->will($this->returnValue($path)); - $this->sessionConfig->expects($this->once()) - ->method('getCookieDomain') - ->will($this->returnValue($domain)); - $this->sessionConfig->expects($this->once()) - ->method('getCookieSecure') - ->will($this->returnValue($secure)); - $this->sessionConfig->expects($this->once()) - ->method('getCookieHttpOnly') - ->will($this->returnValue($httpOnly)); - - $this->session->prolong(); - - $this->assertLessThanOrEqual(time(), $this->session->getUpdatedAt()); - } - - /** - * @dataProvider isAllowedDataProvider - * @param bool $isUserDefined - * @param bool $isAclDefined - * @param bool $isAllowed - * @param true $expectedResult - */ - public function testIsAllowed($isUserDefined, $isAclDefined, $isAllowed, $expectedResult) - { - $userAclRole = 'userAclRole'; - if ($isAclDefined) { - $aclMock = $this->getMockBuilder(\Magento\Framework\Acl::class)->disableOriginalConstructor()->getMock(); - $this->storage->expects($this->any())->method('getAcl')->willReturn($aclMock); - } - if ($isUserDefined) { - $userMock = $this->getMockBuilder(\Magento\User\Model\User::class)->disableOriginalConstructor()->getMock(); - $this->storage->expects($this->once())->method('getUser')->willReturn($userMock); - } - if ($isAclDefined && $isUserDefined) { - $userMock->expects($this->any())->method('getAclRole')->willReturn($userAclRole); - $aclMock->expects($this->once())->method('isAllowed')->with($userAclRole)->willReturn($isAllowed); - } - - $this->assertEquals($expectedResult, $this->session->isAllowed('resource')); - } - - /** - * @return array - */ - public function isAllowedDataProvider() - { - return [ - "Negative: User not defined" => [false, true, true, false], - "Negative: Acl not defined" => [true, false, true, false], - "Negative: Permission denied" => [true, true, false, false], - "Positive: Permission granted" => [true, true, false, false], - ]; - } - - /** - * @dataProvider firstPageAfterLoginDataProvider - * @param bool $isFirstPageAfterLogin - */ - public function testFirstPageAfterLogin($isFirstPageAfterLogin) - { - $this->session->setIsFirstPageAfterLogin($isFirstPageAfterLogin); - $this->assertEquals($isFirstPageAfterLogin, $this->session->isFirstPageAfterLogin()); - } - - /** - * @return array - */ - public function firstPageAfterLoginDataProvider() - { - return [ - 'First page after login' => [true], - 'Not first page after login' => [false], - ]; - } -} diff --git a/app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php b/app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php deleted file mode 100644 index 5b3910e9445f8..0000000000000 --- a/app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Backend\Test\Unit\Model\Authorization; - -class RoleLocatorTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Backend\Model\Authorization\RoleLocator - */ - protected $_model; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_sessionMock = []; - - protected function setUp() - { - $this->_sessionMock = $this->createPartialMock( - \Magento\Backend\Model\Auth\Session::class, - ['getUser', 'getAclRole', 'hasUser'] - ); - $this->_model = new \Magento\Backend\Model\Authorization\RoleLocator($this->_sessionMock); - } - - public function testGetAclRoleIdReturnsCurrentUserAclRoleId() - { - $this->_sessionMock->expects($this->once())->method('hasUser')->will($this->returnValue(true)); - $this->_sessionMock->expects($this->once())->method('getUser')->will($this->returnSelf()); - $this->_sessionMock->expects($this->once())->method('getAclRole')->will($this->returnValue('some_role')); - $this->assertEquals('some_role', $this->_model->getAclRoleId()); - } -} diff --git a/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php b/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php deleted file mode 100644 index 77eb7cdb34d1f..0000000000000 --- a/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Backend\Test\Unit\Model\Locale; - -use Magento\Framework\Locale\Resolver; - -class ManagerTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Backend\Model\Locale\Manager - */ - protected $_model; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\TranslateInterface - */ - protected $_translator; - - /** - * @var \Magento\Backend\Model\Session - */ - protected $_session; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Backend\Model\Auth\Session - */ - protected $_authSession; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Backend\App\ConfigInterface - */ - protected $_backendConfig; - - protected function setUp() - { - $this->_session = $this->createMock(\Magento\Backend\Model\Session::class); - - $this->_authSession = $this->createPartialMock(\Magento\Backend\Model\Auth\Session::class, ['getUser']); - - $this->_backendConfig = $this->getMockForAbstractClass( - \Magento\Backend\App\ConfigInterface::class, - [], - '', - false - ); - - $userMock = new \Magento\Framework\DataObject(); - - $this->_authSession->expects($this->any())->method('getUser')->will($this->returnValue($userMock)); - - $this->_translator = $this->getMockBuilder(\Magento\Framework\TranslateInterface::class) - ->setMethods(['init', 'setLocale']) - ->getMockForAbstractClass(); - - $this->_translator->expects($this->any())->method('setLocale')->will($this->returnValue($this->_translator)); - - $this->_translator->expects($this->any())->method('init')->will($this->returnValue(false)); - - $this->_model = new \Magento\Backend\Model\Locale\Manager( - $this->_session, - $this->_authSession, - $this->_translator, - $this->_backendConfig - ); - } - - /** - * @return array - */ - public function switchBackendInterfaceLocaleDataProvider() - { - return ['case1' => ['locale' => 'de_DE'], 'case2' => ['locale' => 'en_US']]; - } - - /** - * @param string $locale - * @dataProvider switchBackendInterfaceLocaleDataProvider - * @covers \Magento\Backend\Model\Locale\Manager::switchBackendInterfaceLocale - */ - public function testSwitchBackendInterfaceLocale($locale) - { - $this->_model->switchBackendInterfaceLocale($locale); - - $userInterfaceLocale = $this->_authSession->getUser()->getInterfaceLocale(); - $this->assertEquals($userInterfaceLocale, $locale); - - $sessionLocale = $this->_session->getSessionLocale(); - $this->assertEquals($sessionLocale, null); - } - - /** - * @covers \Magento\Backend\Model\Locale\Manager::getUserInterfaceLocale - */ - public function testGetUserInterfaceLocaleDefault() - { - $locale = $this->_model->getUserInterfaceLocale(); - - $this->assertEquals($locale, Resolver::DEFAULT_LOCALE); - } - - /** - * @covers \Magento\Backend\Model\Locale\Manager::getUserInterfaceLocale - */ - public function testGetUserInterfaceLocale() - { - $this->_model->switchBackendInterfaceLocale('de_DE'); - $locale = $this->_model->getUserInterfaceLocale(); - - $this->assertEquals($locale, 'de_DE'); - } - - /** - * @covers \Magento\Backend\Model\Locale\Manager::getUserInterfaceLocale - */ - public function testGetUserInterfaceGeneralLocale() - { - $this->_backendConfig->expects($this->any()) - ->method('getValue') - ->with('general/locale/code') - ->willReturn('test_locale'); - $locale = $this->_model->getUserInterfaceLocale(); - $this->assertEquals($locale, 'test_locale'); - } -} diff --git a/app/code/Magento/Backend/composer.json b/app/code/Magento/Backend/composer.json index f9408768136bb..e54bd136b3494 100644 --- a/app/code/Magento/Backend/composer.json +++ b/app/code/Magento/Backend/composer.json @@ -22,6 +22,7 @@ "magento/module-store": "*", "magento/module-translation": "*", "magento/module-ui": "*", + "magento/module-authorization": "*", "magento/module-user": "*" }, "suggest": { diff --git a/app/code/Magento/Backend/etc/di.xml b/app/code/Magento/Backend/etc/di.xml index c526703da9975..41db85b9323a8 100644 --- a/app/code/Magento/Backend/etc/di.xml +++ b/app/code/Magento/Backend/etc/di.xml @@ -198,4 +198,8 @@ <argument name="anchorRenderer" xsi:type="object">Magento\Backend\Block\AnchorRenderer</argument> </arguments> </type> + <preference for="Magento\Backend\Spi\SessionUserHydratorInterface" + type="Magento\Backend\Model\Auth\SessionUserHydrator" /> + <preference for="Magento\Backend\Spi\SessionAclHydratorInterface" + type="Magento\Backend\Model\Auth\SessionAclHydrator" /> </config> diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index 23f612582f42e..d56cc40ad0fc2 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -845,9 +845,14 @@ public function afterDelete() /** * @inheritdoc * @since 100.0.9 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->unsetData('entity_type'); return array_diff( parent::__sleep(), @@ -858,9 +863,14 @@ public function __sleep() /** * @inheritdoc * @since 100.0.9 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_indexerEavProcessor = $objectManager->get(\Magento\Catalog\Model\Indexer\Product\Flat\Processor::class); diff --git a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php index 1a91e403a679d..ea3b1d4c74a5f 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php +++ b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php @@ -9,6 +9,8 @@ namespace Magento\Config\Model\Config\Backend; /** + * Backend model for encrypted values. + * * @api * @since 100.0.2 */ @@ -48,9 +50,14 @@ public function __construct( * Magic method called during class serialization * * @return string[] + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $properties = parent::__sleep(); return array_diff($properties, ['_encryptor']); } @@ -59,9 +66,14 @@ public function __sleep() * Magic method called during class un-serialization * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $this->_encryptor = \Magento\Framework\App\ObjectManager::getInstance()->get( \Magento\Framework\Encryption\EncryptorInterface::class diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php index 7306942c3c49b..4ead9ffe0fe70 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php @@ -12,6 +12,8 @@ use Magento\Framework\EntityManager\MetadataPool; /** + * Configurable product attribute model. + * * @method Attribute setProductAttribute(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute $value) * @method \Magento\Eav\Model\Entity\Attribute\AbstractAttribute getProductAttribute() */ @@ -86,7 +88,7 @@ public function getOptions() } /** - * {@inheritdoc} + * @inheritdoc */ public function getLabel() { @@ -112,10 +114,10 @@ public function afterSave() } /** - * Load configurable attribute by product and product's attribute + * Load configurable attribute by product and product's attribute. * * @param \Magento\Catalog\Model\Product $product - * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute + * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute * @return void */ public function loadByProductAndAttribute($product, $attribute) @@ -144,7 +146,7 @@ public function deleteByProduct($product) } /** - * {@inheritdoc} + * @inheritdoc * @codeCoverageIgnore */ public function getAttributeId() @@ -153,7 +155,7 @@ public function getAttributeId() } /** - * {@inheritdoc} + * @inheritdoc * @codeCoverageIgnore */ public function getPosition() @@ -162,7 +164,7 @@ public function getPosition() } /** - * {@inheritdoc} + * @inheritdoc * @codeCoverageIgnore */ public function getIsUseDefault() @@ -171,7 +173,7 @@ public function getIsUseDefault() } /** - * {@inheritdoc} + * @inheritdoc * @codeCoverageIgnore */ public function getValues() @@ -182,8 +184,7 @@ public function getValues() //@codeCoverageIgnoreStart /** - * @param string $attributeId - * @return $this + * @inheritdoc */ public function setAttributeId($attributeId) { @@ -191,8 +192,7 @@ public function setAttributeId($attributeId) } /** - * @param string $label - * @return $this + * @inheritdoc */ public function setLabel($label) { @@ -200,8 +200,7 @@ public function setLabel($label) } /** - * @param int $position - * @return $this + * @inheritdoc */ public function setPosition($position) { @@ -209,8 +208,7 @@ public function setPosition($position) } /** - * @param bool $isUseDefault - * @return $this + * @inheritdoc */ public function setIsUseDefault($isUseDefault) { @@ -218,8 +216,7 @@ public function setIsUseDefault($isUseDefault) } /** - * @param \Magento\ConfigurableProduct\Api\Data\OptionValueInterface[] $values - * @return $this + * @inheritdoc */ public function setValues(array $values = null) { @@ -227,7 +224,7 @@ public function setValues(array $values = null) } /** - * {@inheritdoc} + * @inheritdoc * * @return \Magento\ConfigurableProduct\Api\Data\OptionExtensionInterface|null */ @@ -237,7 +234,7 @@ public function getExtensionAttributes() } /** - * {@inheritdoc} + * @inheritdoc * * @param \Magento\ConfigurableProduct\Api\Data\OptionExtensionInterface $extensionAttributes * @return $this @@ -249,7 +246,7 @@ public function setExtensionAttributes( } /** - * {@inheritdoc} + * @inheritdoc */ public function getProductId() { @@ -257,7 +254,7 @@ public function getProductId() } /** - * {@inheritdoc} + * @inheritdoc */ public function setProductId($value) { @@ -268,9 +265,14 @@ public function setProductId($value) /** * @inheritdoc + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return array_diff( parent::__sleep(), ['metadataPool'] @@ -279,9 +281,14 @@ public function __sleep() /** * @inheritdoc + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->metadataPool = $objectManager->get(MetadataPool::class); diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php index 3c40d326be77f..81cbbd06c523c 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php @@ -18,6 +18,8 @@ use Magento\Catalog\Api\Data\ProductInterface; /** + * Collection of configurable product attributes. + * * @api * @SuppressWarnings(PHPMD.LongVariable) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -302,6 +304,8 @@ protected function _loadLabels() } /** + * Load related options' data. + * * @return void */ protected function loadOptions() @@ -354,9 +358,14 @@ protected function getIncludedOptions(array $usedProducts, AbstractAttribute $pr /** * @inheritdoc * @since 100.0.6 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return array_diff( parent::__sleep(), [ @@ -373,9 +382,14 @@ public function __sleep() /** * @inheritdoc * @since 100.0.6 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = ObjectManager::getInstance(); $this->_storeManager = $objectManager->get(\Magento\Store\Model\StoreManagerInterface::class); diff --git a/app/code/Magento/Customer/Model/Attribute.php b/app/code/Magento/Customer/Model/Attribute.php index 98a97872f15f4..ae714f993082e 100644 --- a/app/code/Magento/Customer/Model/Attribute.php +++ b/app/code/Magento/Customer/Model/Attribute.php @@ -202,9 +202,14 @@ public function canBeFilterableInGrid() /** * @inheritdoc + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->unsetData('entity_type'); return array_diff( parent::__sleep(), @@ -214,9 +219,14 @@ public function __sleep() /** * @inheritdoc + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->indexerRegistry = $objectManager->get(\Magento\Framework\Indexer\IndexerRegistry::class); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute.php b/app/code/Magento/Eav/Model/Entity/Attribute.php index 06a4abb985802..e820f14090f77 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute.php @@ -310,9 +310,9 @@ public function beforeSave() } /** - * Save additional data + * @inheritdoc * - * @return $this + * Save additional data. */ public function afterSave() { @@ -496,9 +496,14 @@ public function getIdentities() /** * @inheritdoc * @since 100.0.7 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->unsetData('attribute_set_info'); return array_diff( parent::__sleep(), @@ -509,9 +514,14 @@ public function __sleep() /** * @inheritdoc * @since 100.0.7 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_localeDate = $objectManager->get(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 7ed455eccf4e0..9ed4ac5293681 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -1404,9 +1404,14 @@ public function setExtensionAttributes(\Magento\Eav\Api\Data\AttributeExtensionI /** * @inheritdoc * @since 100.0.7 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return array_diff( parent::__sleep(), [ @@ -1429,9 +1434,14 @@ public function __sleep() /** * @inheritdoc * @since 100.0.7 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_eavConfig = $objectManager->get(\Magento\Eav\Model\Config::class); diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php index 0e7a46125d872..5e7226e7a36dd 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php @@ -725,9 +725,14 @@ public function getValidAttributeIds($attributeIds) * * @return array * @since 100.0.7 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $properties = parent::__sleep(); $properties = array_diff($properties, ['_storeManager']); return $properties; @@ -738,9 +743,14 @@ public function __sleep() * * @return void * @since 100.0.7 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $this->_storeManager = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Store\Model\StoreManagerInterface::class); diff --git a/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php b/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php deleted file mode 100644 index cfdfe17b1e004..0000000000000 --- a/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Paypal\Test\Unit\Block\Adminhtml\System\Config\Fieldset; - -class GroupTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var Group - */ - protected $_model; - - /** - * @var \Magento\Framework\Data\Form\Element\AbstractElement - */ - protected $_element; - - /** - * @var \Magento\Backend\Model\Auth\Session|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_authSession; - - /** - * @var \Magento\User\Model\User|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_user; - - /** - * @var \Magento\Config\Model\Config\Structure\Element\Group|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_group; - - protected function setUp() - { - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->_group = $this->createMock(\Magento\Config\Model\Config\Structure\Element\Group::class); - $this->_element = $this->getMockForAbstractClass( - \Magento\Framework\Data\Form\Element\AbstractElement::class, - [], - '', - false, - true, - true, - ['getHtmlId', 'getElementHtml', 'getName', 'getElements', 'getId'] - ); - $this->_element->expects($this->any()) - ->method('getHtmlId') - ->will($this->returnValue('html id')); - $this->_element->expects($this->any()) - ->method('getElementHtml') - ->will($this->returnValue('element html')); - $this->_element->expects($this->any()) - ->method('getName') - ->will($this->returnValue('name')); - $this->_element->expects($this->any()) - ->method('getElements') - ->will($this->returnValue([])); - $this->_element->expects($this->any()) - ->method('getId') - ->will($this->returnValue('id')); - $this->_user = $this->createMock(\Magento\User\Model\User::class); - $this->_authSession = $this->createMock(\Magento\Backend\Model\Auth\Session::class); - $this->_authSession->expects($this->any()) - ->method('__call') - ->with('getUser') - ->will($this->returnValue($this->_user)); - $this->_model = $helper->getObject( - \Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group::class, - ['authSession' => $this->_authSession] - ); - $this->_model->setGroup($this->_group); - } - - /** - * @param mixed $expanded - * @param int $expected - * @dataProvider isCollapseStateDataProvider - */ - public function testIsCollapseState($expanded, $expected) - { - $this->_user->setExtra(['configState' => []]); - $this->_element->setGroup(isset($expanded) ? ['expanded' => $expanded] : []); - $html = $this->_model->render($this->_element); - $this->assertContains( - '<input id="' . $this->_element->getHtmlId() . '-state" name="config_state[' - . $this->_element->getId() . ']" type="hidden" value="' . $expected . '" />', - $html - ); - } - - /** - * @return array - */ - public function isCollapseStateDataProvider() - { - return [ - [null, 0], - [false, 0], - ['', 0], - [1, 1], - ['1', 1], - ]; - } -} diff --git a/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php b/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php index 55f448730a506..b86f8dff2b3b1 100644 --- a/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php +++ b/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php @@ -12,6 +12,7 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Backend\Model\Auth\Session; use Magento\Framework\App\CacheInterface; +use Magento\User\Model\User; class CanViewNotificationTest extends \PHPUnit\Framework\TestCase { @@ -33,6 +34,11 @@ class CanViewNotificationTest extends \PHPUnit\Framework\TestCase /** @var $cacheStorageMock \PHPUnit_Framework_MockObject_MockObject|CacheInterface */ private $cacheStorageMock; + /** + * @var User|\PHPUnit_Framework_MockObject_MockObject + */ + private $userMock; + public function setUp() { $this->cacheStorageMock = $this->getMockBuilder(CacheInterface::class) @@ -41,7 +47,6 @@ public function setUp() ->getMock(); $this->sessionMock = $this->getMockBuilder(Session::class) ->disableOriginalConstructor() - ->setMethods(['getUser', 'getId']) ->getMock(); $this->viewerLoggerMock = $this->getMockBuilder(Logger::class) ->disableOriginalConstructor() @@ -49,6 +54,7 @@ public function setUp() $this->productMetadataMock = $this->getMockBuilder(ProductMetadataInterface::class) ->disableOriginalConstructor() ->getMock(); + $this->userMock = $this->createMock(User::class); $objectManager = new ObjectManager($this); $this->canViewNotification = $objectManager->getObject( CanViewNotification::class, @@ -65,8 +71,8 @@ public function testIsVisibleLoadDataFromCache() { $this->sessionMock->expects($this->once()) ->method('getUser') - ->willReturn($this->sessionMock); - $this->sessionMock->expects($this->once()) + ->willReturn($this->userMock); + $this->userMock->expects($this->once()) ->method('getId') ->willReturn(1); $this->cacheStorageMock->expects($this->once()) @@ -90,8 +96,8 @@ public function testIsVisible($expected, $version, $lastViewVersion) ->willReturn(false); $this->sessionMock->expects($this->once()) ->method('getUser') - ->willReturn($this->sessionMock); - $this->sessionMock->expects($this->once()) + ->willReturn($this->userMock); + $this->userMock->expects($this->once()) ->method('getId') ->willReturn(1); $this->productMetadataMock->expects($this->once()) diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index b2a515b198b11..21dea880bb43f 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -423,9 +423,14 @@ public function __construct( /** * @inheritdoc + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $properties = parent::__sleep(); $properties = array_diff($properties, ['_coreFileStorageDatabase', '_config']); return $properties; @@ -435,9 +440,14 @@ public function __sleep() * Init not serializable fields * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $this->_coreFileStorageDatabase = ObjectManager::getInstance() ->get(\Magento\MediaStorage\Helper\File\Storage\Database::class); diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index 2994ac351fc78..d8040b0bbaaac 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -212,9 +212,14 @@ protected function _construct() * Removing dependencies and leaving only entity's properties. * * @return string[] + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $properties = parent::__sleep(); return array_diff( $properties, @@ -240,9 +245,14 @@ public function __sleep() * Restoring required objects after serialization. * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->serializer = $objectManager->get(Json::class); @@ -406,6 +416,10 @@ public function getRoles() */ public function getRole() { + if ($this->getData('extracted_role')) { + $this->_role = $this->getData('extracted_role'); + $this->unsetData('extracted_role'); + } if (null === $this->_role) { $this->_role = $this->_roleFactory->create(); $roles = $this->getRoles(); diff --git a/app/code/Magento/User/Test/Unit/Model/Authorization/AdminSessionUserContextTest.php b/app/code/Magento/User/Test/Unit/Model/Authorization/AdminSessionUserContextTest.php deleted file mode 100644 index 23681c4b8da26..0000000000000 --- a/app/code/Magento/User/Test/Unit/Model/Authorization/AdminSessionUserContextTest.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\User\Test\Unit\Model\Authorization; - -use Magento\Authorization\Model\UserContextInterface; - -/** - * Tests Magento\User\Model\Authorization\AdminSessionUserContext - */ -class AdminSessionUserContextTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager - */ - protected $objectManager; - - /** - * @var \Magento\User\Model\Authorization\AdminSessionUserContext - */ - protected $adminSessionUserContext; - - /** - * @var \Magento\Backend\Model\Auth\Session - */ - protected $adminSession; - - protected function setUp() - { - $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - - $this->adminSession = $this->getMockBuilder(\Magento\Backend\Model\Auth\Session::class) - ->disableOriginalConstructor() - ->setMethods(['hasUser', 'getUser', 'getId']) - ->getMock(); - - $this->adminSessionUserContext = $this->objectManager->getObject( - \Magento\User\Model\Authorization\AdminSessionUserContext::class, - ['adminSession' => $this->adminSession] - ); - } - - public function testGetUserIdExist() - { - $userId = 1; - - $this->setupUserId($userId); - - $this->assertEquals($userId, $this->adminSessionUserContext->getUserId()); - } - - public function testGetUserIdDoesNotExist() - { - $userId = null; - - $this->setupUserId($userId); - - $this->assertEquals($userId, $this->adminSessionUserContext->getUserId()); - } - - public function testGetUserType() - { - $this->assertEquals(UserContextInterface::USER_TYPE_ADMIN, $this->adminSessionUserContext->getUserType()); - } - - /** - * @param int|null $userId - * @return void - */ - public function setupUserId($userId) - { - $this->adminSession->expects($this->once()) - ->method('hasUser') - ->will($this->returnValue($userId)); - - if ($userId) { - $this->adminSession->expects($this->once()) - ->method('getUser') - ->will($this->returnSelf()); - - $this->adminSession->expects($this->once()) - ->method('getId') - ->will($this->returnValue($userId)); - } - } -} diff --git a/app/code/Magento/User/Test/Unit/Model/UserTest.php b/app/code/Magento/User/Test/Unit/Model/UserTest.php index 670316c2500fc..ab06c8754b2f0 100644 --- a/app/code/Magento/User/Test/Unit/Model/UserTest.php +++ b/app/code/Magento/User/Test/Unit/Model/UserTest.php @@ -44,31 +44,6 @@ protected function setUp() ); } - /** - * @return void - */ - public function testSleep() - { - $excludedProperties = [ - '_eventManager', - '_cacheManager', - '_registry', - '_appState', - '_userData', - '_config', - '_validatorObject', - '_roleFactory', - '_encryptor', - '_transportBuilder', - '_storeManager', - '_validatorBeforeSave' - ]; - $actualResult = $this->model->__sleep(); - $this->assertNotEmpty($actualResult); - $expectedResult = array_intersect($actualResult, $excludedProperties); - $this->assertEmpty($expectedResult); - } - /** * @return void */ diff --git a/dev/tests/integration/testsuite/Magento/Backend/Model/Auth/SessionTest.php b/dev/tests/integration/testsuite/Magento/Backend/Model/Auth/SessionTest.php index 5ca2bf1f73175..f1e7a10737604 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Model/Auth/SessionTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Model/Auth/SessionTest.php @@ -3,8 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Model\Auth; +use Magento\TestFramework\Bootstrap as TestHelper; +use Magento\TestFramework\Helper\Bootstrap; + /** * @magentoAppArea adminhtml * @magentoAppIsolation enabled @@ -18,10 +22,15 @@ class SessionTest extends \PHPUnit\Framework\TestCase private $auth; /** - * @var \Magento\Backend\Model\Auth\Session + * @var Session */ private $authSession; + /** + * @var SessionFactory + */ + private $authSessionFactory; + /** * @var \Magento\Framework\ObjectManagerInterface */ @@ -30,11 +39,12 @@ class SessionTest extends \PHPUnit\Framework\TestCase protected function setUp() { parent::setUp(); - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->objectManager = Bootstrap::getObjectManager(); $this->objectManager->get(\Magento\Framework\Config\ScopeInterface::class) ->setCurrentScope(\Magento\Backend\App\Area\FrontNameResolver::AREA_CODE); $this->auth = $this->objectManager->create(\Magento\Backend\Model\Auth::class); - $this->authSession = $this->objectManager->create(\Magento\Backend\Model\Auth\Session::class); + $this->authSession = $this->objectManager->create(Session::class); + $this->authSessionFactory = $this->objectManager->get(SessionFactory::class); $this->auth->setAuthStorage($this->authSession); $this->auth->logout(); } @@ -52,8 +62,8 @@ public function testIsLoggedIn($loggedIn) { if ($loggedIn) { $this->auth->login( - \Magento\TestFramework\Bootstrap::ADMIN_NAME, - \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD + TestHelper::ADMIN_NAME, + TestHelper::ADMIN_PASSWORD ); } $this->assertEquals($loggedIn, $this->authSession->isLoggedIn()); @@ -63,4 +73,23 @@ public function loginDataProvider() { return [[false], [true]]; } + + /** + * Check that persisting user data is working. + */ + public function testStorage() + { + $this->auth->login(TestHelper::ADMIN_NAME, TestHelper::ADMIN_PASSWORD); + $user = $this->authSession->getUser(); + $acl = $this->authSession->getAcl(); + /** @var Session $session */ + $session = $this->authSessionFactory->create(); + $persistedUser = $session->getUser(); + $persistedAcl = $session->getAcl(); + + $this->assertEquals($user->getData(), $persistedUser->getData()); + $this->assertEquals($user->getAclRole(), $persistedUser->getAclRole()); + $this->assertEquals($acl->getRoles(), $persistedAcl->getRoles()); + $this->assertEquals($acl->getResources(), $persistedAcl->getResources()); + } } diff --git a/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php b/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php index d1252be2c4b53..88662a65c7428 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php @@ -3,9 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Model\Locale; use Magento\Framework\Locale\Resolver; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\User\Model\User; /** * @magentoAppArea adminhtml @@ -20,7 +23,7 @@ class ResolverTest extends \PHPUnit\Framework\TestCase protected function setUp() { parent::setUp(); - $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + $this->_model = Bootstrap::getObjectManager()->create( \Magento\Backend\Model\Locale\Resolver::class ); } @@ -38,12 +41,12 @@ public function testSetLocaleWithDefaultLocale() */ public function testSetLocaleWithBaseInterfaceLocale() { - $user = new \Magento\Framework\DataObject(); - $session = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + $user = Bootstrap::getObjectManager()->create(User::class); + $session = Bootstrap::getObjectManager()->get( \Magento\Backend\Model\Auth\Session::class ); $session->setUser($user); - \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + Bootstrap::getObjectManager()->get( \Magento\Backend\Model\Auth\Session::class )->getUser()->setInterfaceLocale( 'fr_FR' @@ -56,7 +59,7 @@ public function testSetLocaleWithBaseInterfaceLocale() */ public function testSetLocaleWithSessionLocale() { - \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + Bootstrap::getObjectManager()->get( \Magento\Backend\Model\Session::class )->setSessionLocale( 'es_ES' @@ -69,7 +72,7 @@ public function testSetLocaleWithSessionLocale() */ public function testSetLocaleWithRequestLocale() { - $request = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + $request = Bootstrap::getObjectManager() ->get(\Magento\Framework\App\RequestInterface::class); $request->setPostValue(['locale' => 'de_DE']); $this->_checkSetLocale('de_DE'); diff --git a/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php b/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php new file mode 100644 index 0000000000000..eaa93887fee9e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Backend\Spi; + +use Magento\Framework\AclFactory; +use PHPUnit\Framework\TestCase; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\Acl\Builder as AclBuilder; + +class SessionAclHydratorInterfaceTest extends TestCase +{ + /** + * @var SessionAclHydratorInterface + */ + private $hydrator; + + /** + * @var AclBuilder + */ + private $aclBuilder; + + /** + * @var AclFactory + */ + private $aclFactory; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->hydrator = $objectManager->get(SessionAclHydratorInterface::class); + $this->aclBuilder = $objectManager->get(AclBuilder::class); + $this->aclFactory = $objectManager->get(AclFactory::class); + } + + /** + * Test that ACL data is preserved. + */ + public function testHydrate() + { + $acl = $this->aclBuilder->getAcl(); + $data = $this->hydrator->extract($acl); + $this->hydrator->hydrate($built = $this->aclFactory->create(), $data); + $this->assertEquals($acl->getRoles(), $built->getRoles()); + $this->assertEquals($acl->getResources(), $built->getResources()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionUserHydratorInterfaceTest.php b/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionUserHydratorInterfaceTest.php new file mode 100644 index 0000000000000..e076a4fe1c387 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionUserHydratorInterfaceTest.php @@ -0,0 +1,58 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Backend\Spi; + +use PHPUnit\Framework\TestCase; +use Magento\User\Model\UserFactory; +use Magento\User\Model\User; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Bootstrap as TestHelper; + +/** + * Test hydrator for user data in session. + */ +class SessionUserHydratorInterfaceTest extends TestCase +{ + /** + * @var SessionUserHydratorInterface + */ + private $hydrator; + + /** + * @var UserFactory + */ + private $userFactory; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->hydrator = $objectManager->get(SessionUserHydratorInterface::class); + $this->userFactory = $objectManager->get(UserFactory::class); + } + + /** + * Make sure users' data is preserved during extract/hydrate. + */ + public function testHydrate() + { + /** @var User $user */ + $user = $this->userFactory->create(); + $user->loadByUsername(TestHelper::ADMIN_NAME); + + $userData = $this->hydrator->extract($user); + /** @var User $newUser */ + $newUser = $this->userFactory->create(); + $this->hydrator->hydrate($newUser, $userData); + $this->assertEquals($user->getData(), $newUser->getData()); + $this->assertEquals($user->getRole()->getId(), $newUser->getRole()->getId()); + } +} diff --git a/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/SerializationAware.php b/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/SerializationAware.php new file mode 100644 index 0000000000000..e38fba8558bad --- /dev/null +++ b/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/SerializationAware.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\CodeMessDetector\Rule\Design; + +use PHPMD\AbstractNode; +use PHPMD\AbstractRule; +use PHPMD\Node\ClassNode; +use PHPMD\Node\MethodNode; +use PDepend\Source\AST\ASTMethod; +use PHPMD\Rule\MethodAware; + +/** + * Detect PHP serialization aware methods. + */ +class SerializationAware extends AbstractRule implements MethodAware +{ + /** + * @inheritDoc + * + * @param ASTMethod|MethodNode $method + */ + public function apply(AbstractNode $method) + { + if ($method->getName() === '__wakeup' || $method->getName() === '__sleep') { + $this->addViolation($method, [$method->getName(), $method->getParent()->getFullQualifiedName()]); + } + } +} diff --git a/dev/tests/static/framework/Magento/CodeMessDetector/resources/rulesets/design.xml b/dev/tests/static/framework/Magento/CodeMessDetector/resources/rulesets/design.xml index 73354c46d76b2..56b8036a11ef2 100644 --- a/dev/tests/static/framework/Magento/CodeMessDetector/resources/rulesets/design.xml +++ b/dev/tests/static/framework/Magento/CodeMessDetector/resources/rulesets/design.xml @@ -83,6 +83,31 @@ class OrderProcessor $currentOrder = $this->session->get('current_order'); ... } +} + ]]> + </example> + </rule> + <rule name="SerializationAware" + class="Magento\CodeMessDetector\Rule\Design\SerializationAware" + message="{1} has {0} method and is PHP serialization aware - PHP serialization must be avoided."> + <description> + <![CDATA[ +Using PHP serialization must be avoided in Magento for security reasons and for prevention of unexpected behaviour. + ]]> + </description> + <priority>2</priority> + <properties /> + <example> + <![CDATA[ +class MyModel extends AbstractModel +{ + + ....... + + public function __sleep() + { + ..... + } } ]]> </example> diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml index 7a402818eb0b9..67b195e2f8f0e 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml +++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml @@ -49,5 +49,6 @@ <rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/FinalImplementation" /> <rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/AllPurposeAction" /> <rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/CookieAndSessionMisuse" /> + <rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/SerializationAware" /> </ruleset> diff --git a/lib/internal/Magento/Framework/App/AreaList/Proxy.php b/lib/internal/Magento/Framework/App/AreaList/Proxy.php index d3b26ee9a4190..09115add57190 100644 --- a/lib/internal/Magento/Framework/App/AreaList/Proxy.php +++ b/lib/internal/Magento/Framework/App/AreaList/Proxy.php @@ -1,12 +1,14 @@ <?php /** - * Application area list - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\AreaList; +/** + * Proxy for area list. + */ class Proxy extends \Magento\Framework\App\AreaList implements \Magento\Framework\ObjectManager\NoninterceptableInterface { @@ -56,10 +58,17 @@ public function __construct( } /** + * Remove links to other objects. + * * @return array + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return ['_subject', '_isShared']; } @@ -67,9 +76,14 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/App/Response/Http.php b/lib/internal/Magento/Framework/App/Response/Http.php index 62ff94e7043f5..a152b655e42a3 100644 --- a/lib/internal/Magento/Framework/App/Response/Http.php +++ b/lib/internal/Magento/Framework/App/Response/Http.php @@ -1,10 +1,9 @@ <?php /** - * HTTP response - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Response; use Magento\Framework\App\Http\Context; @@ -16,6 +15,9 @@ use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\Session\Config\ConfigInterface; +/** + * HTTP Response. + */ class Http extends \Magento\Framework\HTTP\PhpEnvironment\Response { /** Cookie to store page vary string */ @@ -113,8 +115,9 @@ public function sendVary() } /** - * Set headers for public cache - * Accepts the time-to-live (max-age) parameter + * Set headers for public cache. + * + * Also accepts the time-to-live (max-age) parameter. * * @param int $ttl * @return void @@ -174,11 +177,18 @@ public function representJson($content) } /** + * Remove links to other objects. + * * @return string[] * @codeCoverageIgnore + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return ['content', 'isRedirect', 'statusCode', 'context', 'headers']; } @@ -187,9 +197,14 @@ public function __sleep() * * @return void * @codeCoverageIgnore + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $objectManager = ObjectManager::getInstance(); $this->cookieManager = $objectManager->create(\Magento\Framework\Stdlib\CookieManagerInterface::class); $this->cookieMetadataFactory = $objectManager->get( diff --git a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php index fd37590bb7782..5e79315238f7d 100644 --- a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php +++ b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php @@ -60,10 +60,17 @@ public function __construct( } /** + * Remove links to other objects. + * * @return array + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return ['_subject', '_isShared']; } @@ -71,9 +78,14 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Response/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Response/HttpTest.php index efb35b7321c3b..9be68b379900a 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Response/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Response/HttpTest.php @@ -290,45 +290,6 @@ public function testRepresentJson() $this->assertEquals('json_string', $this->model->getBody('default')); } - /** - * - * @expectedException \RuntimeException - * @expectedExceptionMessage ObjectManager isn't initialized - */ - public function testWakeUpWithException() - { - /* ensure that the test preconditions are met */ - $objectManagerClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $instanceProperty = $objectManagerClass->getProperty('_instance'); - $instanceProperty->setAccessible(true); - $instanceProperty->setValue(null); - - $this->model->__wakeup(); - $this->assertNull($this->cookieMetadataFactoryMock); - $this->assertNull($this->cookieManagerMock); - } - - /** - * Test for the magic method __wakeup - * - * @covers \Magento\Framework\App\Response\Http::__wakeup - */ - public function testWakeUpWith() - { - $objectManagerMock = $this->createMock(\Magento\Framework\App\ObjectManager::class); - $objectManagerMock->expects($this->once()) - ->method('create') - ->with(\Magento\Framework\Stdlib\CookieManagerInterface::class) - ->will($this->returnValue($this->cookieManagerMock)); - $objectManagerMock->expects($this->at(1)) - ->method('get') - ->with(\Magento\Framework\Stdlib\Cookie\CookieMetadataFactory::class) - ->will($this->returnValue($this->cookieMetadataFactoryMock)); - - \Magento\Framework\App\ObjectManager::setInstance($objectManagerMock); - $this->model->__wakeup(); - } - public function testSetXFrameOptions() { $value = 'DENY'; diff --git a/lib/internal/Magento/Framework/DB/Select.php b/lib/internal/Magento/Framework/DB/Select.php index 4d178b81af6df..f33aaea7d0e68 100644 --- a/lib/internal/Magento/Framework/DB/Select.php +++ b/lib/internal/Magento/Framework/DB/Select.php @@ -400,7 +400,7 @@ public function useStraightJoin($flag = true) /** * Render STRAIGHT_JOIN clause * - * @param string $sql SQL query + * @param string $sql SQL query * @return string */ protected function _renderStraightjoin($sql) @@ -452,7 +452,7 @@ public function orderRand($field = null) /** * Render FOR UPDATE clause * - * @param string $sql SQL query + * @param string $sql SQL query * @return string */ protected function _renderForupdate($sql) @@ -467,9 +467,9 @@ protected function _renderForupdate($sql) /** * Add EXISTS clause * - * @param Select $select - * @param string $joinCondition - * @param bool $isExists + * @param Select $select + * @param string $joinCondition + * @param bool $isExists * @return $this */ public function exists($select, $joinCondition, $isExists = true) @@ -509,11 +509,18 @@ public function assemble() } /** + * Remove links to other objects. + * * @return string[] * @since 100.0.11 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $properties = array_keys(get_object_vars($this)); $properties = array_diff( $properties, @@ -530,9 +537,14 @@ public function __sleep() * * @return void * @since 100.0.11 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_adapter = $objectManager->get(ResourceConnection::class)->getConnection(); $this->selectRenderer = $objectManager->get(\Magento\Framework\DB\Select\SelectRenderer::class); diff --git a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php index 3626f6a07fa18..dc69b96b79050 100644 --- a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php +++ b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php @@ -56,10 +56,17 @@ public function __construct( } /** + * Remove links to other objects. + * * @return array + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return ['_subject', '_isShared']; } @@ -67,9 +74,14 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } @@ -99,7 +111,7 @@ protected function _getSubject() } /** - * {@inheritdoc} + * @inheritdoc */ public function render(\Magento\Framework\DB\Select $select, $sql = '') { diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index 9c789e81913c4..5477b58d4e862 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -886,9 +886,14 @@ public function hasFlag($flag) * * @return string[] * @since 100.0.11 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $properties = array_keys(get_object_vars($this)); $properties = array_diff( $properties, @@ -904,9 +909,14 @@ public function __sleep() * * @return void * @since 100.0.11 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_entityFactory = $objectManager->get(EntityFactoryInterface::class); } diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 308f2a12f506e..1b28e367dcc3a 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -890,9 +890,14 @@ private function getMainTableAlias() /** * @inheritdoc * @since 100.0.11 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return array_diff( parent::__sleep(), ['_fetchStrategy', '_logger', '_conn', 'extensionAttributesJoinProcessor'] @@ -902,9 +907,14 @@ public function __sleep() /** * @inheritdoc * @since 100.0.11 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_logger = $objectManager->get(Logger::class); diff --git a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php index 880da5db771eb..b0f5742afef10 100644 --- a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php @@ -57,10 +57,17 @@ public function __construct( } /** + * Remove links to other objects. + * * @return array + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return ['_subject', '_isShared']; } @@ -68,9 +75,14 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } @@ -100,7 +112,7 @@ protected function _getSubject() } /** - * {@inheritdoc} + * @inheritdoc */ public function merge(array $config) { @@ -108,7 +120,7 @@ public function merge(array $config) } /** - * {@inheritdoc} + * @inheritdoc */ public function get($path = null, $default = null) { @@ -116,7 +128,7 @@ public function get($path = null, $default = null) } /** - * {@inheritdoc} + * @inheritdoc */ public function reset() { diff --git a/lib/internal/Magento/Framework/Interception/Interceptor.php b/lib/internal/Magento/Framework/Interception/Interceptor.php index 07600c5168181..df1b680234220 100644 --- a/lib/internal/Magento/Framework/Interception/Interceptor.php +++ b/lib/internal/Magento/Framework/Interception/Interceptor.php @@ -62,9 +62,14 @@ public function ___callParent($method, array $arguments) * Calls parent class sleep if defined, otherwise provides own implementation * * @return array + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + if (method_exists(get_parent_class($this), '__sleep')) { $properties = parent::__sleep(); } else { @@ -78,9 +83,14 @@ public function __sleep() * Causes Interceptor to be initialized * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + if (method_exists(get_parent_class($this), '__wakeup')) { parent::__wakeup(); } diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index 1cffba2543b0b..e1f6c792c9c3e 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -158,7 +158,7 @@ public function getCustomAttribute($attributeCode) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCustomAttributes(array $attributes) { @@ -166,7 +166,7 @@ public function setCustomAttributes(array $attributes) } /** - * {@inheritdoc} + * @inheritdoc */ public function setCustomAttribute($attributeCode, $attributeValue) { @@ -182,7 +182,7 @@ public function setCustomAttribute($attributeCode, $attributeValue) } /** - * {@inheritdoc} + * @inheritdoc * * Added custom attributes support. */ @@ -200,7 +200,7 @@ public function setData($key, $value = null) } /** - * {@inheritdoc} + * @inheritdoc * * Unset customAttributesChanged flag */ @@ -359,17 +359,27 @@ private function populateExtensionAttributes(array $extensionAttributesData = [] /** * @inheritdoc + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return array_diff(parent::__sleep(), ['extensionAttributesFactory', 'customAttributeFactory']); } /** * @inheritdoc + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->extensionAttributesFactory = $objectManager->get(ExtensionAttributesFactory::class); diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php index 567d174938b11..f5095dbb6e872 100644 --- a/lib/internal/Magento/Framework/Model/AbstractModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractModel.php @@ -219,9 +219,14 @@ protected function _init($resourceModel) * Remove unneeded properties from serialization * * @return string[] + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $properties = array_keys(get_object_vars($this)); $properties = array_diff( $properties, @@ -243,9 +248,14 @@ public function __sleep() * Init not serializable fields * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_registry = $objectManager->get(\Magento\Framework\Registry::class); diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php index 1eaed75bcbfdd..0cadb10aaafe2 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php @@ -156,9 +156,14 @@ public function __construct( * Provide variables to serialize * * @return array + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $properties = array_keys(get_object_vars($this)); $properties = array_diff($properties, ['_resources', '_connections']); return $properties; @@ -168,9 +173,14 @@ public function __sleep() * Restore global dependencies * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->_resources = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\App\ResourceConnection::class); } @@ -219,8 +229,10 @@ protected function _setResource($connections, $tables = null) } /** - * Set main entity table name and primary key field name - * If field name is omitted {table_name}_id will be used + * Main table setter. + * + * Set main entity table name and primary key field name. + * If field name is omitted {table_name}_id will be used. * * @param string $mainTable * @param string|null $idFieldName @@ -253,8 +265,10 @@ public function getIdFieldName() } /** + * Main table getter. + * * Returns main table name - extracted from "module/table" style and - * validated by db adapter + * validated by db adapter. * * @throws LocalizedException * @return string @@ -542,8 +556,7 @@ protected function _prepareDataForSave(\Magento\Framework\Model\AbstractModel $o } /** - * Check that model data fields that can be saved - * has really changed comparing with origData + * Check that model data fields that can be saved has really changed comparing with origData. * * @param \Magento\Framework\Model\AbstractModel $object * @return bool diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php index 8ec47ed97e11c..bc2187f474919 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php @@ -606,9 +606,14 @@ public function save() /** * @inheritdoc * @since 100.0.11 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return array_diff( parent::__sleep(), ['_resource', '_eventManager'] @@ -618,9 +623,14 @@ public function __sleep() /** * @inheritdoc * @since 100.0.11 + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_eventManager = $objectManager->get(\Magento\Framework\Event\ManagerInterface::class); diff --git a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php index a83e9507bda04..d67c380207554 100644 --- a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php @@ -55,10 +55,17 @@ public function __construct( } /** + * Remove links to objects. + * * @return array + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return ['subject', 'isShared']; } @@ -66,9 +73,14 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } @@ -100,7 +112,7 @@ protected function _getSubject() } /** - * {@inheritdoc} + * @inheritdoc */ public function merge(array $config) { @@ -108,7 +120,7 @@ public function merge(array $config) } /** - * {@inheritdoc} + * @inheritdoc */ public function get($path = null, $default = null) { diff --git a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php index 370a88d6d9a43..e6d6cc57c2b09 100644 --- a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php +++ b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php @@ -55,10 +55,17 @@ public function __construct( } /** + * Remove links to other objects. + * * @return array + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return ['subject', 'isShared']; } @@ -66,9 +73,14 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/View/Layout/Proxy.php b/lib/internal/Magento/Framework/View/Layout/Proxy.php index 03020307c5380..a3d89c6ec7a8e 100644 --- a/lib/internal/Magento/Framework/View/Layout/Proxy.php +++ b/lib/internal/Magento/Framework/View/Layout/Proxy.php @@ -57,10 +57,17 @@ public function __construct( } /** + * Remove links to objects. + * * @return array + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __sleep() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + return ['_subject', '_isShared']; } @@ -68,9 +75,14 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void + * + * @SuppressWarnings(PHPMD.SerializationAware) + * @deprecated Do not use PHP serialization. */ public function __wakeup() { + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } @@ -100,7 +112,7 @@ protected function _getSubject() } /** - * {@inheritdoc} + * @inheritdoc */ public function setGeneratorPool(\Magento\Framework\View\Layout\GeneratorPool $generatorPool) { @@ -108,7 +120,7 @@ public function setGeneratorPool(\Magento\Framework\View\Layout\GeneratorPool $g } /** - * {@inheritdoc} + * @inheritdoc */ public function setBuilder(\Magento\Framework\View\Layout\BuilderInterface $builder) { @@ -116,7 +128,7 @@ public function setBuilder(\Magento\Framework\View\Layout\BuilderInterface $buil } /** - * {@inheritdoc} + * @inheritdoc */ public function publicBuild() { @@ -124,7 +136,7 @@ public function publicBuild() } /** - * {@inheritdoc} + * @inheritdoc */ public function getUpdate() { @@ -132,7 +144,7 @@ public function getUpdate() } /** - * {@inheritdoc} + * @inheritdoc */ public function generateXml() { @@ -140,7 +152,7 @@ public function generateXml() } /** - * {@inheritdoc} + * @inheritdoc */ public function generateElements() { @@ -148,7 +160,7 @@ public function generateElements() } /** - * {@inheritdoc} + * @inheritdoc */ public function getChildBlock($parentName, $alias) { @@ -156,7 +168,7 @@ public function getChildBlock($parentName, $alias) } /** - * {@inheritdoc} + * @inheritdoc */ public function setChild($parentName, $elementName, $alias) { @@ -164,7 +176,7 @@ public function setChild($parentName, $elementName, $alias) } /** - * {@inheritdoc} + * @inheritdoc */ public function reorderChild($parentName, $childName, $offsetOrSibling, $after = true) { @@ -172,7 +184,7 @@ public function reorderChild($parentName, $childName, $offsetOrSibling, $after = } /** - * {@inheritdoc} + * @inheritdoc */ public function unsetChild($parentName, $alias) { @@ -180,7 +192,7 @@ public function unsetChild($parentName, $alias) } /** - * {@inheritdoc} + * @inheritdoc */ public function getChildNames($parentName) { @@ -188,7 +200,7 @@ public function getChildNames($parentName) } /** - * {@inheritdoc} + * @inheritdoc */ public function getChildBlocks($parentName) { @@ -196,7 +208,7 @@ public function getChildBlocks($parentName) } /** - * {@inheritdoc} + * @inheritdoc */ public function getChildName($parentName, $alias) { @@ -204,7 +216,7 @@ public function getChildName($parentName, $alias) } /** - * {@inheritdoc} + * @inheritdoc */ public function renderElement($name, $useCache = true) { @@ -212,7 +224,7 @@ public function renderElement($name, $useCache = true) } /** - * {@inheritdoc} + * @inheritdoc */ public function renderNonCachedElement($name) { @@ -220,7 +232,7 @@ public function renderNonCachedElement($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function addToParentGroup($blockName, $parentGroupName) { @@ -228,7 +240,7 @@ public function addToParentGroup($blockName, $parentGroupName) } /** - * {@inheritdoc} + * @inheritdoc */ public function getGroupChildNames($blockName, $groupName) { @@ -236,7 +248,7 @@ public function getGroupChildNames($blockName, $groupName) } /** - * {@inheritdoc} + * @inheritdoc */ public function hasElement($name) { @@ -244,7 +256,7 @@ public function hasElement($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function getElementProperty($name, $attribute) { @@ -252,7 +264,7 @@ public function getElementProperty($name, $attribute) } /** - * {@inheritdoc} + * @inheritdoc */ public function isBlock($name) { @@ -260,7 +272,7 @@ public function isBlock($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function isUiComponent($name) { @@ -268,7 +280,7 @@ public function isUiComponent($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function isContainer($name) { @@ -276,7 +288,7 @@ public function isContainer($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function isManipulationAllowed($name) { @@ -284,7 +296,7 @@ public function isManipulationAllowed($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBlock($name, $block) { @@ -292,7 +304,7 @@ public function setBlock($name, $block) } /** - * {@inheritdoc} + * @inheritdoc */ public function unsetElement($name) { @@ -300,7 +312,7 @@ public function unsetElement($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function createBlock($type, $name = '', array $arguments = []) { @@ -308,7 +320,7 @@ public function createBlock($type, $name = '', array $arguments = []) } /** - * {@inheritdoc} + * @inheritdoc */ public function addBlock($block, $name = '', $parent = '', $alias = '') { @@ -316,7 +328,7 @@ public function addBlock($block, $name = '', $parent = '', $alias = '') } /** - * {@inheritdoc} + * @inheritdoc */ public function addContainer($name, $label, array $options = [], $parent = '', $alias = '') { @@ -324,7 +336,7 @@ public function addContainer($name, $label, array $options = [], $parent = '', $ } /** - * {@inheritdoc} + * @inheritdoc */ public function renameElement($oldName, $newName) { @@ -332,7 +344,7 @@ public function renameElement($oldName, $newName) } /** - * {@inheritdoc} + * @inheritdoc */ public function getAllBlocks() { @@ -340,7 +352,7 @@ public function getAllBlocks() } /** - * {@inheritdoc} + * @inheritdoc */ public function getBlock($name) { @@ -348,7 +360,7 @@ public function getBlock($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function getUiComponent($name) { @@ -356,7 +368,7 @@ public function getUiComponent($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function getParentName($childName) { @@ -364,7 +376,7 @@ public function getParentName($childName) } /** - * {@inheritdoc} + * @inheritdoc */ public function getElementAlias($name) { @@ -372,7 +384,7 @@ public function getElementAlias($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function addOutputElement($name) { @@ -380,7 +392,7 @@ public function addOutputElement($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function removeOutputElement($name) { @@ -388,7 +400,7 @@ public function removeOutputElement($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function getOutput() { @@ -396,7 +408,7 @@ public function getOutput() } /** - * {@inheritdoc} + * @inheritdoc */ public function getMessagesBlock() { @@ -404,7 +416,7 @@ public function getMessagesBlock() } /** - * {@inheritdoc} + * @inheritdoc */ public function getBlockSingleton($type) { @@ -412,7 +424,7 @@ public function getBlockSingleton($type) } /** - * {@inheritdoc} + * @inheritdoc */ public function addAdjustableRenderer($namespace, $staticType, $dynamicType, $type, $template, $data = []) { @@ -427,7 +439,7 @@ public function addAdjustableRenderer($namespace, $staticType, $dynamicType, $ty } /** - * {@inheritdoc} + * @inheritdoc */ public function getRendererOptions($namespace, $staticType, $dynamicType) { @@ -435,7 +447,7 @@ public function getRendererOptions($namespace, $staticType, $dynamicType) } /** - * {@inheritdoc} + * @inheritdoc */ public function executeRenderer($namespace, $staticType, $dynamicType, $data = []) { @@ -443,7 +455,7 @@ public function executeRenderer($namespace, $staticType, $dynamicType, $data = [ } /** - * {@inheritdoc} + * @inheritdoc */ public function initMessages($messageGroups = []) { @@ -451,7 +463,7 @@ public function initMessages($messageGroups = []) } /** - * {@inheritdoc} + * @inheritdoc */ public function isCacheable() { @@ -459,7 +471,7 @@ public function isCacheable() } /** - * {@inheritdoc} + * @inheritdoc */ public function isPrivate() { @@ -467,7 +479,7 @@ public function isPrivate() } /** - * {@inheritdoc} + * @inheritdoc */ public function setIsPrivate($isPrivate = true) { @@ -475,7 +487,7 @@ public function setIsPrivate($isPrivate = true) } /** - * {@inheritdoc} + * @inheritdoc */ public function getReaderContext() { @@ -483,7 +495,7 @@ public function getReaderContext() } /** - * {@inheritdoc} + * @inheritdoc */ public function setXml(\Magento\Framework\Simplexml\Element $node) { @@ -491,7 +503,7 @@ public function setXml(\Magento\Framework\Simplexml\Element $node) } /** - * {@inheritdoc} + * @inheritdoc */ public function getNode($path = null) { @@ -499,7 +511,7 @@ public function getNode($path = null) } /** - * {@inheritdoc} + * @inheritdoc */ public function getXpath($xpath) { @@ -507,7 +519,7 @@ public function getXpath($xpath) } /** - * {@inheritdoc} + * @inheritdoc */ public function getXmlString() { @@ -515,7 +527,7 @@ public function getXmlString() } /** - * {@inheritdoc} + * @inheritdoc */ public function loadFile($filePath) { @@ -523,7 +535,7 @@ public function loadFile($filePath) } /** - * {@inheritdoc} + * @inheritdoc */ public function loadString($string) { @@ -531,7 +543,7 @@ public function loadString($string) } /** - * {@inheritdoc} + * @inheritdoc */ public function loadDom(\DOMNode $dom) { @@ -539,7 +551,7 @@ public function loadDom(\DOMNode $dom) } /** - * {@inheritdoc} + * @inheritdoc */ public function setNode($path, $value, $overwrite = true) { @@ -547,7 +559,7 @@ public function setNode($path, $value, $overwrite = true) } /** - * {@inheritdoc} + * @inheritdoc */ public function applyExtends() { @@ -555,7 +567,7 @@ public function applyExtends() } /** - * {@inheritdoc} + * @inheritdoc */ public function processFileData($text) { @@ -563,7 +575,7 @@ public function processFileData($text) } /** - * {@inheritdoc} + * @inheritdoc */ public function extend(\Magento\Framework\Simplexml\Config $config, $overwrite = true) { From 8f0d0743cdcf0a0a92326f72625908b0212b50b8 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Tue, 26 Mar 2019 16:31:31 -0500 Subject: [PATCH 089/585] MC-4330: Convert AddProductsToCartBySkuFromWidgetTest to MFTF --- .../StorefrontCheckoutCheckOutOfStockProductActionGroup.xml | 2 +- .../Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckOutOfStockProductActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckOutOfStockProductActionGroup.xml index 5fad9f12ca572..92ce4f1f360a6 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckOutOfStockProductActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCheckOutOfStockProductActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontCheckoutCheckOutOfStockProductActionGroup"> <arguments> - <argument name="product"/> + <argument name="product" type="entity"/> </arguments> <see selector="{{CheckoutCartMessageSection.errorMessage}}" userInput="1 product requires your attention." stepKey="seeErrorMessage"/> <see selector="{{CheckoutCartProductSection.productName}}" userInput="{{product.name}}" stepKey="seeProductName"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml index 18393da6738ca..74ece57c6fcc9 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml @@ -33,7 +33,7 @@ <element name="productSubtotalByName" type="input" selector="//main//table[@id='shopping-cart-table']//tbody//tr[..//strong[contains(@class, 'product-item-name')]//a/text()='{{var1}}'][1]//td[contains(@class, 'subtotal')]//span[@class='price']" parameterized="true"/> <element name="updateShoppingCartButton" type="button" selector="#form-validate button[type='submit'].update" timeout="30"/> <element name="qty" type="input" selector="//input[@data-cart-item-id='{{var}}'][@title='Qty']" parameterized="true"/> - <element name="messageErrorItem" type="text" selector="//*[@id='sku-stock-failed-']"/> + <element name="messageErrorItem" type="text" selector="#sku-stock-failed-"/> <element name="messageErrorNeedChooseOptions" type="text" selector="//*[contains(@class, 'error')]/div"/> <element name="productOptionsLink" type="text" selector="a.action.configure"/> </section> From e627992e01baf5e19b8fae76ed2b23f12fc8d5b2 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 27 Mar 2019 01:03:00 +0200 Subject: [PATCH 090/585] 530 - [Cart Operations] Update Cart Items validation messages 1. Add necessary tests --- .../CatalogInventory/AddProductToCartTest.php | 21 ++++++++++++++++++- .../Quote/AddSimpleProductToCartTest.php | 21 ++++++++++++++++++- .../Quote/Customer/UpdateCartItemsTest.php | 21 +++++++++++++++++++ .../Quote/Guest/UpdateCartItemsTest.php | 21 +++++++++++++++++++ 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 17c2af8dc59d0..e41c6b4dfe3b2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -78,6 +78,25 @@ public function testAddMoreProductsThatAllowed() self::fail('Should be "The most you may purchase is 5." error message.'); } + /** + * @magentoApiDataFixture Magento/Catalog/_files/products.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + */ + public function testAddProductIfQuantityIsDecimal() + { + $sku = 'simple'; + $qty = 0.2; + + $maskedQuoteId = $this->getMaskedQuoteId(); + $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not add the product with SKU {$sku} to the shopping cart: The fewest you may purchase is 1." + ); + + $this->graphQlQuery($query); + } + /** * @return string */ @@ -95,7 +114,7 @@ public function getMaskedQuoteId() : string * @param int $qty * @return string */ - public function getAddSimpleProductQuery(string $maskedQuoteId, string $sku, int $qty) : string + public function getAddSimpleProductQuery(string $maskedQuoteId, string $sku, float $qty) : string { return <<<QUERY mutation { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php index 1e92a2e497bed..6fe2853f43657 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php @@ -59,6 +59,25 @@ public function testAddSimpleProductToCart() self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); } + /** + * @magentoApiDataFixture Magento/Catalog/_files/products.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + */ + public function testAddSimpleProductToCartWithDecimalQty() + { + $sku = 'simple'; + $qty = 0.5; + $maskedQuoteId = $this->getMaskedQuoteId(); + + $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not add the product with SKU {$sku} to the shopping cart: The fewest you may purchase is 1." + ); + + $this->graphQlQuery($query); + } + /** * @return string */ @@ -76,7 +95,7 @@ public function getMaskedQuoteId() : string * @param int $qty * @return string */ - public function getAddSimpleProductQuery(string $maskedQuoteId, string $sku, int $qty): string + public function getAddSimpleProductQuery(string $maskedQuoteId, string $sku, float $qty): string { return <<<QUERY mutation { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php index 74e7aa8b5d0a4..4538f3cbe4c86 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php @@ -79,6 +79,27 @@ public function testUpdateCartItemQty() $this->assertEquals($qty, $item['qty']); } + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + */ + public function testUpdateCartItemDecimalQty() + { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); + $product = $this->productRepository->get('simple'); + + $itemId = (int)$quote->getItemByProduct($product)->getId(); + $qty = 0.5; + + $this->expectExceptionMessage( + "Could not update the product with SKU " . $product->getSku() . ": The fewest you may purchase is 1." + ); + + $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php index fca7a4287620b..254d2560f8992 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php @@ -72,6 +72,27 @@ public function testUpdateCartItemQty() $this->assertEquals($qty, $item['qty']); } + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + */ + public function testUpdateCartItemDecimalQty() + { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); + $product = $this->productRepository->get('simple'); + + $itemId = (int)$quote->getItemByProduct($product)->getId(); + $qty = 0.5; + + $this->expectExceptionMessage( + "Could not update the product with SKU " . $product->getSku() . ": The fewest you may purchase is 1." + ); + + $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $this->graphQlQuery($query); + } + /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php */ From eec7473b6c774d72ab2d3e86495b43082face6f5 Mon Sep 17 00:00:00 2001 From: Vishal Sutariya <vishalsutariya7037@gmail.com> Date: Wed, 27 Mar 2019 15:10:47 +0530 Subject: [PATCH 091/585] Fixed shipping method block alignment issue --- .../backend/Magento_Sales/web/css/source/module/_order.less | 1 + 1 file changed, 1 insertion(+) diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less index fa1ae25628986..480fc57c1149d 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less @@ -64,6 +64,7 @@ } .order-shipping-address, + .order-shipping-method, .order-totals, .order-view-account-information .order-account-information { float: right; From 27554ca478a6cac01dabe542885124de45a17dd9 Mon Sep 17 00:00:00 2001 From: Denys Saltanahmedov <d.saltanakhmedov@atwix.com> Date: Wed, 27 Mar 2019 14:08:33 +0200 Subject: [PATCH 092/585] Adding delete customer group product form test case #581 --- .../Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml index e5f889a068067..3086c07c46ddc 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml @@ -68,5 +68,13 @@ <argument name="customerEmail" value="$$createCustomer.email$$"/> <argument name="groupName" value="{{GeneralCustomerGroup.code}}"/> </actionGroup> + + <!--Go to New Product page, add check custom customer group values--> + <amOnPage url="{{AdminProductCreatePage.url('4', 'simple')}}" stepKey="goToCreateSimpleProductPage"/> + <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickOnAdvancedPricingButton"/> + <waitForElement selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForCustomerGroupPriceAddButton"/> + <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="addCustomerGroupAllGroupsQty1PriceDiscountAnd10percent"/> + <waitForElement selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" stepKey="waitForSelectCustomerGroupNameAttribute2"/> + <dontSee selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" userInput="{{CustomerGroupChange.code}}" stepKey="seeProductTierPriceCustomerGroupInput"/> </test> </tests> From 7cb0cf8dc21612761b9e58de600447c12ef340dd Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Wed, 27 Mar 2019 14:41:42 +0200 Subject: [PATCH 093/585] fix issue-21960 --- app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php index e61a886a41d6f..a5e9f9ef0a331 100644 --- a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php +++ b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php @@ -115,7 +115,7 @@ protected function _getItemsData() } $label = $this->renderRangeLabel( empty($from) ? 0 : $from, - empty($to) ? 0 : $to + empty($to) ? $to : $to ); $value = $from . '-' . $to; From 3b29e37fe5e8160fd98999f1fce09e3409c9e337 Mon Sep 17 00:00:00 2001 From: Denys Saltanahmedov <d.saltanakhmedov@atwix.com> Date: Wed, 27 Mar 2019 14:49:40 +0200 Subject: [PATCH 094/585] Adding delete customer group - catalog and cart price rules test cases #581 --- .../Mftf/Test/DeleteCustomerGroupTest.xml | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml index 3086c07c46ddc..c7c40d8170f3b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml @@ -19,7 +19,6 @@ <before> <createData entity="Simple_US_Customer" stepKey="createCustomer"/> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> @@ -72,9 +71,30 @@ <!--Go to New Product page, add check custom customer group values--> <amOnPage url="{{AdminProductCreatePage.url('4', 'simple')}}" stepKey="goToCreateSimpleProductPage"/> <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickOnAdvancedPricingButton"/> - <waitForElement selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForCustomerGroupPriceAddButton"/> - <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="addCustomerGroupAllGroupsQty1PriceDiscountAnd10percent"/> - <waitForElement selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" stepKey="waitForSelectCustomerGroupNameAttribute2"/> - <dontSee selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" userInput="{{CustomerGroupChange.code}}" stepKey="seeProductTierPriceCustomerGroupInput"/> + <waitForElement selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" + stepKey="waitForCustomerGroupPriceAddButton"/> + <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" + stepKey="addCustomerGroupAllGroupsQty1PriceDiscountAnd10percent"/> + <waitForElement selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" + stepKey="waitForSelectCustomerGroupNameAttribute2"/> + <dontSee selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" + userInput="{{CustomerGroupChange.code}}" + stepKey="seeProductTierPriceCustomerGroupInput"/> + + <!--Go to Catalog price rule page, add check custom customer group values--> + <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> + <waitForPageLoad stepKey="waitForPriceRulePage"/> + <click stepKey="addNewRule" selector="{{AdminGridMainControls.add}}"/> + <dontSee selector="{{AdminNewCatalogPriceRule.customerGroups}}" + userInput="{{CustomerGroupChange.code}}" + stepKey="dontSeeCatalogPriceRuleCustomerGroups"/> + + <!--Go to Cart price rule page, add check custom customer group values--> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForRulesPage"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <dontSee selector="{{AdminCartPriceRulesFormSection.customerGroups}}" + userInput="{{CustomerGroupChange.code}}" + stepKey="dontSeeCartPriceRuleCustomerGroups"/> </test> </tests> From 6ad583a3198eca02650ac4718447c02f00756b04 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Wed, 27 Mar 2019 10:02:44 -0500 Subject: [PATCH 095/585] MC-4432: Convert ApplyConfigurableProductCatalogPriceRulesTest to MFTF --- ...ableProductWithAssignedSimpleProductsTest.xml | 16 +++------------- .../Customer/Test/Mftf/Data/CustomerData.xml | 13 +++++++++++++ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml index d614af31339fa..7363fe7b3a96b 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml @@ -137,7 +137,9 @@ <createData entity="CustomCustomerGroup" stepKey="customerGroup"/> <!-- Create Customer --> - <createData entity="CustomerEntityOne" stepKey="createCustomer"/> + <createData entity="SimpleUsCustomerWithNewCustomerGroup" stepKey="createCustomer"> + <requiredEntity createDataKey="customerGroup" /> + </createData> <!-- Login as Admin --> <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> @@ -172,18 +174,6 @@ <!-- Admin log out --> <actionGroup ref="logout" stepKey="logout"/> </after> - - <!-- Go to the Customer page and find created customer --> - <actionGroup ref="AdminFilterCustomerByEmail" stepKey="findCreatedCustomerByEmail"> - <argument name="email" value="$$createCustomer.email$$"/> - </actionGroup> - <actionGroup ref="AdminSelectAllCustomers" stepKey="selectCustomer"/> - - <!-- Change customer group to created below --> - <actionGroup ref="SetCustomerGroupForSelectedCustomersViaGrid" stepKey="setCustomerGroup"> - <argument name="groupName" value="$$customerGroup.code$$"/> - </actionGroup> - <!-- Create price rule --> <actionGroup ref="newCatalogPriceRuleByUI" stepKey="createPriceRule"> <argument name="catalogRule" value="CatalogRuleToFixed"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index 06c23a2864984..4796fd73e104f 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -46,6 +46,19 @@ <data key="website_id">0</data> <requiredEntity type="address">US_Address_TX</requiredEntity> </entity> + <entity name="SimpleUsCustomerWithNewCustomerGroup" type="customer"> + <data key="default_billing">true</data> + <data key="default_shipping">true</data> + <data key="email" unique="prefix">John.Doe@example.com</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="fullname">John Doe</data> + <data key="password">pwdTest123!</data> + <data key="store_id">0</data> + <data key="website_id">0</data> + <requiredEntity type="address">US_Address_TX</requiredEntity> + <var entityType="customerGroup" entityKey="id" key="group_id" /> + </entity> <entity name="Simple_US_Customer_Incorrect_Name" type="customer"> <data key="group_id">1</data> <data key="default_billing">true</data> From eefa8891687de63e3e66d3a1616b4695893b7bdf Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Wed, 27 Mar 2019 17:44:30 +0200 Subject: [PATCH 096/585] Converting the ValidateEmailOnCheckoutTest to MFTF --- .../Mftf/Test/ValidateEmailOnCheckoutTest.xml | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml new file mode 100644 index 0000000000000..e41573ffbfc64 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ValidateEmailOnCheckoutTest"> + <annotations> + <features value="Checkout"/> + <title value="Guest Checkout"/> + <description value="Email validation for Guest on checkout flow"/> + <stories value="Email validation for Guest on checkout flow"/> + <group value="shoppingCart"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <createData entity="SimpleTwo" stepKey="createSimpleProduct"/> + </before> + + <!--Go to product page--> + <amOnPage url="$$createSimpleProduct.custom_attributes[url_key]$$.html" stepKey="navigateToSimpleProductPage"/> + <waitForPageLoad stepKey="waitForCatalogPageLoad"/> + + <!--Add Product to Shopping Cart--> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addToCartFromStorefrontProductPage"> + <argument name="productName" value="$$createSimpleProduct.name$$"/> + </actionGroup> + + <!--Go to Checkout--> + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask1"/> + + <!--Fill in the form fields for 1st variation, and check the validation message--> + <fillField selector="{{CheckoutShippingSection.email}}" userInput="johndoe" stepKey="setCustomerEmailVariation1"/> + <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="John" stepKey="SetCustomerFirstNameVariation1"/> + <waitForPageLoad stepKey="waitforFormValidation1"/> + <see userInput="Please enter a valid email address (Ex: johndoe@domain.com)." stepKey="seeTheErrorMessageIsDisplayed1"/> + + <!--Fill in the form fields for 2nd variation, and check the validation message--> + <fillField selector="{{CheckoutShippingSection.email}}" userInput="johndoe#example.com" stepKey="setCustomerEmailVariation2"/> + <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="John" stepKey="SetCustomerFirstNameVariation2"/> + <waitForPageLoad stepKey="waitForFormValidation2"/> + <see userInput="Please enter a valid email address (Ex: johndoe@domain.com)." stepKey="seeTheErrorMessageIsDisplayed2"/> + + <!--Fill in the form fields for 3rd variation, and check the validation message--> + <fillField selector="{{CheckoutShippingSection.email}}" userInput="johndoe@example.c" stepKey="setCustomerEmailVariation3"/> + <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="John" stepKey="SetCustomerFirstNameVariation3"/> + <waitForPageLoad stepKey="waitForFormValidation3"/> + <see userInput="Please enter a valid email address (Ex: johndoe@domain.com)." stepKey="seeTheErrorMessageIsDisplayed3"/> + + <after> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> + </after> + </test> +</tests> From 58211e3cd81dca5e441d3b3f3d1810ef6ce2783b Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Wed, 27 Mar 2019 18:28:09 +0200 Subject: [PATCH 097/585] Convert LockAdminUserWhenCreatingNewUserTest to MFTF --- .../Test/Mftf/Page/AdminAddNewUserPage.xml | 14 +++++ .../Mftf/Section/AdminLoginFormSection.xml | 1 + .../Test/Mftf/Section/AdminNewUserSection.xml | 23 +++++++ ...rInvalidCurrentUserPasswordActionGroup.xml | 25 ++++++++ .../Security/Test/Mftf/Data/AdminUserData.xml | 18 ++++++ .../LockAdminUserWhenCreatingNewUserTest.xml | 62 +++++++++++++++++++ 6 files changed, 143 insertions(+) create mode 100644 app/code/Magento/Backend/Test/Mftf/Page/AdminAddNewUserPage.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml create mode 100644 app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml create mode 100644 app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml create mode 100644 app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Page/AdminAddNewUserPage.xml b/app/code/Magento/Backend/Test/Mftf/Page/AdminAddNewUserPage.xml new file mode 100644 index 0000000000000..4f7dc5539de6f --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Page/AdminAddNewUserPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminAddNewUserPage" url="admin/user/new" area="admin" module="Backend"> + <section name="AddNewAdminUserSection"/> + </page> +</pages> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 3b10fac7bb9dc..58efb66747b15 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,5 +12,6 @@ <element name="username" type="input" selector="#username"/> <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> + <element name="error" type="text" selector=".message.message-error.error"/> </section> </sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml new file mode 100644 index 0000000000000..a85229ad991d6 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminNewUserSection"> + <element name="username" type="input" selector="#user_username"/> + <element name="firstname" type="input" selector="#user_firstname"/> + <element name="lastname" type="input" selector="#user_lastname"/> + <element name="email" type="input" selector="#user_email"/> + <element name="password" type="input" selector="#user_password"/> + <element name="confirmation" type="input" selector="#user_confirmation"/> + <element name="currentPassword" type="input" selector="#user_current_password"/> + <element name="save" type="button" selector="#save"/> + <element name="userRoleTab" type="button" selector="#page_tabs_roles_section"/> + <element name="administratorRole" type="radio" selector="//*[@id='permissionsUserRolesGrid_table']//td[{{role}}]/input" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml new file mode 100644 index 0000000000000..4721106c1e317 --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminNewUserInvalidCurrentUserPasswordActionGroup"> + <!-- Fill in all data according to data set (current password is incorrect). --> + <fillField selector="{{AdminNewUserSection.username}}" userInput="{{AdminUserData.username}}" stepKey="fillUser"/> + <fillField selector="{{AdminNewUserSection.firstname}}" userInput="{{AdminUserData.firstname}}" stepKey="fillFirstName"/> + <fillField selector="{{AdminNewUserSection.lastname}}" userInput="{{AdminUserData.lastname}}" stepKey="fillLastName"/> + <fillField selector="{{AdminNewUserSection.email}}" userInput="{{AdminUserData.email}}" stepKey="fillEmail"/> + <fillField selector="{{AdminNewUserSection.password}}" userInput="{{AdminUserData.password}}" stepKey="fillPassword"/> + <fillField selector="{{AdminNewUserSection.confirmation}}" userInput="{{AdminUserData.password}}" stepKey="fillPasswordConfirmation"/> + <fillField selector="{{AdminNewUserSection.currentPassword}}" userInput="{{AdminUserData.password}}INVALID" stepKey="fillCurrentUserPassword"/> + <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> + <click selector="{{AdminNewUserSection.userRoleTab}}" stepKey="openUserRoleTab"/> + <click selector="{{AdminNewUserSection.administratorRole('1')}}" stepKey="assignRole"/> + <click selector="{{AdminNewUserSection.save}}" stepKey="saveNewUser"/> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml b/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml new file mode 100644 index 0000000000000..65b18910098ad --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="AdminUserData" type="admin"> + <data key="email" unique="prefix">John.Doe@example.com</data> + <data key="firstname">John</data> + <data key="username">lockuser</data> + <data key="lastname">Doe</data> + <data key="password">pwdTest123!</data> + </entity> +</entities> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml new file mode 100644 index 0000000000000..1aa0fdfc8b8fc --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="LockAdminUserWhenCreatingNewUserTest"> + <annotations> + <features value="Security"/> + <stories value="Runs Lock admin user when creating new user test."/> + <title value="Lock admin user when creating new user"/> + <description value="Runs Lock admin user when creating new user test."/> + <severity value="MAJOR"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Log in to Admin Panel --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!-- Unlock Admin user --> + <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> + </after> + + <!-- Open Admin New User Page --> + <amOnPage url="{{AdminAddNewUserPage.url}}" stepKey="amOnNewAdminUserPage"/> + <waitForPageLoad stepKey="waitForNewAdminUserPageLoad"/> + + <!-- Perform add new admin user 6 specified number of times. + "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt1"> + </actionGroup> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + <see selector="{{AdminMessagesSection.error}}" userInput="The password entered for the current user is invalid. Verify the password and try again." + stepKey="seeInvalidPasswordError"/> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt2"> + </actionGroup> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt3"> + </actionGroup> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt4"> + </actionGroup> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt5"> + </actionGroup> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt6"> + </actionGroup> + + <!-- Check Error that account has been locked --> + <waitForPageLoad stepKey="wailtForSaveResultLoad"/> + <see selector="{{AdminLoginFormSection.error}}" userInput="Your account is temporarily disabled. Please try again later." stepKey="seeLockUserError"/> + + <!-- Try to login as admin and check error --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> + <waitForPageLoad stepKey="waitForError"/> + <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" + stepKey="seeLockUserError2"/> + </test> +</tests> From b748038a432bcdf469b84ae4b18406a3e35e24f0 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Wed, 27 Mar 2019 11:34:47 -0500 Subject: [PATCH 098/585] MC-4440: Convert CreateScheduledProductUpdateTest to MFTF --- app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml | 4 ++++ .../Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml | 1 + 2 files changed, 5 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 1aca63b28c95d..42267b8707b11 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -982,4 +982,8 @@ <data key="tax_class_id">2</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> </entity> + <entity name="SimpleProductWithTwoOption" type="product"> + <var key="sku" entityType="product" entityKey="sku" /> + <requiredEntity type="product_option">ProductOptionMultiSelect</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml index 59fbeee142dfe..83b541458ee9b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml @@ -11,5 +11,6 @@ <section name="AdminProductMessagesSection"> <element name="successMessage" type="text" selector=".message-success"/> <element name="errorMessage" type="text" selector=".message.message-error.error"/> + <element name="adminMessage" type="text" selector="//*[contains(@class, 'message-error')]"/> </section> </sections> From 1936cfad30a62b712b841929f984cde00750d763 Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Wed, 27 Mar 2019 13:08:05 -0500 Subject: [PATCH 099/585] MC-4428: Convert CreateCatalogPriceRuleEntityTest to MFTF --- ...inCreateNewCatalogPriceRuleActionGroup.xml | 30 ++++++++ .../AdminDeleteCatalogRuleActionGroup.xml | 18 +++++ .../AdminSaveAndApplyRulesActionGroup.xml | 21 ++++++ ...dminSearchCatalogRuleInGridActionGroup.xml | 23 ++++++ ...inSelectCatalogRuleFromGridActionGroup.xml | 18 +++++ .../AssertCatalogPriceRuleFormActionGroup.xml | 29 +++++++ .../AssertCatalogRuleInGridActionGroup.xml | 23 ++++++ .../Test/Mftf/Data/CatalogRuleData.xml | 13 ++++ .../Page/AdminNewCatalogPriceRulePage.xml | 14 ++++ .../AdminNewCatalogPriceRuleSection.xml | 8 ++ ...dminCreateInactiveCatalogPriceRuleTest.xml | 75 +++++++++++++++++++ 11 files changed, 272 insertions(+) create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCreateNewCatalogPriceRuleActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminDeleteCatalogRuleActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSaveAndApplyRulesActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSearchCatalogRuleInGridActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSelectCatalogRuleFromGridActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCatalogPriceRuleFormActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCatalogRuleInGridActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Page/AdminNewCatalogPriceRulePage.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateInactiveCatalogPriceRuleTest.xml diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCreateNewCatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCreateNewCatalogPriceRuleActionGroup.xml new file mode 100644 index 0000000000000..4599e325e39cb --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCreateNewCatalogPriceRuleActionGroup.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateNewCatalogPriceRuleActionGroup"> + <arguments> + <argument name="catalogRule" defaultValue="_defaultCatalogRule"/> + <argument name="customerGroup" type="string"/> + </arguments> + <amOnPage url="{{AdminNewCatalogPriceRulePage.url}}" stepKey="openNewCatalogPriceRulePage"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <fillField stepKey="fillName" selector="{{AdminNewCatalogPriceRule.ruleName}}" userInput="{{catalogRule.name}}"/> + <fillField stepKey="fillDescription" selector="{{AdminNewCatalogPriceRule.description}}" userInput="{{catalogRule.description}}"/> + <selectOption selector="{{AdminNewCatalogPriceRule.status}}" userInput="{{catalogRule.is_active}}" stepKey="selectStatus"/> + <selectOption stepKey="selectWebSite" selector="{{AdminNewCatalogPriceRule.websites}}" userInput="{{catalogRule.website_ids[0]}}"/> + <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="{{customerGroup}}" stepKey="selectCustomerGroup"/> + <scrollTo selector="{{AdminNewCatalogPriceRule.actionsTab}}" stepKey="scrollToActionTab"/> + <click stepKey="openActionDropdown" selector="{{AdminNewCatalogPriceRule.actionsTab}}"/> + <selectOption stepKey="discountType" selector="{{AdminNewCatalogPriceRuleActions.apply}}" userInput="{{catalogRule.simple_action}}"/> + <fillField stepKey="fillDiscountValue" selector="{{AdminNewCatalogPriceRuleActions.discountAmount}}" userInput="{{catalogRule.discount_amount}}"/> + <selectOption stepKey="discardSubsequentRules" selector="{{AdminNewCatalogPriceRuleActions.disregardRules}}" userInput="Yes"/> + <waitForPageLoad stepKey="waitForApplied"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminDeleteCatalogRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminDeleteCatalogRuleActionGroup.xml new file mode 100644 index 0000000000000..ea2d6821917e3 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminDeleteCatalogRuleActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminDeleteCatalogRuleActionGroup"> + <click selector="{{AdminNewCatalogPriceRule.delete}}" stepKey="clickOnDeleteButton"/> + <waitForElementVisible selector="{{AdminNewCatalogPriceRule.okButton}}" stepKey="waitForOkButtonToBeVisible"/> + <click selector="{{AdminNewCatalogPriceRule.okButton}}" stepKey="clickOnOkButton"/> + <waitForPageLoad stepKey="waitForPagetoLoad"/> + <see selector="{{AdminNewCatalogPriceRule.successMessage}}" userInput="You deleted the rule." stepKey="seeSuccessDeleteMessage"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSaveAndApplyRulesActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSaveAndApplyRulesActionGroup.xml new file mode 100644 index 0000000000000..2584b8b36b769 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSaveAndApplyRulesActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSaveAndApplyRulesActionGroup"> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <scrollToTopOfPage stepKey="scrollToTop"/> + <click selector="{{AdminNewCatalogPriceRule.save}}" stepKey="saveTheCatalogRule"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <seeElement selector="{{AdminCatalogPriceRuleGrid.updateMessage}}" stepKey="seeMessageToUpdateTheCatalogRules"/> + <see selector="{{AdminNewCatalogPriceRule.successMessage}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> + <click stepKey="applyRules" selector="{{AdminCatalogPriceRuleGrid.applyRules}}"/> + <see stepKey="assertSuccess" selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="Updated rules applied."/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSearchCatalogRuleInGridActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSearchCatalogRuleInGridActionGroup.xml new file mode 100644 index 0000000000000..c7d5d853642c0 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSearchCatalogRuleInGridActionGroup.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSearchCatalogRuleInGridActionGroup"> + <arguments> + <argument name="catalogRuleName" type="string"/> + </arguments> + <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> + <waitForPageLoad stepKey="waitForPriceRulePage"/> + <click selector="{{AdminCatalogPriceRuleGrid.resetFilter}}" stepKey="clickOnResetFilter"/> + <waitForPageLoad stepKey="waitForTheGridPageToLoad"/> + <fillField selector="{{AdminCatalogPriceRuleGrid.ruleFilter}}" userInput="{{catalogRuleName}}" stepKey="fillTheRuleFilter"/> + <click selector="{{AdminCatalogPriceRuleGrid.search}}" stepKey="clickOnSearchButton"/> + <waitForPageLoad stepKey="waitForTheSearchResult"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSelectCatalogRuleFromGridActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSelectCatalogRuleFromGridActionGroup.xml new file mode 100644 index 0000000000000..f0e927ea84048 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminSelectCatalogRuleFromGridActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSelectCatalogRuleFromGridActionGroup"> + <arguments> + <argument name="catalogRuleName" type="string"/> + </arguments> + <click selector="{{AdminCatalogPriceRuleGrid.selectRowByRuleName(catalogRuleName)}}" stepKey="selectRow"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCatalogPriceRuleFormActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCatalogPriceRuleFormActionGroup.xml new file mode 100644 index 0000000000000..330c2ad7e15f6 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCatalogPriceRuleFormActionGroup.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCatalogPriceRuleFormActionGroup"> + <arguments> + <argument name="catalogRule" defaultValue="inactiveCatalogRule" /> + <argument name="status" type="string" defaultValue=""/> + <argument name="websites" type="string"/> + <argument name="customerGroup" type="string"/> + </arguments> + <seeInField stepKey="fillName" selector="{{AdminNewCatalogPriceRule.ruleName}}" userInput="{{catalogRule.name}}"/> + <seeInField stepKey="fillDescription" selector="{{AdminNewCatalogPriceRule.description}}" userInput="{{catalogRule.description}}"/> + <seeOptionIsSelected selector="{{AdminNewCatalogPriceRule.status}}" userInput="{{status}}" stepKey="selectStatus"/> + <see stepKey="seeWebSite" selector="{{AdminNewCatalogPriceRule.websites}}" userInput="{{websites}}"/> + <seeOptionIsSelected selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="{{customerGroup}}" stepKey="selectCustomerGroup"/> + <scrollTo selector="{{AdminNewCatalogPriceRule.actionsTab}}" stepKey="scrollToActionTab"/> + <click stepKey="openActionDropdown" selector="{{AdminNewCatalogPriceRule.actionsTab}}"/> + <seeInField stepKey="discountType" selector="{{AdminNewCatalogPriceRuleActions.apply}}" userInput="{{catalogRule.simple_action}}"/> + <seeInField stepKey="fillDiscountValue" selector="{{AdminNewCatalogPriceRuleActions.discountAmount}}" userInput="{{catalogRule.discount_amount}}"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCatalogRuleInGridActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCatalogRuleInGridActionGroup.xml new file mode 100644 index 0000000000000..8be41c3b07af6 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCatalogRuleInGridActionGroup.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCatalogRuleInGridActionGroup"> + <arguments> + <argument name="catalogRuleName" type="string"/> + <argument name="status" type="string" defaultValue=""/> + <argument name="websites" type="string"/> + <argument name="catalogRuleId" type="string"/> + </arguments> + <see selector="{{AdminCatalogPriceRuleGrid.firstRow}}" userInput="{{catalogRuleId}}" stepKey="seeCatalogRuleId"/> + <see selector="{{AdminCatalogPriceRuleGrid.firstRow}}" userInput="{{catalogRuleName}}" stepKey="seeCatalogRuleName"/> + <see selector="{{AdminCatalogPriceRuleGrid.firstRow}}" userInput="{{status}}" stepKey="seeCatalogRuleStatus"/> + <see selector="{{AdminCatalogPriceRuleGrid.firstRow}}" userInput="{{websites}}" stepKey="seeCatalogRuleWebsite"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml b/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml index 5b75708d1ae0a..d04957a7cdfb5 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml @@ -94,4 +94,17 @@ <data key="simple_action">by_percent</data> <data key="discount_amount">10</data> </entity> + <entity name="InactiveCatalogRule" type="catalogRule"> + <data key="name" unique="suffix">InactiveCatalogRule</data> + <data key="description">Inactive Catalog Price Rule Description</data> + <data key="is_active">0</data> + <array key="customer_group_ids"> + <item>1</item> + </array> + <array key="website_ids"> + <item>1</item> + </array> + <data key="simple_action">by_fixed</data> + <data key="discount_amount">10</data> + </entity> </entities> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Page/AdminNewCatalogPriceRulePage.xml b/app/code/Magento/CatalogRule/Test/Mftf/Page/AdminNewCatalogPriceRulePage.xml new file mode 100644 index 0000000000000..fded4f5e5f322 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Page/AdminNewCatalogPriceRulePage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminNewCatalogPriceRulePage" url="catalog_rule/promo_catalog/new/" module="Magento_CatalogRule" area="admin"> + <section name="AdminNewCatalogPriceRule"/> + </page> +</pages> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml b/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml index 635260888e7fb..0b1c935a3c248 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml @@ -13,6 +13,8 @@ <element name="save" type="button" selector="#save" timeout="30"/> <element name="saveAndContinue" type="button" selector="#save_and_continue" timeout="30"/> <element name="delete" type="button" selector="#delete" timeout="30"/> + <element name="okButton" type="button" selector="//button[@class='action-primary action-accept']"/> + <element name="successMessage" type="text" selector="#messages"/> <element name="ruleName" type="input" selector="[name='name']"/> <element name="description" type="textarea" selector="[name='description']"/> @@ -49,5 +51,11 @@ <section name="AdminCatalogPriceRuleGrid"> <element name="applyRules" type="button" selector="#apply_rules" timeout="30"/> + <element name="updateMessage" type="text" selector="//div[@class='message message-notice notice']//div[contains(.,'We found updated rules that are not applied. Please click')]"/> + <element name="ruleFilter" type="input" selector="//td[@data-column='name']/input[@name='name']"/> + <element name="resetFilter" type="button" selector="//button[@title='Reset Filter']" timeout="30"/> + <element name="search" type="button" selector="//div[@id='promo_catalog_grid']//button[@title='Search']" timeout="30"/> + <element name="selectRowByRuleName" type="text" selector="//tr[@data-role='row']//td[contains(.,'{{ruleName}}')]" parameterized="true"/> + <element name="firstRow" type="text" selector="//tr[@data-role='row']"/> </section> </sections> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateInactiveCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateInactiveCatalogPriceRuleTest.xml new file mode 100644 index 0000000000000..5223b18df4e4a --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateInactiveCatalogPriceRuleTest.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateInactiveCatalogPriceRuleTest"> + <annotations> + <stories value="Create Catalog Price Rule"/> + <title value="Create Inactive Catalog Price Rule"/> + <description value="Login as admin and create inactive catalog price Rule"/> + <testCaseId value="MC-13977"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + </before> + <after> + <actionGroup ref="AdminSearchCatalogRuleInGridActionGroup" stepKey="searchCreatedCatalogRule"> + <argument name="catalogRuleName" value="{{InactiveCatalogRule.name}}"/> + </actionGroup> + <actionGroup ref="AdminSelectCatalogRuleFromGridActionGroup" stepKey="selectCreatedCatalogRule"> + <argument name="catalogRuleName" value="{{InactiveCatalogRule.name}}"/> + </actionGroup> + <actionGroup ref="AdminDeleteCatalogRuleActionGroup" stepKey="deleteTheCatalogRule"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create Inactive Catalog Price Rule --> + <actionGroup ref="AdminCreateNewCatalogPriceRuleActionGroup" stepKey="createCatalogPriceRule"> + <argument name="catalogRule" value="InactiveCatalogRule"/> + <argument name="customerGroup" value="General"/> + </actionGroup> + + <!-- Save and Apply Rules --> + <actionGroup ref="AdminSaveAndApplyRulesActionGroup" stepKey="saveAndApplyRules"/> + + <!-- Search Catalog Rule in Grid --> + <actionGroup ref="AdminSearchCatalogRuleInGridActionGroup" stepKey="searchAndSelectCreatedCatalogRule"> + <argument name="catalogRuleName" value="{{InactiveCatalogRule.name}}"/> + </actionGroup> + + <!--Select Catalog Rule in Grid --> + <actionGroup ref="AdminSelectCatalogRuleFromGridActionGroup" stepKey="selectCreatedCatalogRule"> + <argument name="catalogRuleName" value="{{InactiveCatalogRule.name}}"/> + </actionGroup> + <grabFromCurrentUrl stepKey="catalogRuleId" regex="#\/([0-9]*)?\/$#"/> + + <!-- Assert catalog Price Rule Form --> + <actionGroup ref="AssertCatalogPriceRuleFormActionGroup" stepKey="assertCatalogRuleForm"> + <argument name="catalogRule" value="InactiveCatalogRule"/> + <argument name="status" value="Inactive"/> + <argument name="websites" value="Main Website"/> + <argument name="customerGroup" value="General"/> + </actionGroup> + + <!-- Search Catalog Rule in Grid --> + <actionGroup ref="AdminSearchCatalogRuleInGridActionGroup" stepKey="searchCreatedCatalogRule"> + <argument name="catalogRuleName" value="{{InactiveCatalogRule.name}}"/> + </actionGroup> + + <!-- Assert Catalog Rule In Grid --> + <actionGroup ref="AssertCatalogRuleInGridActionGroup" stepKey="assertCatalogRuleInGrid"> + <argument name="catalogRuleName" value="{{InactiveCatalogRule.name}}"/> + <argument name="status" value="Inactive"/> + <argument name="websites" value="Main Website"/> + <argument name="catalogRuleId" value="$catalogRuleId"/> + </actionGroup> + </test> +</tests> From 416451745a49074f981882b15f6ec9605cad3105 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Wed, 27 Mar 2019 13:51:22 -0500 Subject: [PATCH 100/585] MC-5588: When using MysqlMQ messages are always set to complete even if exception occurs --- .../_files/Magento/TestModuleMysqlMq/etc/communication.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml index f3c1705f5afbd..4d6269dbb7920 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml @@ -7,7 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Communication/etc/communication.xsd"> <topic name="demo.exception" request="Magento\TestModuleMysqlMq\Model\DataObject"/> - <topic name="test.schema.defined.by.method" schema="Magento\TestModuleMysqlMq\Model\DataObjectRepository::delayedOperation"/> + <topic name="test.schema.defined.by.method" schema="Magento\TestModuleMysqlMq\Model\DataObjectRepository::delayedOperation" is_synchronous="false"/> <topic name="demo.object.created" request="Magento\TestModuleMysqlMq\Model\DataObject"/> <topic name="demo.object.updated" request="Magento\TestModuleMysqlMq\Model\DataObject"/> <topic name="demo.object.custom.created" request="Magento\TestModuleMysqlMq\Model\DataObject"/> From 938dd362d47844045488f263b776bdb821fdb55c Mon Sep 17 00:00:00 2001 From: Denis Kopylov <dkopylov@magenius.team> Date: Wed, 27 Mar 2019 22:46:32 +0300 Subject: [PATCH 101/585] [Module Rule] Revert es6 variable diclarations --- app/code/Magento/Rule/view/adminhtml/web/rules.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Rule/view/adminhtml/web/rules.js b/app/code/Magento/Rule/view/adminhtml/web/rules.js index 202337c39da35..a15caa08cc0ae 100644 --- a/app/code/Magento/Rule/view/adminhtml/web/rules.js +++ b/app/code/Magento/Rule/view/adminhtml/web/rules.js @@ -13,6 +13,7 @@ define([ 'mage/translate', 'prototype' ], function (jQuery) { + 'use strict'; var VarienRulesForm = new Class.create(); @@ -299,14 +300,14 @@ define([ }, changeVisibilityForValueRuleParam: function(elem) { - let parsedElementId = elem.id.split('__'); - if (parsedElementId[2] != 'operator') { + var parsedElementId = elem.id.split('__'); + if (parsedElementId[2] !== 'operator') { return false; } - let valueElement = jQuery('#' + parsedElementId[0] + '__' + parsedElementId[1] + '__value'); + var valueElement = jQuery('#' + parsedElementId[0] + '__' + parsedElementId[1] + '__value'); - if(elem.value == '<=>') { + if(elem.value === '<=>') { valueElement.closest('.rule-param').hide(); } else { valueElement.closest('.rule-param').show(); From 938f8aca3db722ed89dde31bd216f5932b4f5b2b Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Thu, 28 Mar 2019 08:36:32 -0500 Subject: [PATCH 102/585] MC-4585: Convert CreateDownloadableProductEntityTest to MFTF --- ...inCreateCustomDropDownOptionsActionGroup.xml | 6 +++--- ...dableProductAndAssignItToCustomStoreTest.xml | 6 +++--- ...DownloadableProductWithCustomOptionsTest.xml | 11 ++++++----- ...wnloadableProductWithDefaultSetLinksTest.xml | 6 +++--- ...ateDownloadableProductWithGroupPriceTest.xml | 10 +++++----- ...minCreateDownloadableProductWithLinkTest.xml | 17 ++++++++--------- ...teDownloadableProductWithManageStockTest.xml | 10 +++++----- ...nloadableProductWithOutOfStockStatusTest.xml | 10 +++++----- ...eDownloadableProductWithSpecialPriceTest.xml | 3 +-- ...eateDownloadableProductWithTierPriceText.xml | 6 +----- ...roductWithoutFillingQuantityAndStockTest.xml | 13 +++++++------ ...DownloadableProductWithoutTaxClassIdTest.xml | 10 +++++----- 12 files changed, 52 insertions(+), 56 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateCustomDropDownOptionsActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateCustomDropDownOptionsActionGroup.xml index 2b2e288fcfedb..a674647a5c85b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateCustomDropDownOptionsActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateCustomDropDownOptionsActionGroup.xml @@ -11,9 +11,9 @@ <!-- ActionGroup will add a single custom option to a product You must already be on the product creation page --> <arguments> - <argument name="customOptionName"/> - <argument name="firstOption"/> - <argument name="secondOption"/> + <argument name="customOptionName" type="string"/> + <argument name="firstOption" type="entity"/> + <argument name="secondOption" type="entity"/> </arguments> <click stepKey="clickAddOptions" selector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}"/> <waitForPageLoad stepKey="waitForAddProductPageLoad"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml index a47cef13a4d49..5d7e4518525f7 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml @@ -58,16 +58,16 @@ </actionGroup> <!-- Add downloadable product to category --> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> <!-- Fill downloadable link information before the creation link --> <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> <!-- Links can be purchased separately --> - <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately"/> <!-- Add downloadable link --> - <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addDownloadableProductLink"> <argument name="link" value="downloadableLinkWithMaxDownloads"/> </actionGroup> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml index 7e19d7071fed4..0ae2c1254be01 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml @@ -52,7 +52,7 @@ </actionGroup> <!-- Add downloadable product to category --> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> <!-- Open custom option panel --> <click selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" stepKey="openCustomizableOptions"/> @@ -60,14 +60,14 @@ <!-- Create a first custom option with 2 values --> <actionGroup ref="AdminCreateCustomDropDownOptionsActionGroup" stepKey="createFirstCustomOption"> - <argument name="customOptionName" value="ProductOptionDropDown.title"/> + <argument name="customOptionName" value="{{ProductOptionDropDown.title}}"/> <argument name="firstOption" value="ProductOptionValueDropdown1"/> <argument name="secondOption" value="ProductOptionValueDropdown2"/> </actionGroup> <!-- Create a second custom option with 2 values --> <actionGroup ref="AdminCreateCustomDropDownOptionsActionGroup" stepKey="createSecondCustomOption"> - <argument name="customOptionName" value="ProductOptionDropDownWithLongValuesTitle.title"/> + <argument name="customOptionName" value="{{ProductOptionDropDownWithLongValuesTitle.title}}"/> <argument name="firstOption" value="ProductOptionValueDropdown1"/> <argument name="secondOption" value="ProductOptionValueDropdown2"/> </actionGroup> @@ -76,10 +76,10 @@ <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> <!-- Links can be purchased separately --> - <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately"/> <!-- Add downloadable link --> - <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addDownloadableProductLink"> <argument name="link" value="downloadableLinkWithMaxDownloads"/> </actionGroup> @@ -101,6 +101,7 @@ </actionGroup> <!-- Assert product custom options on product page --> + <scrollTo selector="{{StorefrontDownloadableProductSection.downloadableLinkBlock}}" stepKey="scrollToLinksInStorefront"/> <seeElement stepKey="seeFirstOptionName" selector="{{StorefrontProductInfoMainSection.customOptionLabel(ProductOptionDropDown.title)}}"/> <seeElement stepKey="seeSecondOptionName" selector="{{StorefrontProductInfoMainSection.customOptionLabel(ProductOptionDropDownWithLongValuesTitle.title)}}"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml index f78eee00fb486..eadefabb8bbcb 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml @@ -52,16 +52,16 @@ </actionGroup> <!-- Add downloadable product to category --> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> <!-- Fill downloadable link information before the creation link --> <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> <!-- Links can be purchased separately --> - <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately"/> <!-- Add first downloadable link --> - <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink"> <argument name="link" value="downloadableLinkWithMaxDownloads"/> </actionGroup> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml index a4b44280cc951..1a94ffad3ca89 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml @@ -18,6 +18,7 @@ <testCaseId value="MC-14514"/> <group value="Downloadable"/> <group value="mtf_migrated"/> + <group value="mary"/> </annotations> <before> <!-- Create category --> @@ -58,16 +59,16 @@ </actionGroup> <!-- Add downloadable product to category --> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> <!-- Fill downloadable link information before the creation link --> <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> <!-- Links can be purchased separately --> - <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately"/> <!-- Add first downloadable link --> - <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink"> <argument name="link" value="downloadableLinkWithMaxDownloads"/> </actionGroup> @@ -99,8 +100,7 @@ </actionGroup> <!-- Assert group price in storefront product page --> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.updatedPrice}}" stepKey="grabGroupPrice"/> - <assertEquals expected='${{simpleGroupPrice.price}}' expectedType="string" actual="$grabGroupPrice" stepKey="assertGroupPrice"/> + <see selector="{{StorefrontProductInfoMainSection.updatedPrice}}" userInput="$90.00" stepKey="assertGroupPrice"/> <!-- See product link in storefront product page --> <scrollTo selector="{{StorefrontDownloadableProductSection.downloadableLinkBlock}}" stepKey="scrollToLinksInStorefront"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml index 477e932c9ed74..d8bd641e84e55 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml @@ -52,16 +52,16 @@ </actionGroup> <!-- Add downloadable product to category --> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> <!-- Fill downloadable link information before the creation link --> <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> <!-- Links can be purchased separately --> - <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately"/> <!-- Add downloadable link --> - <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addDownloadableProductLink"> <argument name="link" value="downloadableLinkWithMaxDownloads"/> </actionGroup> @@ -80,16 +80,15 @@ <argument name="product" value="DownloadableProduct"/> </actionGroup> + <!-- Assert product price in storefront product page --> + <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="{{DownloadableProduct.price}}" stepKey="assertProductPrice"/> + <!-- Select product link in storefront product page--> <scrollTo selector="{{StorefrontDownloadableProductSection.downloadableLinkBlock}}" stepKey="scrollToLinks"/> <click selector="{{StorefrontDownloadableProductSection.downloadableLinkByTitle(downloadableLinkWithMaxDownloads.title)}}" stepKey="selectProductLink"/> - <!-- Assert product price in storefront product page--> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="grabProductsPrice"/> - <assertEquals expected='$51.99' expectedType="string" actual="$grabProductsPrice" message="ExpectedPrice" stepKey="assertProductPrice"/> - <!-- Add product with selected link to the cart --> - <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToCart" after="assertProductPrice"> + <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToCart"> <argument name="product" value="DownloadableProduct"/> <argument name="productCount" value="1"/> </actionGroup> @@ -97,6 +96,6 @@ <!-- Assert product price in cart --> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="openShoppingCartPage"/> <waitForPageLoad stepKey="waitForShoppingCartPageLoad"/> - <assertEquals expected='$51.99' expectedType="string" actual="$grabProductsPrice" message="ExpectedPrice" stepKey="assertProductPriceInCart"/> + <see selector="{{CheckoutCartProductSection.ProductPriceByName(DownloadableProduct.name)}}" userInput="$51.99" stepKey="assertProductPriceInCart"/> </test> </tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml index 47ff348ebaab7..3efd4b8ab276f 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml @@ -65,16 +65,16 @@ <actionGroup ref="AdminSubmitAdvancedInventoryFormActionGroup" stepKey="clickDoneBtn"/> <!-- Add downloadable product to category --> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> <!-- Fill downloadable link information before the creation link --> <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> <!-- Links can be purchased separately --> - <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately"/> <!-- Add first downloadable link --> - <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink"> <argument name="link" value="downloadableLinkWithMaxDownloads"/> </actionGroup> @@ -97,8 +97,8 @@ <!-- Assert downloadable links in product form --> <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> - <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> - <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + <seeInField selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" userInput="{{downloadableLinkWithMaxDownloads.title}}" stepKey="seeFirstLinkTitle"/> + <seeInField selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" userInput="{{downloadableLink.title}}" stepKey="seeSecondLinkTitle"/> <!-- Assert product is out of stock in store front --> <amOnPage url="{{DownloadableProduct.urlKey}}.html" stepKey="navigateToProductPage"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml index 6f369c00f25ac..07f7c40bb3560 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml @@ -52,16 +52,16 @@ </actionGroup> <!-- Add downloadable product to category --> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> <!-- Fill downloadable link information before the creation link --> <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> <!-- Links can be purchased separately --> - <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately"/> <!-- Add first downloadable link --> - <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink"> <argument name="link" value="downloadableLinkWithMaxDownloads"/> </actionGroup> @@ -89,7 +89,7 @@ <!-- Assert downloadable links in product form --> <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> - <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> - <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + <seeInField selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" userInput="{{downloadableLinkWithMaxDownloads.title}}" stepKey="seeFirstLinkTitle"/> + <seeInField selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" userInput="{{downloadableLink.title}}" stepKey="seeSecondLinkTitle"/> </test> </tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml index 267b6bb6f883a..796b62084a272 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml @@ -30,7 +30,6 @@ <remove keyForRemoval="assertGroupPrice"/> <!-- Assert special price in storefront product page --> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.specialPriceValue}}" stepKey="grabSpecialPrice" after="AssertProductInStorefrontProductPage"/> - <assertEquals expected='${{specialProductPrice.price}}' expectedType="string" actual="$grabSpecialPrice" stepKey="assertSpecialPrice"/> + <see selector="{{StorefrontProductInfoMainSection.specialPriceValue}}" userInput="$99.99" stepKey="assertSpecialPrice"/> </test> </tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml index a34393b5f8e92..684d0fa766e60 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml @@ -31,10 +31,6 @@ <remove keyForRemoval="assertGroupPrice"/> <!-- Assert tier price in storefront product page --> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.tierPriceText}}" stepKey="tierPriceText" after="AssertProductInStorefrontProductPage"/> - <assertEquals stepKey="assertTierPriceTextOnProductPage"> - <expectedResult type="string">Buy {{tierProductPrice.quantity}} for ${{tierProductPrice.price}} each and save 27%</expectedResult> - <actualResult type="variable">tierPriceText</actualResult> - </assertEquals> + <see selector="{{StorefrontProductInfoMainSection.tierPriceText}}" userInput="Buy {{tierProductPrice.quantity}} for ${{tierProductPrice.price}} each and save 27%" stepKey="assertTierPriceText"/> </test> </tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml index 5948c19cb8026..f326a047c32b5 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml @@ -51,19 +51,19 @@ <argument name="product" value="DownloadableProduct"/> </actionGroup> - <clearField selector="{{AdminProductFormSection.productQuantity}}" stepKey="clearProductQty" after="fillDownloadableProductForm"/> + <clearField selector="{{AdminProductFormSection.productQuantity}}" stepKey="clearProductQty"/> <!-- Add downloadable product to category --> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillDownloadableProductForm"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> <!-- Fill downloadable link information before the creation link --> <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> <!-- Links can be purchased separately --> - <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately"/> <!-- Add first downloadable link --> - <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink"> <argument name="link" value="downloadableLinkWithMaxDownloads"/> </actionGroup> @@ -86,8 +86,9 @@ <!-- Assert downloadable links in product form --> <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> - <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> - <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + <seeInField selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" userInput="{{downloadableLinkWithMaxDownloads.title}}" stepKey="seeFirstLinkTitle"/> + <seeInField selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" userInput="{{downloadableLink.title}}" stepKey="seeSecondLinkTitle"/> + <!-- See stock status--> <seeOptionIsSelected selector="{{AdminProductFormSection.productStockStatus}}" userInput="Out of Stock" stepKey="seeStockStatus"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml index da691b207cac2..8e33a082d0ba2 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml @@ -55,16 +55,16 @@ <selectOption selector="{{AdminProductFormBundleSection.taxClassDropDown}}" userInput="None" stepKey="taxClassDropDown"/> <!-- Add downloadable product to category --> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="taxClassDropDown"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> <!-- Fill downloadable link information before the creation link --> <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> <!-- Links can be purchased separately --> - <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately" after="addDownloadableLinkInformation"/> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately"/> <!-- Add first downloadable link --> - <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink" after="checkOptionPurchaseSeparately"> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink"> <argument name="link" value="downloadableLinkWithMaxDownloads"/> </actionGroup> @@ -87,8 +87,8 @@ <!-- Assert downloadable links in product form --> <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> - <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> - <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + <seeInField selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" userInput="{{downloadableLinkWithMaxDownloads.title}}" stepKey="seeFirstLinkTitle"/> + <seeInField selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" userInput="{{downloadableLink.title}}" stepKey="seeSecondLinkTitle"/> <!-- Assert product in storefront product page --> <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPage" stepKey="AssertProductInStorefrontProductPage"> From 4cdd3b88b3c35eaddfc19be5282ec062ddfe6b52 Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Thu, 28 Mar 2019 12:44:37 -0500 Subject: [PATCH 103/585] MC-4788: Convert DeleteSalesRuleEntityTest to MFTF --- .../Section/StorefrontMiniCartSection.xml | 3 + .../AdminCreateCartPriceRuleActionGroup.xml | 6 +- ...CartPriceRuleActionsSectionActionGroup.xml | 22 +++++++ ...tPriceRuleConditionsSectionActionGroup.xml | 36 +++++++++++ ...eCartPriceRuleLabelsSectionActionGroup.xml | 18 ++++++ ...artPriceRuleRuleInfoSectionActionGroup.xml | 31 +++++++++ .../AdminFilterCartPriceRuleActionGroup.xml | 7 +- ...PriceRuleSuccessSaveMessageActionGroup.xml | 14 ++++ ...sertStorefrontMiniCartItemsActionGroup.xml | 24 +++++++ .../StorefrontAddToTheCartActionGroup.xml | 16 +++++ .../StorefrontClickOnMiniCartActionGroup.xml | 16 +++++ .../Test/Mftf/Data/SalesRuleData.xml | 49 +++++++++++++- .../AdminCartPriceRulesFormSection.xml | 17 ++++- .../Section/AdminCartPriceRulesSection.xml | 1 + ...exConditionsAndVerifyDeleteMessageTest.xml | 58 +++++++++++++++++ ...PercentPriceAndVerifyDeleteMessageTest.xml | 44 +++++++++++++ ...iveSalesRuleAndVerifyDeleteMessageTest.xml | 64 +++++++++++++++++++ 17 files changed, 422 insertions(+), 4 deletions(-) create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleRuleInfoSectionActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCartPriceRuleSuccessSaveMessageActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithPercentPriceAndVerifyDeleteMessageTest.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml index 38c88bf4f80bb..fec06f226d45e 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml @@ -33,5 +33,8 @@ <element name="subtotal" type="text" selector="//tr[@class='totals sub']//td[@class='amount']/span"/> <element name="emptyCart" type="text" selector=".counter.qty.empty"/> <element name="minicartContent" type="block" selector="#minicart-content-wrapper"/> + <element name="productQuantity" type="input" selector="//*[@id='mini-cart']//a[contains(text(),'{{productName}}')]/../..//div[@class='details-qty qty']//input[@data-item-qty='{{qty}}']" parameterized="true"/> + <element name="productImage" type="text" selector="//ol[@id='mini-cart']//img[@class='product-image-photo']"/> + <element name="productSubTotal" type="text" selector="//div[@class='subtotal']//span/span[@class='price']"/> </section> </sections> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml index cc165e0b5dc96..544200e5e5123 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml @@ -91,4 +91,8 @@ <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="Second Website" stepKey="selectWebsites"/> </actionGroup> -</actionGroups> + + <actionGroup name="AdminInactiveCartPriceRuleActionGroup" extends="AdminCreateCartPriceRuleActionGroup"> + <click selector="{{AdminCartPriceRulesFormSection.active}}" stepKey="clickActiveToDisable" after="fillRuleName"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml new file mode 100644 index 0000000000000..3d2ff88840144 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCartPriceRuleActionsSectionActionGroup"> + <arguments> + <argument name="ruleName"/> + </arguments> + <click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{ruleName.simple_action}}" stepKey="selectActionType"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{ruleName.discount_amount}}" stepKey="fillDiscountAmount"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountStep}}" userInput="{{ruleName.discount_step}}" stepKey="fillDiscountStep"/> + <click selector="{{AdminCartPriceRulesFormSection.applyToShippingAmount}}" stepKey="clickApplyToShipping"/> + <click selector="{{AdminCartPriceRulesFormSection.discardSubsequentRules}}" stepKey="clickDiscardSubsequentRules"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{ruleName.simple_free_shipping}}" stepKey="selectForMatchingItemsOnly"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml new file mode 100644 index 0000000000000..085a0ab33440c --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCartPriceRuleConditionsSectionActionGroup"> + <arguments> + <argument name="ruleName"/> + <argument name="condition1" type="string"/> + <argument name="condition2" type="string"/> + <argument name="condition3" type="string"/> + </arguments> + <click selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="clickToExpandConditions"/> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewCondition"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition1}}" stepKey="selectCondition1"/> + <waitForPageLoad stepKey="waitForConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{ruleName.subtotal}}" stepKey="fillSubtotalParameter"/> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewConditionButton"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition2}}" stepKey="selectCondition2"/> + <waitForPageLoad stepKey="waitForSecondConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickTheEllipsis"/> + <click selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" stepKey="clickSelectCountryDropdown"/> + <waitForPageLoad stepKey="waitForDropdownLoad"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" userInput="{{ruleName.shippingCountry}}" stepKey="fillShippingCountryParameter"/> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickOnNewCondition"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition3}}" stepKey="selectCondition3"/> + <waitForPageLoad stepKey="waitForThirdConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickOnEllipsis"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--3')}}" userInput="{{ruleName.shippingPostcode}}" stepKey="fillShippingPostcodeParameter"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml new file mode 100644 index 0000000000000..49d5900a3a45b --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCartPriceRuleLabelsSectionActionGroup"> + <arguments> + <argument name="ruleName"/> + </arguments> + <click selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="clickToExpandLabels"/> + <fillField selector="{{AdminCartPriceRulesFormSection.defaultRuleLabelAllStoreViews}}" userInput="{{ruleName.defaultRuleLabelAllStoreViews}}" stepKey="fillDefaultRuleLabelAllStoreViews"/> + <fillField selector="{{AdminCartPriceRulesFormSection.defaultStoreView}}" userInput="{{ruleName.defaultStoreView}}" stepKey="fillDefaultStoreView"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleRuleInfoSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleRuleInfoSectionActionGroup.xml new file mode 100644 index 0000000000000..591dfbfb95536 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleRuleInfoSectionActionGroup.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCartPriceRuleRuleInfoSectionActionGroup"> + <arguments> + <argument name="ruleName"/> + </arguments> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForPriceList"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{ruleName.name}}" stepKey="fillRuleName"/> + <fillField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{ruleName.description}}" stepKey="fillDescription"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{ruleName.websites}}" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" parameterArray="[{{ruleName.customerGroups}}]" stepKey="selectCustomerGroup"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{ruleName.coupon_type}}" stepKey="selectCouponType"/> + <waitForElementVisible selector="{{AdminCartPriceRulesFormSection.couponCode}}" stepKey="waitForElementVisible"/> + <fillField selector="{{AdminCartPriceRulesFormSection.couponCode}}" userInput="{{ruleName.coupon_code}}" stepKey="fillCouponCode"/> + <fillField selector="{{AdminCartPriceRulesFormSection.userPerCoupon}}" userInput="{{ruleName.uses_per_coupon}}" stepKey="fillUsesPerCoupon"/> + <fillField selector="{{AdminCartPriceRulesFormSection.userPerCustomer}}" userInput="{{ruleName.uses_per_customer}}" stepKey="fillUsesPerCustomer"/> + <generateDate date="+1 minute" format="m/d/Y" stepKey="startDateTime"/> + <fillField selector="{{AdminCartPriceRulesFormSection.fromDate}}" userInput="{$startDateTime}" stepKey="fillStartDate"/> + <fillField selector="{{AdminCartPriceRulesFormSection.priority}}" userInput="{{ruleName.sort_order}}" stepKey="fillPriority"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.publicInRSSFeed}}" dependentSelector="{{AdminCartPriceRulesFormSection.publicInRSSFeed}}" visible="false" stepKey="clickOnlyIfRSSIsDisabled"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminFilterCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminFilterCartPriceRuleActionGroup.xml index 35e1bee0952cf..7a3a20e603255 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminFilterCartPriceRuleActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminFilterCartPriceRuleActionGroup.xml @@ -18,4 +18,9 @@ <click selector="{{AdminCartPriceRulesSection.searchButton}}" stepKey="doFilter"/> <click selector="{{AdminCartPriceRulesSection.rowByIndex('1')}}" stepKey="goToEditRulePage"/> </actionGroup> -</actionGroups> + <actionGroup name="AdminCartPriceRuleNotInGridActionGroup" extends="AdminFilterCartPriceRuleActionGroup"> + <remove keyForRemoval="goToEditRulePage"/> + <waitForPageLoad stepKey="waitForStoreToLoad"/> + <see selector="{{AdminCartPriceRulesSection.emptyText}}" userInput="We couldn't find any records." stepKey="seeAssertCartPriceRuleIsNotPresentedInGrid"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCartPriceRuleSuccessSaveMessageActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCartPriceRuleSuccessSaveMessageActionGroup.xml new file mode 100644 index 0000000000000..8fe0250307c6a --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCartPriceRuleSuccessSaveMessageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCartPriceRuleSuccessSaveMessageActionGroup"> + <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> + <see selector="{{AdminCartPriceRulesFormSection.successMessage}}" userInput="You saved the rule." stepKey="seeAssertSuccessSaveMessage"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml new file mode 100644 index 0000000000000..f9c9a9fd357ee --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontMiniCartItemsActionGroup"> + <arguments> + <argument name="productName" type="string"/> + <argument name="productPrice" type="string"/> + <argument name="cartSubtotal" type="string"/> + <argument name="qty" type="string"/> + </arguments> + <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{productName}}" stepKey="seeProductNameInMiniCart"/> + <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{productPrice}}" stepKey="seeProductPriceInMiniCart"/> + <seeElement selector="{{StorefrontMinicartSection.goToCheckout}}" stepKey="seeCheckOutButtonInMiniCart"/> + <seeElement selector="{{StorefrontMinicartSection.productQuantity(productName, qty)}}" stepKey="seeProductQuantity1"/> + <seeElement selector="{{StorefrontMinicartSection.productImage}}" stepKey="seeProductImage"/> + <see selector="{{StorefrontMinicartSection.productSubTotal}}" userInput="{{cartSubtotal}}" stepKey="seeSubTotal"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml new file mode 100644 index 0000000000000..fa474194635e6 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAddToTheCartActionGroup"> + <waitForPageLoad stepKey="waitForPageLoad"/> + <scrollTo selector="{{StorefrontProductActionSection.addToCart}}" stepKey="scrollToAddToCartButton"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml new file mode 100644 index 0000000000000..59028ee1a17b5 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontClickOnMiniCartActionGroup"> + <scrollToTopOfPage stepKey="scrollToTheTopOfThePage"/> + <waitForElementVisible selector="{{StorefrontMinicartSection.showCart}}" stepKey="waitForElementToBeVisible"/> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml index 8f6e63534b0ca..278991967418a 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml @@ -193,4 +193,51 @@ <entity name="SalesRuleNoCouponWithFixedDiscount" extends="ApiCartRule"> <data key="simple_action">by_fixed</data> </entity> -</entities> + <entity name="ActiveSalesRuleWithPercentPriceDiscountCoupon"> + <data key="name" unique="suffix">Cart Price Rule with Specific Coupon</data> + <data key="description">Description for Cart Price Rule</data> + <data key="is_active">Yes</data> + <data key="websites">Main Website</data> + <data key="customerGroups">'NOT LOGGED IN'</data> + <data key="coupon_type">Specific Coupon</data> + <data key="coupon_code" unique="suffix">123-abc-ABC-987</data> + <data key="apply">Percent of product price discount</data> + <data key="discountAmount">50</data> + <data key="defaultRuleLabelAllStoreViews">Cart Price Rule with Specific Coupon</data> + <data key="defaultStoreView">Cart Price Rule with Specific Coupon</data> + </entity> + <entity name="ActiveSalesRuleWithComplexConditions"> + <data key="name" unique="suffix">Cart Price Rule with complex conditions</data> + <data key="description">Cart Price Rule with complex conditions</data> + <data key="is_active">Yes</data> + <data key="websites">Main Website</data> + <data key="customerGroups">'NOT LOGGED IN', 'General', 'Wholesale', 'Retailer'</data> + <data key="coupon_type">Specific Coupon</data> + <data key="coupon_code" unique="suffix">123-abc-ABC-987</data> + <data key="uses_per_coupon">13</data> + <data key="uses_per_customer">63</data> + <data key="sort_order">1</data> + <data key="is_rss">Yes</data> + <data key="subtotal">300</data> + <data key="shippingCountry">US</data> + <data key="shippingPostcode">123456789a</data> + <data key="simple_action">Percent of product price discount</data> + <data key="discount_amount">50</data> + <data key="discount_step">0</data> + <data key="apply_to_shipping">Yes</data> + <data key="stop_rules_processing">Yes</data> + <data key="simple_free_shipping">For matching items only</data> + <data key="defaultRuleLabelAllStoreViews">Cart Price Rule with complex conditions</data> + <data key="defaultStoreView">Cart Price Rule with complex conditions</data> + </entity> + <entity name="InactiveSalesRule"> + <data key="name" unique="suffix">Inactive Cart Price Rule</data> + <data key="description">Inactive Cart Price Rule</data> + <data key="is_active">0</data> + <data key="websites">Main Website</data> + <data key="customerGroups">'NOT LOGGED IN'</data> + <data key="coupon_type">No Coupon</data> + <data key="apply">Percent of product price discount</data> + <data key="discountAmount">50</data> + </entity> +</entities> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml index c8da82407457d..88be49d7f96ca 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml @@ -16,6 +16,8 @@ <!-- Rule Information (the main form on the page) --> <element name="ruleInformationHeader" type="button" selector="div[data-index='rule_information']" timeout="30"/> <element name="ruleName" type="input" selector="input[name='name']"/> + <element name="description" type="textarea" selector="//div[@class='admin__field-control']/textarea[@name='description']"/> + <element name="active" type="checkbox" selector="//div[@class='admin__actions-switch']/input[@name='is_active']/../label"/> <element name="websites" type="multiselect" selector="select[name='website_ids']"/> <element name="customerGroups" type="multiselect" selector="select[name='customer_group_ids']"/> <element name="coupon" type="select" selector="select[name='coupon_type']"/> @@ -26,6 +28,7 @@ <element name="userPerCoupon" type="input" selector="//input[@name='uses_per_coupon']"/> <element name="userPerCustomer" type="input" selector="//input[@name='uses_per_customer']"/> <element name="priority" type="input" selector="//*[@name='sort_order']"/> + <element name="publicInRSSFeed" type="checkbox" selector="//div[@class='admin__actions-switch']/input[@name='is_rss']/../label"/> <!-- Conditions sub-form --> <element name="conditionsHeader" type="button" selector="div[data-index='conditions']" timeout="30"/> @@ -39,6 +42,11 @@ <element name="ruleParameterInput" type="input" selector="rule[conditions][{{arg}}][value]" parameterized="true"/> <element name="openChooser" type="button" selector="//label[@for='conditions__{{arg}}__value']" parameterized="true"/> <element name="categoryCheckbox" type="checkbox" selector="//span[contains(text(), '{{arg}}')]/parent::a/preceding-sibling::input[@type='checkbox']" parameterized="true"/> + <element name="newCondition" type="button" selector=".rule-param.rule-param-new-child" timeout="30"/> + <element name="conditionSelect" type="select" selector="select[name='rule[conditions][1][new_child]']"/> + <element name="targetEllipsis" type="input" selector="//ul[contains(@id, 'conditions')]//a[.='...']"/> + <element name="ruleFieldByIndex" type="input" selector="[id='conditions__{{index}}__value']" parameterized="true"/> + <element name="selectCountryDropdown" type="select" selector="(//*[contains(@value,'country_id')]/..//select)[last()]"/> <!-- Actions sub-form --> <element name="actionsTab" type="text" selector="//div[@data-index='actions']//span[contains(.,'Actions')][1]"/> @@ -59,9 +67,16 @@ <element name="applyDiscountToShippingLabel" type="checkbox" selector="input[name='apply_to_shipping']+label"/> <element name="discountAmount" type="input" selector="input[name='discount_amount']"/> <element name="discountStep" type="input" selector="input[name='discount_step']"/> + <element name="applyToShippingAmount" type="checkbox" selector="//div[@class='admin__actions-switch']/input[@name='apply_to_shipping']/../label"/> + <element name="discardSubsequentRules" type="checkbox" selector="//div[@class='admin__actions-switch']/input[@name='stop_rules_processing']/../label"/> <element name="addRewardPoints" type="input" selector="input[name='extension_attributes[reward_points_delta]']"/> <element name="freeShipping" type="select" selector="//select[@name='simple_free_shipping']"/> + <!-- Labels sub-form --> + <element name="labelsHeader" type="button" selector="div[data-index='labels']" timeout="30"/> + <element name="defaultRuleLabelAllStoreViews" type="input" selector="input[name='store_labels[0]']"/> + <element name="defaultStoreView" type="input" selector="input[name='store_labels[1]']"/> + <!-- Manage Coupon Codes sub-form --> <element name="manageCouponCodesHeader" type="button" selector="div[data-index='manage_coupon_codes']" timeout="30"/> <element name="successMessage" type="text" selector="div.message.message-success.success"/> @@ -69,4 +84,4 @@ <element name="generateCouponsButton" type="button" selector="#coupons_generate_button" timeout="30"/> <element name="generatedCouponByIndex" type="text" selector="#couponCodesGrid_table > tbody > tr:nth-child({{var}}) > td.col-code" parameterized="true"/> </section> -</sections> +</sections> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml index 14d3a734408db..60bf3d63e7e54 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml @@ -18,5 +18,6 @@ <element name="rulesRow" type="text" selector="//tr[@data-role='row']"/> <element name="pageCurrent" type="text" selector="//label[@for='promo_quote_grid_page-current']"/> <element name="totalCount" type="text" selector="span[data-ui-id*='grid-total-count']"/> + <element name="emptyText" type="text" selector="//tr[@class='data-grid-tr-no-data even']/td"/> </section> </sections> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml new file mode 100644 index 0000000000000..d1852590d7826 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest"> + <annotations> + <stories value="Delete Sales Rule"/> + <title value="Delete Active Sales Rule With Complex Conditions And Verify Delete Message"/> + <description value="Test log in to Cart Price Rule and Delete Active Sales Rule With Complex Conditions Test"/> + <testCaseId value="MC-15450"/> + <severity value="CRITICAL"/> + <group value="salesRule"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!--Create active cart price rule--> + <actionGroup ref="AdminCreateCartPriceRuleRuleInfoSectionActionGroup" stepKey="createActiveCartPriceRuleRuleInfoSection"> + <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> + </actionGroup> + <!--Fill values for Condition Section--> + <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionActionGroup" stepKey="createActiveCartPriceRuleConditionsSection"> + <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> + <argument name="condition1" value="Subtotal"/> + <argument name="condition2" value="Shipping Country"/> + <argument name="condition3" value="Shipping Postcode"/> + </actionGroup> + <!--Fill values for Action Section--> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> + <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> + </actionGroup> + <!--Fill values for Labels Section--> + <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> + <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> + </actionGroup> + <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="assertVerifyCartPriceRuleSuccessSaveMessage"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Delete active cart price rule--> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteActiveCartPriceRule"> + <argument name="ruleName" value="{{ActiveSalesRuleWithComplexConditions.name}}"/> + </actionGroup> + + <!--Go to grid and verify AssertCartPriceRuleIsNotPresentedInGrid--> + <actionGroup ref="AdminCartPriceRuleNotInGridActionGroup" stepKey="searchAndVerifyActiveCartPriceRuleNotInGrid"> + <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions.name"/> + </actionGroup> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithPercentPriceAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithPercentPriceAndVerifyDeleteMessageTest.xml new file mode 100644 index 0000000000000..41e4221a2c37f --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithPercentPriceAndVerifyDeleteMessageTest.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminDeleteActiveSalesRuleWithPercentPriceAndVerifyDeleteMessageTest"> + <annotations> + <stories value="Delete Sales Rule"/> + <title value="Delete Active Sales Rule With Percent Price And Verify Delete Message"/> + <description value="Test log in to Cart Price Rule and Delete Active Sales Rule Test"/> + <testCaseId value="MC-15449"/> + <severity value="CRITICAL"/> + <group value="salesRule"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!--Create active cart price rule--> + <actionGroup ref="AdminCreateCartPriceRuleWithCouponCode" stepKey="createActiveCartPriceRule"> + <argument name="ruleName" value="ActiveSalesRuleWithPercentPriceDiscountCoupon"/> + <argument name="couponCode" value="ActiveSalesRuleWithPercentPriceDiscountCoupon.coupon_code"/> + </actionGroup> + </before> + <after> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Delete active cart price rule--> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteActiveCartPriceRule"> + <argument name="ruleName" value="{{ActiveSalesRuleWithPercentPriceDiscountCoupon.name}}"/> + </actionGroup> + + <!--Go to grid and verify AssertCartPriceRuleIsNotPresentedInGrid--> + <actionGroup ref="AdminCartPriceRuleNotInGridActionGroup" stepKey="searchAndVerifyActiveCartPriceRuleNotInGrid"> + <argument name="ruleName" value="ActiveSalesRuleWithPercentPriceDiscountCoupon.name"/> + </actionGroup> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml new file mode 100644 index 0000000000000..a46c98a47e8a5 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest"> + <annotations> + <stories value="Delete Sales Rule"/> + <title value="Delete Inactive Sales Rule And Verify Delete Message"/> + <description value="Test log in to Cart Price Rule and Delete Inactive Sales Rule Test"/> + <testCaseId value="MC-15451"/> + <severity value="CRITICAL"/> + <group value="salesRule"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="defaultSimpleProduct" stepKey="initialSimpleProduct"/> + <!--Create inactive cart price rule--> + <actionGroup ref="AdminInactiveCartPriceRuleActionGroup" stepKey="createInactiveCartPriceRule"> + <argument name="ruleName" value="InactiveSalesRule"/> + </actionGroup> + </before> + <after> + <deleteData createDataKey="initialSimpleProduct" stepKey="deleteProduct"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Delete inactive cart price rule--> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteInactiveCartPriceRule"> + <argument name="ruleName" value="{{InactiveSalesRule.name}}"/> + </actionGroup> + + <!--Go to grid and verify AssertCartPriceRuleIsNotPresentedInGrid--> + <actionGroup ref="AdminCartPriceRuleNotInGridActionGroup" stepKey="searchAndVerifyInactiveCartPriceRuleNotInGrid"> + <argument name="ruleName" value="InactiveSalesRule.name"/> + </actionGroup> + + <!--Verify customer don't see updated virtual product link on category page --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct1PageAndVerifyProduct"> + <argument name="product" value="$$initialSimpleProduct$$"/> + </actionGroup> + + <!--Click on Add To Cart button--> + <actionGroup ref="StorefrontAddToTheCartActionGroup" stepKey="clickOnAddToCartButton"/> + + <!--Click on mini cart--> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> + + <!--Open mini cart and verify Shopping cart subtotal equals to grand total - price rule has not been applied.--> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="verifyCartSubtotalEqualsGrandTotal"> + <argument name="productName" value="$$initialSimpleProduct.name$$"/> + <argument name="productPrice" value="$560.00"/> + <argument name="cartSubtotal" value="$560.00" /> + <argument name="qty" value="1"/> + </actionGroup> + </test> +</tests> \ No newline at end of file From 9f85367d6b7ca62851542ba01b1c8ffa1b1b66e3 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Thu, 28 Mar 2019 15:58:29 -0500 Subject: [PATCH 104/585] MC-4585: Convert CreateDownloadableProductEntityTest to MFTF --- .../AdminAddAdvancedPricingToTheProductActionGroup.xml | 8 ++++++++ .../AdminCreateDownloadableProductWithGroupPriceTest.xml | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddAdvancedPricingToTheProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddAdvancedPricingToTheProductActionGroup.xml index 14ff6640f1274..a8d2f7d9860f3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddAdvancedPricingToTheProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddAdvancedPricingToTheProductActionGroup.xml @@ -23,4 +23,12 @@ <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput(index)}}" userInput="{{groupPrice.price}}" stepKey="selectProductTierPriceFixedPrice"/> <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDoneButton"/> </actionGroup> + + <!-- Customer group is selected in different way for B2B --> + <actionGroup name="AdminAddAdvancedPricingToTheProductExtendedActionGroup" extends="AdminAddAdvancedPricingToTheProductActionGroup"> + <remove keyForRemoval="selectProductTierPriceCustomerGroupInput"/> + <click selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect(index)}}" stepKey="clickProductTierPriceCustGroupSelect" after="selectProductTierPriceWebsiteInput"/> + <waitForElement selector="{{AdminProductFormAdvancedPricingSection.productTierPriceGroupOrCatalogOption(groupPrice.customer_group)}}" time="30" stepKey="waitProductTierPriceGroupOrCatalogOption" after="clickProductTierPriceCustGroupSelect"/> + <click selector="{{AdminProductFormAdvancedPricingSection.productTierPriceGroupOrCatalogOption(groupPrice.customer_group)}}" stepKey="clickAllGroupsOption" after="waitProductTierPriceGroupOrCatalogOption"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml index 1a94ffad3ca89..8bd4305e6b358 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml @@ -18,7 +18,6 @@ <testCaseId value="MC-14514"/> <group value="Downloadable"/> <group value="mtf_migrated"/> - <group value="mary"/> </annotations> <before> <!-- Create category --> From 103c28be56300b235582504bbeb7a1325ef95eb7 Mon Sep 17 00:00:00 2001 From: Szymon Dudzik <szymon.dudzik@ageno.pl> Date: Thu, 28 Mar 2019 22:09:05 +0100 Subject: [PATCH 105/585] Fixes issue with non existing file, when adding image to gallery with move option. Fix for #21978 --- app/code/Magento/Catalog/Model/Product/Gallery/Processor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php index 0912324745360..21503c1c8a687 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php @@ -196,7 +196,7 @@ public function addImage( $mediaGalleryData = $product->getData($attrCode); $position = 0; - $absoluteFilePath = $this->mediaDirectory->getAbsolutePath($file); + $absoluteFilePath = $this->mediaDirectory->getAbsolutePath($destinationFile); $imageMimeType = $this->mime->getMimeType($absoluteFilePath); $imageContent = $this->mediaDirectory->readFile($absoluteFilePath); $imageBase64 = base64_encode($imageContent); From fb4c3b622a86aec63133b716aa6319c3d6a79a6a Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Fri, 29 Mar 2019 10:11:59 +0300 Subject: [PATCH 106/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Gateway URL changed to https; --- app/code/Magento/Ups/Model/Carrier.php | 2 +- app/code/Magento/Ups/etc/config.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 8c60f5a53a2d9..75ce0c3014efa 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -77,7 +77,7 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface * * @var string */ - protected $_defaultCgiGatewayUrl = 'http://www.ups.com:80/using/services/rave/qcostcgi.cgi'; + protected $_defaultCgiGatewayUrl = 'https://www.ups.com:80/using/services/rave/qcostcgi.cgi'; /** * Test urls for shipment diff --git a/app/code/Magento/Ups/etc/config.xml b/app/code/Magento/Ups/etc/config.xml index e2ac1c6d6c443..791b325c65e3f 100644 --- a/app/code/Magento/Ups/etc/config.xml +++ b/app/code/Magento/Ups/etc/config.xml @@ -19,7 +19,7 @@ <cutoff_cost /> <dest_type>RES</dest_type> <free_method>GND</free_method> - <gateway_url>http://www.ups.com/using/services/rave/qcostcgi.cgi</gateway_url> + <gateway_url>https://www.ups.com/using/services/rave/qcostcgi.cgi</gateway_url> <gateway_xml_url>https://onlinetools.ups.com/ups.app/xml/Rate</gateway_xml_url> <handling>0</handling> <model>Magento\Ups\Model\Carrier</model> From bbe71ef43062429cd3f235ad885cc3a996e7628d Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Fri, 29 Mar 2019 13:44:55 +0200 Subject: [PATCH 107/585] refactoring --- .../Magento/CatalogSearch/Model/Layer/Filter/Decimal.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php index a5e9f9ef0a331..e9fb1070fedd5 100644 --- a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php +++ b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php @@ -111,12 +111,9 @@ protected function _getItemsData() $from = ''; } if ($to == '*') { - $to = ''; + $to = null; } - $label = $this->renderRangeLabel( - empty($from) ? 0 : $from, - empty($to) ? $to : $to - ); + $label = $this->renderRangeLabel(empty($from) ? 0 : $from, $to); $value = $from . '-' . $to; $data[] = [ @@ -141,7 +138,7 @@ protected function _getItemsData() protected function renderRangeLabel($fromPrice, $toPrice) { $formattedFromPrice = $this->priceCurrency->format($fromPrice); - if ($toPrice === '') { + if ($toPrice === null) { return __('%1 and above', $formattedFromPrice); } else { if ($fromPrice != $toPrice) { From 2de902a700424e0c41d7386e806a4d2e23282ccb Mon Sep 17 00:00:00 2001 From: Vishal Sutariya <vishalsutariya7037@gmail.com> Date: Fri, 29 Mar 2019 17:35:32 +0530 Subject: [PATCH 108/585] Fixed typo error in sales grid at admin --- .../view/adminhtml/ui_component/sales_order_creditmemo_grid.xml | 2 +- .../view/adminhtml/ui_component/sales_order_shipment_grid.xml | 2 +- .../adminhtml/ui_component/sales_order_view_creditmemo_grid.xml | 2 +- .../adminhtml/ui_component/sales_order_view_shipment_grid.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml index f36a7d2821f7a..e0b7dae8fdb1a 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml @@ -92,7 +92,7 @@ <column name="order_increment_id"> <settings> <filter>text</filter> - <label translate="true">Order</label> + <label translate="true">Order #</label> </settings> </column> <column name="order_created_at" class="Magento\Ui\Component\Listing\Columns\Date" component="Magento_Ui/js/grid/columns/date"> diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml index e0495e62d5ce1..9e02c31a20635 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml @@ -100,7 +100,7 @@ <column name="order_increment_id"> <settings> <filter>text</filter> - <label translate="true">Order</label> + <label translate="true">Order #</label> </settings> </column> <column name="order_created_at" class="Magento\Ui\Component\Listing\Columns\Date" component="Magento_Ui/js/grid/columns/date"> diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml index 10b7b1c028c66..cf536c27a0ac3 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml @@ -105,7 +105,7 @@ <column name="order_increment_id"> <settings> <filter>text</filter> - <label translate="true">Order</label> + <label translate="true">Order #</label> </settings> </column> <column name="order_created_at" class="Magento\Ui\Component\Listing\Columns\Date" component="Magento_Ui/js/grid/columns/date"> diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml index 6db77a79b8c14..5f8ebde290664 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml @@ -106,7 +106,7 @@ <column name="order_increment_id"> <settings> <filter>textRange</filter> - <label translate="true">Order</label> + <label translate="true">Order #</label> </settings> </column> <column name="order_created_at" class="Magento\Ui\Component\Listing\Columns\Date" component="Magento_Ui/js/grid/columns/date"> From c7e1defe63e859c2a1e19bcf736234533b3fa21b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Me=CC=81ndez=20Calzada?= <gonzalo.mendez@interactiv4.com> Date: Fri, 29 Mar 2019 14:18:26 +0100 Subject: [PATCH 109/585] Add multibyte support for attributeSource getOptionId method --- .../Attribute/Source/AbstractSource.php | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php index 36ad026029056..0e547e0887c30 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php @@ -88,7 +88,7 @@ public function getOptionText($value) public function getOptionId($value) { foreach ($this->getAllOptions() as $option) { - if (strcasecmp($option['label'], $value) == 0 || $option['value'] == $value) { + if ($this->mbStrcasecmp($option['label'], $value) == 0 || $option['value'] == $value) { return $option['value']; } } @@ -166,4 +166,22 @@ public function toOptionArray() { return $this->getAllOptions(); } + + /** + * Multibyte support strcasecmp function version + * @param string $str1 + * @param string $str2 + * @param null|string $encoding + * @return int|\\lt + */ + private function mbStrcasecmp($str1, $str2, $encoding = null) + { + if (null === $encoding) { + $encoding = mb_internal_encoding(); + } + return strcmp( + mb_strtoupper($str1, $encoding), + mb_strtoupper($str2, $encoding) + ); + } } From 3e5772b1360fe034765185ade13b263d8550848c Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Fri, 29 Mar 2019 10:06:22 -0500 Subject: [PATCH 110/585] MC-4585: Convert CreateDownloadableProductEntityTest to MFTF --- ...ownloadableProductWithSpecialPriceTest.xml | 81 ++++++++++++++++++- ...teDownloadableProductWithTierPriceText.xml | 1 - 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml index 796b62084a272..275e72b2ec8cb 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml @@ -8,7 +8,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminCreateDownloadableProductWithSpecialPriceTest" extends="AdminCreateDownloadableProductWithGroupPriceTest"> + <test name="AdminCreateDownloadableProductWithSpecialPriceTest"> <annotations> <features value="Catalog"/> <stories value="Create Downloadable Product"/> @@ -19,17 +19,90 @@ <group value="Downloadable"/> <group value="mtf_migrated"/> </annotations> - <remove keyForRemoval="addCustomerGroupPrice"/> + <before> + <!-- Create category --> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete created downloadable product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="ApiDownloadableProduct"/> + </actionGroup> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create downloadable product --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> + <waitForPageLoad stepKey="waitForProductGridPageLoad"/> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createProduct"> + <argument name="productType" value="downloadable"/> + </actionGroup> <!-- Add special price to product --> <actionGroup ref="AddSpecialPriceToProductActionGroup" stepKey="setSpecialPriceToCreatedProduct" after="createProduct"> <argument name="price" value="{{specialProductPrice.price}}"/> </actionGroup> - <remove keyForRemoval="grabGroupPrice"/> - <remove keyForRemoval="assertGroupPrice"/> + <!-- Fill downloadable product values --> + <actionGroup ref="fillMainProductFormNoWeight" stepKey="fillDownloadableProductForm"> + <argument name="product" value="ApiDownloadableProduct"/> + </actionGroup> + + <!-- Add downloadable product to category --> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> + + <!-- Fill downloadable link information before the creation link --> + <actionGroup ref="AdminAddDownloadableLinkInformationActionGroup" stepKey="addDownloadableLinkInformation"/> + + <!-- Links can be purchased separately --> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOptionPurchaseSeparately"/> + + <!-- Add first downloadable link --> + <actionGroup ref="addDownloadableProductLinkWithMaxDownloads" stepKey="addFirstDownloadableProductLink"> + <argument name="link" value="downloadableLinkWithMaxDownloads"/> + </actionGroup> + + <!-- Add second downloadable link --> + <actionGroup ref="addDownloadableProductLink" stepKey="addSecondDownloadableProductLink"> + <argument name="link" value="downloadableLink"/> + </actionGroup> + + <!-- Save product --> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Find downloadable product in grid --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPage"/> + <waitForPageLoad stepKey="waitForAdminProductPageLoad"/> + <actionGroup ref="filterProductGridBySku" stepKey="findCreatedConfigurableProduct"> + <argument name="product" value="ApiDownloadableProduct"/> + </actionGroup> + <click selector="{{AdminProductGridSection.firstRow}}" stepKey="clickOnProduct"/> + <waitForPageLoad stepKey="waitForProductFormPageLoad"/> + + <!-- Assert downloadable links in product form --> + <scrollTo selector="{{AdminProductDownloadableSection.sectionLinkGrid}}" stepKey="scrollToLinks"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="seeFirstLinkTitle"/> + <seeElement selector="{{AdminProductDownloadableSection.addLinkTitleInput('1')}}" stepKey="seeSecondLinkTitle"/> + + <!-- Assert product in storefront product page --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPage" stepKey="AssertProductInStorefrontProductPage"> + <argument name="product" value="ApiDownloadableProduct"/> + </actionGroup> <!-- Assert special price in storefront product page --> <see selector="{{StorefrontProductInfoMainSection.specialPriceValue}}" userInput="$99.99" stepKey="assertSpecialPrice"/> + + <!-- See product link in storefront product page --> + <scrollTo selector="{{StorefrontDownloadableProductSection.downloadableLinkBlock}}" stepKey="scrollToLinksInStorefront"/> + <seeElement stepKey="seeFirstDownloadableLink" selector="{{StorefrontDownloadableProductSection.downloadableLinkLabel(downloadableLinkWithMaxDownloads.title)}}"/> + <seeElement stepKey="seeSecondDownloadableLink" selector="{{StorefrontDownloadableProductSection.downloadableLinkLabel(downloadableLink.title)}}"/> </test> </tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml index 684d0fa766e60..ca4e560506ad0 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithTierPriceText.xml @@ -27,7 +27,6 @@ <argument name="groupPrice" value="tierProductPrice"/> </actionGroup> - <remove keyForRemoval="grabGroupPrice"/> <remove keyForRemoval="assertGroupPrice"/> <!-- Assert tier price in storefront product page --> From 4944b3ea74dcd9fe72586a8d8de6e93e79df77b7 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Fri, 29 Mar 2019 17:25:57 +0200 Subject: [PATCH 111/585] Updating the old test by marking the migrated variations. --- .../Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml index 90c42505585a2..8290d825593af 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml @@ -10,17 +10,20 @@ <variation name="ValidateEmailOnCheckoutTestVariation1"> <data name="customer/data/email" xsi:type="string">johndoe</data> <data name="customer/data/firstname" xsi:type="string">John</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertEmailErrorValidationMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertEmailToolTips" /> </variation> <variation name="ValidateEmailOnCheckoutTestVariation2"> <data name="customer/data/email" xsi:type="string">johndoe#example.com</data> <data name="customer/data/firstname" xsi:type="string">John</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertEmailErrorValidationMessage" /> </variation> <variation name="ValidateEmailOnCheckoutTestVariation3"> <data name="customer/data/email" xsi:type="string">johndoe@example.c</data> <data name="customer/data/firstname" xsi:type="string">John</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertEmailErrorValidationMessage" /> </variation> </testCase> From a5635a267e2927450518e2b8ff174df1c564b768 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Fri, 29 Mar 2019 11:31:11 -0500 Subject: [PATCH 112/585] MAGETWO-93628: Shopping cart is emptied after reset password procedure --- app/code/Magento/Customer/Model/AccountManagement.php | 4 ++-- .../Customer/Test/Unit/Model/AccountManagementTest.php | 4 +++- lib/internal/Magento/Framework/Session/SessionManager.php | 1 - 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 673300369fe06..d86286bc2fcb9 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -624,7 +624,6 @@ public function initiatePasswordReset($email, $template, $websiteId = null) * @param string $rpToken * @throws ExpiredException * @throws NoSuchEntityException - * * @return CustomerInterface * @throws LocalizedException */ @@ -703,7 +702,7 @@ public function resetPassword($email, $resetToken, $newPassword) $customerSecure->setRpTokenCreatedAt(null); $customerSecure->setPasswordHash($this->createPasswordHash($newPassword)); $this->destroyCustomerSessions($customer->getId()); - $this->sessionManager->destroy(); + $this->sessionManager->destroy(['send_expire_cookie' => false]); $this->customerRepository->save($customer); return true; @@ -1564,6 +1563,7 @@ private function getEmailNotification() /** * Destroy all active customer sessions by customer id (current session will not be destroyed). + * * Customer sessions which should be deleted are collecting from the "customer_visitor" table considering * configured session lifetime. * diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 22c9d90c086dc..aa901e8a2e978 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1610,7 +1610,9 @@ function ($string) { $this->customerSecure->expects($this->once())->method('setRpTokenCreatedAt')->with(null); $this->customerSecure->expects($this->any())->method('setPasswordHash')->willReturn(null); - $this->sessionManager->expects($this->atLeastOnce())->method('destroy'); + $this->sessionManager->expects($this->once()) + ->method('destroy') + ->with(['send_expire_cookie' => false]); $this->sessionManager->expects($this->atLeastOnce())->method('getSessionId'); $visitor = $this->getMockBuilder(\Magento\Customer\Model\Visitor::class) ->disableOriginalConstructor() diff --git a/lib/internal/Magento/Framework/Session/SessionManager.php b/lib/internal/Magento/Framework/Session/SessionManager.php index c7d201676b228..b306b879b7127 100644 --- a/lib/internal/Magento/Framework/Session/SessionManager.php +++ b/lib/internal/Magento/Framework/Session/SessionManager.php @@ -353,7 +353,6 @@ public function destroy(array $options = null) } session_regenerate_id(true); - session_destroy(); if ($options['send_expire_cookie']) { $this->expireSessionCookie(); } From 6271cc29ffb70f04610e1d231a0a412e1fae4877 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Fri, 29 Mar 2019 14:18:51 -0500 Subject: [PATCH 113/585] MC-4461: Convert AddProductsToShoppingCartEntityTest to MFTF - Minor code review tweaks --- .../AssertStorefronElementVisibleActionGroup.xml | 8 ++++---- .../AssertStorefrontMiniCartItemsActionGroup.xml | 12 ++++++------ ...torefrontAddBundleProductToTheCartActionGroup.xml | 4 ++-- ...ToTheShoppingCartWithoutAnySelectedOptionTest.xml | 4 ++-- ...rontAddBundleDynamicProductToShoppingCartTest.xml | 2 +- ...tToShoppingCartWithDisableMiniCartSidebarTest.xml | 2 +- ...frontAddConfigurableProductToShoppingCartTest.xml | 2 +- ...frontAddDownloadableProductToShoppingCartTest.xml | 2 +- ...StorefrontAddGroupedProductToShoppingCartTest.xml | 4 ++-- ...eBundleMultiSelectOptionToTheShoppingCartTest.xml | 2 +- ...thAllTypesOfCustomOptionToTheShoppingCartTest.xml | 2 +- ...BundleMultiSelectOptionsToTheShoppingCartTest.xml | 2 +- ...ckItemDisplayWithDefaultDisplayLimitationTest.xml | 2 +- ...temsAddedToTheCartThanDefaultDisplayLimitTest.xml | 2 +- ...efaultDisplayLimitAndDefaultTotalQuantityTest.xml | 4 ++-- ...oductCartItemDisplayWithDefaultLimitationTest.xml | 2 +- ...ountDisplayWithCustomDisplayConfigurationTest.xml | 2 +- 17 files changed, 29 insertions(+), 29 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefronElementVisibleActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefronElementVisibleActionGroup.xml index ddda54799f985..b99c4b7f5bf16 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefronElementVisibleActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefronElementVisibleActionGroup.xml @@ -8,10 +8,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStorefrontElementVisibleActionGroup"> - <arguments> - <argument name="selector" type="string"/> - <argument name="userInput" type="string"/> - </arguments> + <arguments> + <argument name="selector" type="string"/> + <argument name="userInput" type="string"/> + </arguments> <see selector="{{selector}}" userInput="{{userInput}}" stepKey="assertElement"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml index 1d8f065fa1786..258d8ed9021c0 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml @@ -8,12 +8,12 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStorefrontMiniCartItemsActionGroup"> - <arguments> - <argument name="productName" type="string"/> - <argument name="productPrice" type="string"/> - <argument name="cartSubtotal" type="string"/> - <argument name="qty" type="string"/> - </arguments> + <arguments> + <argument name="productName" type="string"/> + <argument name="productPrice" type="string"/> + <argument name="cartSubtotal" type="string"/> + <argument name="qty" type="string"/> + </arguments> <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{productName}}" stepKey="seeProductNameInMiniCart"/> <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{productPrice}}" stepKey="seeProductPriceInMiniCart"/> <seeElement selector="{{StorefrontMinicartSection.goToCheckout}}" stepKey="seeCheckOutButtonInMiniCart"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddBundleProductToTheCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddBundleProductToTheCartActionGroup.xml index 5f418077afbe6..2c64eda38a420 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddBundleProductToTheCartActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddBundleProductToTheCartActionGroup.xml @@ -9,8 +9,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontAddBundleProductToTheCartActionGroup"> <arguments> - <argument name="productName" type="string"/> - <argument name="quantity" type="string"/> + <argument name="productName" type="string"/> + <argument name="quantity" type="string"/> </arguments> <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickOnCustomizeAndAddToCartButton"/> <waitForPageLoad stepKey="waitForPageLoad"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOptionTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOptionTest.xml index 23389e119d268..2ac84000fd1e8 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOptionTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOptionTest.xml @@ -10,8 +10,8 @@ <test name="StoreFrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOptionTest"> <annotations> <stories value="Shopping Cart"/> - <title value="AddProductWithAllTypesOfCustomOptionToTheShoppingCartWithoutAnySelectedOption"/> - <description value="Add simple product with all types of custom options to cart without selecting any options "/> + <title value="Add simple product with all types of custom options to cart without selecting any options"/> + <description value="Add simple product with all types of custom options to cart without selecting any options"/> <testCaseId value="MC-14725"/> <severity value="CRITICAL"/> <group value="mtf_migrated"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml index 027c21ae2ae82..73f8f03e6d9ce 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontAddBundleDynamicProductToShoppingCartTest"> <annotations> <stories value="Shopping Cart"/> - <title value="AddBundleDynamicProductToShoppingCart"/> + <title value="Add bundle dynamic product to the cart"/> <description value="Add bundle dynamic product to the cart"/> <testCaseId value="MC-14715"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml index 44fa46c9b941a..938f56e61136b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest"> <annotations> <stories value="Shopping Cart"/> - <title value="AddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebar"/> + <title value="Create Grouped product and verify mini cart action with disabled and enable Mini Cart Sidebar"/> <description value="Create Grouped product and verify mini cart action with disabled and enable Mini Cart Sidebar"/> <testCaseId value="MC-14719"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml index 31c987a701f29..a0c9c07f9ff80 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontAddConfigurableProductToShoppingCartTest"> <annotations> <stories value="Shopping Cart"/> - <title value="AddConfigurableProductToShoppingCart"/> + <title value="Create configurable product with three options and add configurable product to the cart"/> <description value="Create configurable product with three options and add configurable product to the cart"/> <testCaseId value="MC-14716"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml index fabdcc2da5d86..ef49b6660a983 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontAddDownloadableProductToShoppingCartTest"> <annotations> <stories value="Shopping Cart"/> - <title value="AddDownloadableProductToShoppingCart"/> + <title value="Create Downloadable product with two links and add to the shopping cart"/> <description value="Create Downloadable product with two links and add to the shopping cart"/> <testCaseId value="MC-14717"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml index 90f3022cf2b8e..26a2149081d19 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml @@ -10,8 +10,8 @@ <test name="StorefrontAddGroupedProductToShoppingCartTest"> <annotations> <stories value="Shopping Cart"/> - <title value="AddGroupedProductToShoppingCartTest"/> - <description value="Create grouped product with three simple product and Add grouped product to the cart "/> + <title value="Create grouped product with three simple product and Add grouped product to the cart"/> + <description value="Create grouped product with three simple product and Add grouped product to the cart"/> <testCaseId value="MC-14718"/> <severity value="CRITICAL"/> <group value="mtf_migrated"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml index 3cacb5b76b503..ee50310cd88b8 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest"> <annotations> <stories value="Shopping Cart"/> - <title value="AddOneBundleMultiSelectOptionToTheShoppingCart"/> + <title value="Select one multi select option of a bundle product and add to the shopping cart"/> <description value="Select one multi select option of a bundle product and add to the shopping cart "/> <testCaseId value="MC-14727"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml index 0f74032303eb9..611c53dba0dec 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest"> <annotations> <stories value="Shopping Cart"/> - <title value="AddSimpleProductsWithAllTypesOfCustomOptionsToTheShoppingCart"/> + <title value="Create a simple products with all types of oprtions and add it to the cart"/> <description value="Create a simple products with all types of oprtions and add it to the cart"/> <testCaseId value="MC-14726"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml index 232ac15f6be56..6bada4ce66b4d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest"> <annotations> <stories value="Shopping Cart"/> - <title value="AddTwoBundleMultiSelectOptionsToTheShoppingCart"/> + <title value="Add two products to the cart from multi select options of a bundle product"/> <description value="Add two products to the cart from multi select options of a bundle product."/> <testCaseId value="MC-14728"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndSummaryBlockItemDisplayWithDefaultDisplayLimitationTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndSummaryBlockItemDisplayWithDefaultDisplayLimitationTest.xml index 4acd8a232058a..92c612b75f07a 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndSummaryBlockItemDisplayWithDefaultDisplayLimitationTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndSummaryBlockItemDisplayWithDefaultDisplayLimitationTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontCheckCartAndSummaryBlockItemDisplayWithDefaultDisplayLimitationTest"> <annotations> <stories value="Shopping Cart"/> - <title value="CheckCartAndSummaryBlockDisplayWithDefaultDisplayLimitation"/> + <title value="Add 10 items to the cart and check cart and summary block display with default display limit"/> <description value="Add 10 items to the cart and check cart and summary block display with default display limit"/> <testCaseId value="MC-14722"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimitTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimitTest.xml index f1c50d04e460e..fec5bb9fadb6e 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimitTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimitTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontCheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimitTest"> <annotations> <stories value="Shopping Cart"/> - <title value="CheckCartItemDisplayWhenMoreItemsAddedToTheCartThanDefaultDisplayLimit"/> + <title value="Add 11 Simple product to the cart and check cart display with default display limit"/> <description value="Add 11 Simple product to the cart and check cart display with default display limit"/> <testCaseId value="MC-14720"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantityTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantityTest.xml index 53fbb8eeef513..2339789bd85d1 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantityTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantityTest.xml @@ -10,8 +10,8 @@ <test name="StorefrontCheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantityTest"> <annotations> <stories value="Shopping Cart"/> - <title value="CheckCartItemDisplayWithDefaultDisplayLimitAndDefaultTotalQuantity"/> - <description value="Add 10 itemsto the cart and check cart display with default display limit"/> + <title value="Add 10 items to the cart and check cart display with default display limit"/> + <description value="Add 10 items to the cart and check cart display with default display limit"/> <testCaseId value="MC-14721"/> <severity value="CRITICAL"/> <group value="mtf_migrated"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckSimpleProductCartItemDisplayWithDefaultLimitationTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckSimpleProductCartItemDisplayWithDefaultLimitationTest.xml index 9ef8856f401e1..bca14c8379ca3 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckSimpleProductCartItemDisplayWithDefaultLimitationTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckSimpleProductCartItemDisplayWithDefaultLimitationTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontCheckSimpleProductCartItemDisplayWithDefaultLimitationTest"> <annotations> <stories value="Shopping Cart"/> - <title value="CheckSimpleProductCartItemDisplayWithDefaultLimitation"/> + <title value="Add 10 SimpleProducts to the cart and check cart display with default display limit"/> <description value="Add 10 SimpleProducts to the cart and check cart display with default display limit"/> <testCaseId value="MC-14723"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckVirtualProductCountDisplayWithCustomDisplayConfigurationTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckVirtualProductCountDisplayWithCustomDisplayConfigurationTest.xml index c8e343e695f10..1f63565899f88 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckVirtualProductCountDisplayWithCustomDisplayConfigurationTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckVirtualProductCountDisplayWithCustomDisplayConfigurationTest.xml @@ -10,7 +10,7 @@ <test name="StorefrontCheckVirtualProductCountDisplayWithCustomDisplayConfigurationTest"> <annotations> <stories value="Shopping Cart"/> - <title value="CheckVirtualProductCountDisplayWithCustomDisplayConfiguration"/> + <title value="Verify virtual products count in mini cart and summary block with custom display configuration"/> <description value="Verify virtual products count in mini cart and summary block with custom display configuration"/> <testCaseId value="MC-14724"/> <severity value="CRITICAL"/> From 9c7820c7695dc8c191693963988b515e174e2009 Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Fri, 29 Mar 2019 14:59:10 -0500 Subject: [PATCH 114/585] MC-4788: Convert DeleteSalesRuleEntityTest to MFTF Addressing review comments --- ...CartPriceRuleActionsSectionActionGroup.xml | 18 +++++++++++---- ...tPriceRuleConditionsSectionActionGroup.xml | 22 ++++++++++++++----- ...eCartPriceRuleLabelsSectionActionGroup.xml | 4 ++-- ...artPriceRuleRuleInfoSectionActionGroup.xml | 2 +- .../Test/Mftf/Data/SalesRuleData.xml | 1 + .../AdminCartPriceRulesFormSection.xml | 1 + ...exConditionsAndVerifyDeleteMessageTest.xml | 15 +++++++++++-- ...iveSalesRuleAndVerifyDeleteMessageTest.xml | 3 ++- 8 files changed, 51 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml index 3d2ff88840144..dc67dfd68d589 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml @@ -7,16 +7,26 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCreateCartPriceRuleActionsSectionActionGroup"> + <actionGroup name="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup"> <arguments> - <argument name="ruleName"/> + <argument name="ruleName" type="entity"/> </arguments> - <click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.actionsHeader}}" visible="true" stepKey="clickToExpandActions"/> <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{ruleName.simple_action}}" stepKey="selectActionType"/> <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{ruleName.discount_amount}}" stepKey="fillDiscountAmount"/> + <fillField selector="{{AdminCartPriceRulesFormSection.maximumQtyDiscount}}" userInput="{{ruleName.maximumQtyDiscount}}" stepKey="fillMaximumQtyDiscount"/> <fillField selector="{{AdminCartPriceRulesFormSection.discountStep}}" userInput="{{ruleName.discount_step}}" stepKey="fillDiscountStep"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleActionsSectionShippingAmountActionGroup"> <click selector="{{AdminCartPriceRulesFormSection.applyToShippingAmount}}" stepKey="clickApplyToShipping"/> - <click selector="{{AdminCartPriceRulesFormSection.discardSubsequentRules}}" stepKey="clickDiscardSubsequentRules"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleActionsSectionSubsequentRulesActionGroup"> + <click selector="{{AdminCartPriceRulesFormSection.discardSubsequentRules}}" stepKey="clickApplyToShipping"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup"> + <arguments> + <argument name="ruleName" type="entity"/> + </arguments> <selectOption selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{ruleName.simple_free_shipping}}" stepKey="selectForMatchingItemsOnly"/> </actionGroup> </actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml index 085a0ab33440c..3c9e015300327 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml @@ -7,19 +7,24 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCreateCartPriceRuleConditionsSectionActionGroup"> + <actionGroup name="AdminCreateCartPriceRuleConditionsSectionSubtotalActionGroup"> <arguments> - <argument name="ruleName"/> + <argument name="ruleName" type="entity"/> <argument name="condition1" type="string"/> - <argument name="condition2" type="string"/> - <argument name="condition3" type="string"/> </arguments> - <click selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="clickToExpandConditions"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewCondition"/> <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition1}}" stepKey="selectCondition1"/> <waitForPageLoad stepKey="waitForConditionLoad"/> <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis"/> <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{ruleName.subtotal}}" stepKey="fillSubtotalParameter"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleConditionsSectionShippingCountryActionGroup"> + <arguments> + <argument name="ruleName" type="entity"/> + <argument name="condition2" type="string"/> + </arguments> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewConditionButton"/> <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition2}}" stepKey="selectCondition2"/> <waitForPageLoad stepKey="waitForSecondConditionLoad"/> @@ -27,6 +32,13 @@ <click selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" stepKey="clickSelectCountryDropdown"/> <waitForPageLoad stepKey="waitForDropdownLoad"/> <selectOption selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" userInput="{{ruleName.shippingCountry}}" stepKey="fillShippingCountryParameter"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleConditionsSectionShippingPostcodeActionGroup"> + <arguments> + <argument name="ruleName" type="entity"/> + <argument name="condition3" type="string"/> + </arguments> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickOnNewCondition"/> <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition3}}" stepKey="selectCondition3"/> <waitForPageLoad stepKey="waitForThirdConditionLoad"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml index 49d5900a3a45b..4133cc44ebc15 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml @@ -9,9 +9,9 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminCreateCartPriceRuleLabelsSectionActionGroup"> <arguments> - <argument name="ruleName"/> + <argument name="ruleName" type="entity"/> </arguments> - <click selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="clickToExpandLabels"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.labelsHeader}}" visible="true" stepKey="clickToExpandLabels"/> <fillField selector="{{AdminCartPriceRulesFormSection.defaultRuleLabelAllStoreViews}}" userInput="{{ruleName.defaultRuleLabelAllStoreViews}}" stepKey="fillDefaultRuleLabelAllStoreViews"/> <fillField selector="{{AdminCartPriceRulesFormSection.defaultStoreView}}" userInput="{{ruleName.defaultStoreView}}" stepKey="fillDefaultStoreView"/> </actionGroup> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleRuleInfoSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleRuleInfoSectionActionGroup.xml index 591dfbfb95536..27b9634cbe28c 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleRuleInfoSectionActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleRuleInfoSectionActionGroup.xml @@ -9,7 +9,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminCreateCartPriceRuleRuleInfoSectionActionGroup"> <arguments> - <argument name="ruleName"/> + <argument name="ruleName" type="entity"/> </arguments> <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> <waitForPageLoad stepKey="waitForPriceList"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml index 278991967418a..74ee28de2d3fa 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml @@ -223,6 +223,7 @@ <data key="shippingPostcode">123456789a</data> <data key="simple_action">Percent of product price discount</data> <data key="discount_amount">50</data> + <data key="maximumQtyDiscount">0</data> <data key="discount_step">0</data> <data key="apply_to_shipping">Yes</data> <data key="stop_rules_processing">Yes</data> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml index 88be49d7f96ca..b701389a13418 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml @@ -66,6 +66,7 @@ <element name="applyDiscountToShipping" type="checkbox" selector="input[name='apply_to_shipping']"/> <element name="applyDiscountToShippingLabel" type="checkbox" selector="input[name='apply_to_shipping']+label"/> <element name="discountAmount" type="input" selector="input[name='discount_amount']"/> + <element name="maximumQtyDiscount" type="input" selector="input[name='discount_qty']"/> <element name="discountStep" type="input" selector="input[name='discount_step']"/> <element name="applyToShippingAmount" type="checkbox" selector="//div[@class='admin__actions-switch']/input[@name='apply_to_shipping']/../label"/> <element name="discardSubsequentRules" type="checkbox" selector="//div[@class='admin__actions-switch']/input[@name='stop_rules_processing']/../label"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml index d1852590d7826..20476858d58ce 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml @@ -25,14 +25,25 @@ <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> </actionGroup> <!--Fill values for Condition Section--> - <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionActionGroup" stepKey="createActiveCartPriceRuleConditionsSection"> + <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionSubtotalActionGroup" stepKey="createActiveCartPriceRuleConditionsSubtotalSection"> <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> <argument name="condition1" value="Subtotal"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionShippingCountryActionGroup" stepKey="createActiveCartPriceRuleConditionsShippingCountrySection"> + <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> <argument name="condition2" value="Shipping Country"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionShippingPostcodeActionGroup" stepKey="createActiveCartPriceRuleConditionsShippingPostcodeSection"> + <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> <argument name="condition3" value="Shipping Postcode"/> </actionGroup> <!--Fill values for Action Section--> - <actionGroup ref="AdminCreateCartPriceRuleActionsSectionActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> + <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionShippingAmountActionGroup" stepKey="createActiveCartPriceRuleShippingAmountActionsSection"/> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionSubsequentRulesActionGroup" stepKey="createActiveCartPriceRuleDiscardSubsequentRulesActionsSection"/> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> </actionGroup> <!--Fill values for Labels Section--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml index a46c98a47e8a5..1570bfbdb7a23 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml @@ -25,6 +25,7 @@ <!--Create inactive cart price rule--> <actionGroup ref="AdminInactiveCartPriceRuleActionGroup" stepKey="createInactiveCartPriceRule"> <argument name="ruleName" value="InactiveSalesRule"/> + <argument name="custGrp" value="NOT LOGGED IN"/> </actionGroup> </before> <after> @@ -43,7 +44,7 @@ </actionGroup> <!--Verify customer don't see updated virtual product link on category page --> - <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProduct1PageAndVerifyProduct"> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> <argument name="product" value="$$initialSimpleProduct$$"/> </actionGroup> From 24e61f5b84cd8fd5079a1074b86386b107c61f8f Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Fri, 29 Mar 2019 15:41:11 -0500 Subject: [PATCH 115/585] MC-4437: Convert SuggestSearchingResultEntityTest to MFTF --- ...roductNameOnProductMainPageActionGroup.xml | 16 ++++ .../StorefrontOpenHomePageActionGroup.xml | 13 ++++ .../Catalog/Test/Mftf/Data/ProductData.xml | 13 ++++ .../AdminCatalogSearchTermIndexSection.xml | 2 + ...ectDropDownSearchSuggestionActionGroup.xml | 21 +++++ .../Section/StorefrontQuickSearchSection.xml | 2 + ...archSuggestionByProductDescriptionTest.xml | 77 +++++++++++++++++++ ...erifySearchSuggestionByProductNameTest.xml | 63 +++++++++++++++ ...uggestionByProductShortDescriptionTest.xml | 65 ++++++++++++++++ ...VerifySearchSuggestionByProductSkuTest.xml | 65 ++++++++++++++++ 10 files changed, 337 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameOnProductMainPageActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenHomePageActionGroup.xml create mode 100644 app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontSelectDropDownSearchSuggestionActionGroup.xml create mode 100644 app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductDescriptionTest.xml create mode 100644 app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductNameTest.xml create mode 100644 app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductShortDescriptionTest.xml create mode 100644 app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductSkuTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameOnProductMainPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameOnProductMainPageActionGroup.xml new file mode 100644 index 0000000000000..43a34448c8a68 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameOnProductMainPageActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertProductNameOnProductMainPageActionGroup"> + <arguments> + <argument name="productName" type="string"/> + </arguments> + <waitForPageLoad stepKey="waitForTheProductPageToLoad"/> + <see selector="{{StorefrontCategoryMainSection.productName}}" userInput="{{productName}}" stepKey="seeProductName"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenHomePageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenHomePageActionGroup.xml new file mode 100644 index 0000000000000..692d1f4266b98 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenHomePageActionGroup.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontOpenHomePageActionGroup"> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> + <waitForPageLoad stepKey="waitForStorefrontPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 1aca63b28c95d..37fc3cfb8c703 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -982,4 +982,17 @@ <data key="tax_class_id">2</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> </entity> + <entity name="SimpleProductWithDescription" type="product"> + <data key="sku" unique="suffix">productwithdescription</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="name" unique="suffix">ProductWithDescription</data> + <data key="price">123.00</data> + <data key="urlKey" unique="suffix">productwithdescription</data> + <data key="status">1</data> + <data key="quantity">100</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute_array">ApiProductDescription</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Section/AdminCatalogSearchTermIndexSection.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Section/AdminCatalogSearchTermIndexSection.xml index ac316d060f6e9..aa0145b9f96cd 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Section/AdminCatalogSearchTermIndexSection.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Section/AdminCatalogSearchTermIndexSection.xml @@ -19,5 +19,7 @@ <element name="searchTermRowCheckboxBySearchQuery" type="checkbox" selector="//*[normalize-space()='{{var1}}']/preceding-sibling::td//input[@name='search']" parameterized="true" timeout="30"/> <element name="okButton" type="button" selector="//button[@class='action-primary action-accept']/span" timeout="30"/> <element name="emptyRecords" type="text" selector="//tr[@class='data-grid-tr-no-data even']/td[@class='empty-text']"/> + <element name="gridRow" type="text" selector="//tr[@data-role='row']"/> + <element name="numberOfSearchTermResults" type="text" selector="//tr[@data-role='row']/td[@data-column='num_results']"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontSelectDropDownSearchSuggestionActionGroup.xml b/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontSelectDropDownSearchSuggestionActionGroup.xml new file mode 100644 index 0000000000000..7084965297c45 --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontSelectDropDownSearchSuggestionActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StoreFrontSelectDropDownSearchSuggestionActionGroup"> + <arguments> + <argument name="searchQuery" type="string"/> + </arguments> + <waitForElementVisible selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" stepKey="waitForQuickSearchToBeVisible"/> + <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{searchQuery}}" stepKey="fillSearchInput"/> + <waitForElementVisible selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" stepKey="WaitForSearchDropDownSuggestion"/> + <see selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" userInput="{{searchQuery}}" stepKey="seeDropDownSuggestion"/> + <click selector="{{StorefrontQuickSearchSection.searchDropDownName(searchQuery)}}" stepKey="clickOnSearchSuggestion"/> + <waitForPageLoad stepKey="waitForSelectedProductToLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchSection.xml b/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchSection.xml index 3c2909b59c0de..34379fd6d2e4a 100644 --- a/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchSection.xml +++ b/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchSection.xml @@ -12,5 +12,7 @@ <element name="searchPhrase" type="input" selector="#search"/> <element name="searchButton" type="button" selector="button.action.search" timeout="30"/> <element name="searchMiniForm" type="input" selector="#search_mini_form"/> + <element name="searchDropDownSuggestion" type="text" selector="//div[@id='search_autocomplete']/ul/li/span"/> + <element name="searchDropDownName" type="text" selector="//div[@id='search_autocomplete']//span[contains(., '{{searchQuery}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductDescriptionTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductDescriptionTest.xml new file mode 100644 index 0000000000000..9e3ed2def2f87 --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductDescriptionTest.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySearchSuggestionByProductDescriptionTest"> + <annotations> + <stories value="Search Term"/> + <title value="Create search query using product description and verify search suggestions"/> + <description value="Storefront search by product description, generate search query and verify dropdown product search suggestions"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14765"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Create product with description --> + <createData entity="SimpleProductWithDescription" stepKey="simpleProduct"/> + </before> + <after> + <!--Delete create product --> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + + <!--Go to the catalog search term page --> + <amOnPage url="{{AdminCatalogSearchTermIndexPage.url}}" stepKey="openAdminCatalogSearchTermIndexPage"/> + <waitForPageLoad stepKey="waitForAdminCatalogSearchTermIndexPageLoad"/> + + <!--Filter the search term --> + <actionGroup ref="searchTermFilterBySearchQuery" stepKey="filterByThirdSearchQuery"> + <argument name="searchQuery" value="{{ApiProductDescription.value}}"/> + </actionGroup> + + <!-- Delete created below search terms --> + <actionGroup ref="deleteSearchTerm" stepKey="deleteSearchTerms"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Go to storefront home page --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openStoreFrontHomePage"/> + + <!--Storefront quick search by product name --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName"> + <argument name="phrase" value="{{ApiProductDescription.value}}"/> + </actionGroup> + + <!--Verify search suggestions and select the suggestion from dropdown options --> + <actionGroup ref="StoreFrontSelectDropDownSearchSuggestionActionGroup" stepKey="seeDropDownSearchSuggestion"> + <argument name="searchQuery" value="{{ApiProductDescription.value}}"/> + </actionGroup> + + <!-- Assert Product storefront main page --> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeProductName"> + <argument name="productName" value="$$simpleProduct.name$$"/> + </actionGroup> + + <!--Go to the catalog search term page --> + <amOnPage url="{{AdminCatalogSearchTermIndexPage.url}}" stepKey="openAdminCatalogSearchTermIndexPage"/> + <waitForPageLoad stepKey="waitForAdminCatalogSearchTermIndexPageLoad"/> + + <!--Filter the search term --> + <actionGroup ref="searchTermFilterBySearchQuery" stepKey="filterByThirdSearchQuery"> + <argument name="searchQuery" value="{{ApiProductDescription.value}}"/> + </actionGroup> + + <!--Assert Search Term in grid --> + <see stepKey="seeSearchTermInGrid" selector="{{AdminCatalogSearchTermIndexSection.gridRow}}" userInput="{{ApiProductDescription.value}}" /> + <see selector="{{AdminCatalogSearchTermIndexSection.numberOfSearchTermResults}}" userInput="1" stepKey="seeNumberOfSearchTermResultInGrid"/> + </test> +</tests> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductNameTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductNameTest.xml new file mode 100644 index 0000000000000..119faef9f2f59 --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductNameTest.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySearchSuggestionByProductNameTest"> + <annotations> + <stories value="Search Term"/> + <title value="Create search query using product name and verify search suggestions"/> + <description value="Storefront search by product name and verify dropdown product search suggestions"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14763"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!--Create Simple Product --> + <createData entity="defaultSimpleProduct" stepKey="simpleProduct"/> + </before> + <after> + <!-- Delete create product --> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + + <!-- Go to the catalog search term page --> + <amOnPage url="{{AdminCatalogSearchTermIndexPage.url}}" stepKey="openAdminCatalogSearchTermIndexPage"/> + <waitForPageLoad stepKey="waitForAdminCatalogSearchTermIndexPageLoad"/> + + <!--Filter the search term --> + <actionGroup ref="searchTermFilterBySearchQuery" stepKey="filterByThirdSearchQuery"> + <argument name="searchQuery" value="$$simpleProduct.name$$"/> + </actionGroup> + <!-- Delete created below search terms --> + <actionGroup ref="deleteSearchTerm" stepKey="deleteSearchTerms"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Go to storefront home page --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openStoreFrontHomePage"/> + + <!--Storefront quick search by product name --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName"> + <argument name="phrase" value="$$simpleProduct.name$$"/> + </actionGroup> + + <!--Verify search suggestions and select the suggestion from dropdown options --> + <actionGroup ref="StoreFrontSelectDropDownSearchSuggestionActionGroup" stepKey="seeDropDownSearchSuggestion"> + <argument name="searchQuery" value="$$simpleProduct.name$$"/> + </actionGroup> + + <!-- Assert Product storefront main page --> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeProductName"> + <argument name="productName" value="$$simpleProduct.name$$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductShortDescriptionTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductShortDescriptionTest.xml new file mode 100644 index 0000000000000..ca48fb8565ca8 --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductShortDescriptionTest.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySearchSuggestionByProductShortDescriptionTest"> + <annotations> + <stories value="Search Term"/> + <title value="Create search query using product short description and verify search suggestions"/> + <description value="Storefront search by product short description, generate search query and verify dropdown product search suggestions"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14766"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Create product with short description --> + <createData entity="ApiProductWithDescription" stepKey="product"/> + </before> + <after> + + <!--Delete create product --> + <deleteData createDataKey="product" stepKey="deleteProduct"/> + + <!--Go to the catalog search term page --> + <amOnPage url="{{AdminCatalogSearchTermIndexPage.url}}" stepKey="openAdminCatalogSearchTermIndexPage"/> + <waitForPageLoad stepKey="waitForAdminCatalogSearchTermIndexPageLoad"/> + + <!--Filter the search term --> + <actionGroup ref="searchTermFilterBySearchQuery" stepKey="filterByThirdSearchQuery"> + <argument name="searchQuery" value="{{ApiProductShortDescription.value}}"/> + </actionGroup> + + <!-- Delete created below search terms --> + <actionGroup ref="deleteSearchTerm" stepKey="deleteSearchTerms"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Go to storefront home page --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openStoreFrontHomePage"/> + + <!--Storefront quick search by product name --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName"> + <argument name="phrase" value="{{ApiProductShortDescription.value}}"/> + </actionGroup> + + <!--Verify search suggestions and select the suggestion from dropdown options --> + <actionGroup ref="StoreFrontSelectDropDownSearchSuggestionActionGroup" stepKey="seeDropDownSearchSuggestion"> + <argument name="searchQuery" value="{{ApiProductShortDescription.value}}"/> + </actionGroup> + + <!-- Assert Product storefront main page --> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeProductName"> + <argument name="productName" value="$$product.name$$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductSkuTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductSkuTest.xml new file mode 100644 index 0000000000000..6033ea8dee28b --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductSkuTest.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySearchSuggestionByProductSkuTest"> + <annotations> + <stories value="Search Term"/> + <title value="Create search query using product sku and verify search suggestions"/> + <description value="Storefront search by product sku, generate search query and verify dropdown product search suggestions"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14764"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!--Create Simple Product --> + <createData entity="defaultSimpleProduct" stepKey="simpleProduct"/> + </before> + <after> + + <!-- Delete create product --> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + + <!-- Go to the catalog search term page --> + <amOnPage url="{{AdminCatalogSearchTermIndexPage.url}}" stepKey="openAdminCatalogSearchTermIndexPage"/> + <waitForPageLoad stepKey="waitForAdminCatalogSearchTermIndexPageLoad"/> + + <!--Filter the search term --> + <actionGroup ref="searchTermFilterBySearchQuery" stepKey="filterByThirdSearchQuery"> + <argument name="searchQuery" value="$$simpleProduct.sku$$"/> + </actionGroup> + + <!-- Delete created below search terms --> + <actionGroup ref="deleteSearchTerm" stepKey="deleteSearchTerms"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Go to storefront home page --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openStoreFrontHomePage"/> + + <!--Storefront quick search by product name --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName"> + <argument name="phrase" value="$$simpleProduct.sku$$"/> + </actionGroup> + + <!--Verify search suggestions and select the suggestion from dropdown options --> + <actionGroup ref="StoreFrontSelectDropDownSearchSuggestionActionGroup" stepKey="seeDropDownSearchSuggestion"> + <argument name="searchQuery" value="$$simpleProduct.sku$$"/> + </actionGroup> + + <!-- Assert Product storefront main page --> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeProductName"> + <argument name="productName" value="$$simpleProduct.name$$"/> + </actionGroup> + </test> +</tests> From b49305c10a4f7870f1c1a882bc20838a189d47a4 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Sat, 30 Mar 2019 00:08:51 +0200 Subject: [PATCH 116/585] Add arguments to AdminNewUserInvalidCurrentUserPasswordActionGroup, add review suggestions --- ...rInvalidCurrentUserPasswordActionGroup.xml | 26 +++++--- .../Security/Test/Mftf/Data/AdminUserData.xml | 2 +- .../LockAdminUserWhenCreatingNewUserTest.xml | 62 ++++++++++++++++--- .../LockAdminUserWhenCreatingNewUserTest.xml | 1 + 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml index 4721106c1e317..0992dd23c76f4 100644 --- a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml +++ b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml @@ -8,17 +8,27 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminNewUserInvalidCurrentUserPasswordActionGroup"> + <arguments> + <argument name="adminUser" type="string" /> + <argument name="adminFirstname" type="string" /> + <argument name="adminLastname" type="string" /> + <argument name="adminEmail" type="string" /> + <argument name="adminPassword" type="string" /> + <argument name="adminPasswordConfirmation" type="string" /> + <argument name="currentAdminPassword" type="string" /> + <argument name="adminUserRole" type="string"/> + </arguments> <!-- Fill in all data according to data set (current password is incorrect). --> - <fillField selector="{{AdminNewUserSection.username}}" userInput="{{AdminUserData.username}}" stepKey="fillUser"/> - <fillField selector="{{AdminNewUserSection.firstname}}" userInput="{{AdminUserData.firstname}}" stepKey="fillFirstName"/> - <fillField selector="{{AdminNewUserSection.lastname}}" userInput="{{AdminUserData.lastname}}" stepKey="fillLastName"/> - <fillField selector="{{AdminNewUserSection.email}}" userInput="{{AdminUserData.email}}" stepKey="fillEmail"/> - <fillField selector="{{AdminNewUserSection.password}}" userInput="{{AdminUserData.password}}" stepKey="fillPassword"/> - <fillField selector="{{AdminNewUserSection.confirmation}}" userInput="{{AdminUserData.password}}" stepKey="fillPasswordConfirmation"/> - <fillField selector="{{AdminNewUserSection.currentPassword}}" userInput="{{AdminUserData.password}}INVALID" stepKey="fillCurrentUserPassword"/> + <fillField selector="{{AdminNewUserSection.username}}" userInput="{{adminUser}}" stepKey="fillUser"/> + <fillField selector="{{AdminNewUserSection.firstname}}" userInput="{{adminFirstname}}" stepKey="fillFirstName"/> + <fillField selector="{{AdminNewUserSection.lastname}}" userInput="{{adminLastname}}" stepKey="fillLastName"/> + <fillField selector="{{AdminNewUserSection.email}}" userInput="{{adminEmail}}" stepKey="fillEmail"/> + <fillField selector="{{AdminNewUserSection.password}}" userInput="{{adminPassword}}" stepKey="fillPassword"/> + <fillField selector="{{AdminNewUserSection.confirmation}}" userInput="{{adminPasswordConfirmation}}" stepKey="fillPasswordConfirmation"/> + <fillField selector="{{AdminNewUserSection.currentPassword}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> <click selector="{{AdminNewUserSection.userRoleTab}}" stepKey="openUserRoleTab"/> - <click selector="{{AdminNewUserSection.administratorRole('1')}}" stepKey="assignRole"/> + <click selector="{{adminUserRole}}" stepKey="assignRole"/> <click selector="{{AdminNewUserSection.save}}" stepKey="saveNewUser"/> <waitForPageLoad stepKey="waitForSaveResultLoad"/> </actionGroup> diff --git a/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml b/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml index 65b18910098ad..1b3ec0ab351b9 100644 --- a/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml +++ b/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml @@ -11,7 +11,7 @@ <entity name="AdminUserData" type="admin"> <data key="email" unique="prefix">John.Doe@example.com</data> <data key="firstname">John</data> - <data key="username">lockuser</data> + <data key="username" unique="prefix">lockuser</data> <data key="lastname">Doe</data> <data key="password">pwdTest123!</data> </entity> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml index 1aa0fdfc8b8fc..ec4dcd8dd0f6d 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml @@ -33,20 +33,68 @@ <!-- Perform add new admin user 6 specified number of times. "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt1"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFirstAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> <waitForPageLoad stepKey="waitForSaveResultLoad"/> <see selector="{{AdminMessagesSection.error}}" userInput="The password entered for the current user is invalid. Verify the password and try again." stepKey="seeInvalidPasswordError"/> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt2"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserSecondAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt3"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserThirdAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt4"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFourthAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt5"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFifthAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt6"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserSixthAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> <!-- Check Error that account has been locked --> @@ -57,6 +105,6 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> <waitForPageLoad stepKey="waitForError"/> <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" - stepKey="seeLockUserError2"/> + stepKey="seeLoginUserError"/> </test> </tests> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml index c4cfe3f7f274c..4d0c58fb1e07b 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml @@ -19,6 +19,7 @@ <data name="user/data/password_confirmation" xsi:type="string">123123q</data> <data name="user/data/current_password" xsi:type="string">incorrect password</data> <data name="attempts" xsi:type="string">4</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" /> </variation> </testCase> From a1661a5effb01e5fcd3cdf846d3052d8ec8e642f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Sat, 30 Mar 2019 13:47:29 +0100 Subject: [PATCH 117/585] #22047 Add Transaction name to NewRelic based on Command name --- .../Model/NewRelicWrapper.php | 15 ++++++- .../Plugin/CommandPlugin.php | 44 +++++++++++++++++++ app/code/Magento/NewRelicReporting/etc/di.xml | 3 ++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php diff --git a/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php b/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php index 9882a1ce9b0b8..c37d3bcd2bba9 100644 --- a/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php +++ b/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php @@ -49,7 +49,7 @@ public function reportError($exception) */ public function setAppName(string $appName) { - if (extension_loaded('newrelic')) { + if ($this->isExtensionInstalled()) { newrelic_set_appname($appName); } } @@ -66,4 +66,17 @@ public function isExtensionInstalled() } return false; } + + /** + * Wrapper for 'newrelic_name_transaction' + * + * @param string $transactionName + * @return void + */ + public function setTransactionName(string $transactionName): void + { + if ($this->isExtensionInstalled()) { + newrelic_name_transaction($transactionName); + } + } } diff --git a/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php b/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php new file mode 100644 index 0000000000000..1d24ed609bef7 --- /dev/null +++ b/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\NewRelicReporting\Plugin; + +use Magento\Framework\Exception\LocalizedException; +use Magento\NewRelicReporting\Model\Config; +use Magento\NewRelicReporting\Model\NewRelicWrapper; + +class CommandPlugin +{ + /** + * @var Config + */ + private $config; + + /** + * @var NewRelicWrapper + */ + private $newRelicWrapper; + + /** + * @param Config $config + * @param NewRelicWrapper $newRelicWrapper + */ + public function __construct( + Config $config, + NewRelicWrapper $newRelicWrapper + ) { + $this->config = $config; + $this->newRelicWrapper = $newRelicWrapper; + } + + public function beforeRun(\Symfony\Component\Console\Command\Command $command, ...$args) + { + $this->newRelicWrapper->setTransactionName( + sprintf('CLI %s', $command->getName()) + ); + + return $args; + } +} diff --git a/app/code/Magento/NewRelicReporting/etc/di.xml b/app/code/Magento/NewRelicReporting/etc/di.xml index bab7d6611f14b..15516f6df89be 100644 --- a/app/code/Magento/NewRelicReporting/etc/di.xml +++ b/app/code/Magento/NewRelicReporting/etc/di.xml @@ -40,4 +40,7 @@ </argument> </arguments> </type> + <type name="Symfony\Component\Console\Command\Command"> + <plugin name="newrelic-describe-commands" type="Magento\NewRelicReporting\Plugin\CommandPlugin"/> + </type> </config> From 07f8a65073331732f511c61fb66954365e2ada11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Sat, 30 Mar 2019 13:47:54 +0100 Subject: [PATCH 118/585] Remove unused `use` section --- app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php b/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php index 1d24ed609bef7..065455e2a27c3 100644 --- a/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php +++ b/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php @@ -5,7 +5,6 @@ */ namespace Magento\NewRelicReporting\Plugin; -use Magento\Framework\Exception\LocalizedException; use Magento\NewRelicReporting\Model\Config; use Magento\NewRelicReporting\Model\NewRelicWrapper; From 638b73a514788822c19d8506763f79c0ac5a70b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Sat, 30 Mar 2019 13:50:23 +0100 Subject: [PATCH 119/585] Cleanup for Wrapper --- .../Model/NewRelicWrapper.php | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php b/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php index c37d3bcd2bba9..bce42b4e90074 100644 --- a/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php +++ b/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php @@ -21,7 +21,7 @@ class NewRelicWrapper */ public function addCustomParameter($param, $value) { - if (extension_loaded('newrelic')) { + if ($this->isExtensionInstalled()) { newrelic_add_custom_parameter($param, $value); return true; } @@ -36,7 +36,7 @@ public function addCustomParameter($param, $value) */ public function reportError($exception) { - if (extension_loaded('newrelic')) { + if ($this->isExtensionInstalled()) { newrelic_notice_error($exception->getMessage(), $exception); } } @@ -55,28 +55,28 @@ public function setAppName(string $appName) } /** - * Checks whether newrelic-php5 agent is installed + * Wrapper for 'newrelic_name_transaction' * - * @return bool + * @param string $transactionName + * @return void */ - public function isExtensionInstalled() + public function setTransactionName(string $transactionName): void { - if (extension_loaded('newrelic')) { - return true; + if ($this->isExtensionInstalled()) { + newrelic_name_transaction($transactionName); } - return false; } /** - * Wrapper for 'newrelic_name_transaction' + * Checks whether newrelic-php5 agent is installed * - * @param string $transactionName - * @return void + * @return bool */ - public function setTransactionName(string $transactionName): void + public function isExtensionInstalled() { - if ($this->isExtensionInstalled()) { - newrelic_name_transaction($transactionName); + if (extension_loaded('newrelic')) { + return true; } + return false; } } From 2038d7d00ae6428fd4aea976f275ff01924eecee Mon Sep 17 00:00:00 2001 From: Sergey Nezbritskiy <sergeyn@corra.com> Date: Thu, 28 Mar 2019 10:23:27 +0200 Subject: [PATCH 120/585] Flush totalRecords when clearing data collection --- .../Entity/Collection/AbstractCollection.php | 13 +----------- .../Adminhtml/Edit/Tab/View/CartTest.php | 11 ---------- .../Magento/Framework/Data/Collection.php | 1 + .../Test/Unit/Data/CollectionTest.php | 21 +++++++++++++++++++ 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index dad420ea0b375..247ee2d5423cd 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -395,7 +395,7 @@ public function addAttributeToFilter($attribute, $condition = null, $joinType = if (!empty($conditionSql)) { $this->getSelect()->where($conditionSql, null, \Magento\Framework\DB\Select::TYPE_CONDITION); - $this->invalidateSize(); + $this->_totalRecords = null; } else { throw new \Magento\Framework\Exception\LocalizedException( __('Invalid attribute identifier for filter (%1)', get_class($attribute)) @@ -1720,15 +1720,4 @@ public function removeAllFieldsFromSelect() return $this->removeAttributeToSelect(); } - /** - * Invalidates "Total Records Count". - * Invalidates saved "Total Records Count" attribute with last counting, - * so a next calling of method getSize() will query new total records count. - * - * @return void - */ - private function invalidateSize(): void - { - $this->_totalRecords = null; - } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php index 3bb10baff6572..396d3b60e4f20 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php @@ -100,15 +100,4 @@ public function testToHtmlCartItem() $this->assertContains('$10.00', $html); $this->assertContains('catalog/product/edit/id/1', $html); } - - /** - * Verify that the customer has a single item in his cart. - * - * @magentoDataFixture Magento/Customer/_files/customer.php - * @magentoDataFixture Magento/Customer/_files/quote.php - */ - public function testGetCollection() - { - $this->assertEquals(1, $this->block->getCollection()->getSize()); - } } diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index dbafc9734e091..82f0ee1da464a 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -492,6 +492,7 @@ public function clear() { $this->_setIsLoaded(false); $this->_items = []; + $this->_totalRecords = null; return $this; } diff --git a/lib/internal/Magento/Framework/Test/Unit/Data/CollectionTest.php b/lib/internal/Magento/Framework/Test/Unit/Data/CollectionTest.php index 75f8b1cd0633f..913d5a577e62a 100644 --- a/lib/internal/Magento/Framework/Test/Unit/Data/CollectionTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/Data/CollectionTest.php @@ -57,6 +57,27 @@ public function testWalk() ); } + /** + * Ensure that getSize works correctly with clear + * + */ + public function testClearTotalRecords() + { + $objOne = new \Magento\Framework\DataObject(['id' => 1, 'name' => 'one']); + $objTwo = new \Magento\Framework\DataObject(['id' => 2, 'name' => 'two']); + $objThree = new \Magento\Framework\DataObject(['id' => 3, 'name' => 'three']); + + /** @noinspection PhpUnhandledExceptionInspection */ + $this->collection->addItem($objOne); + /** @noinspection PhpUnhandledExceptionInspection */ + $this->collection->addItem($objTwo); + /** @noinspection PhpUnhandledExceptionInspection */ + $this->collection->addItem($objThree); + $this->assertEquals(3, $this->collection->getSize()); + $this->collection->clear(); + $this->assertEquals(0, $this->collection->getSize()); + } + /** * Callback function. * From f3d4d9611fdbbec3c4eddca917e86e3fae272f0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20F=C3=BChr?= <d.fuehr@techdivision.com> Date: Mon, 1 Apr 2019 10:27:38 +0200 Subject: [PATCH 121/585] changes due to backword compatiblity constraints --- .../Magento/Framework/Validator/Factory.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Validator/Factory.php b/lib/internal/Magento/Framework/Validator/Factory.php index 198f4fb6730fa..87c29dd6681c3 100644 --- a/lib/internal/Magento/Framework/Validator/Factory.php +++ b/lib/internal/Magento/Framework/Validator/Factory.php @@ -10,12 +10,20 @@ use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Phrase; use Magento\Framework\Validator; +use Magento\Framework\Cache\FrontendInterface; /** * Factory for \Magento\Framework\Validator and \Magento\Framework\Validator\Builder. */ class Factory { + /** + * cache key + * + * @deprecated + */ + const CACHE_KEY = __CLASS__; + /** * @var ObjectManagerInterface */ @@ -26,7 +34,7 @@ class Factory * * @var iterable|null */ - protected $_configFiles; + protected $_configFiles = null; /** * @var bool @@ -43,10 +51,12 @@ class Factory * * @param ObjectManagerInterface $objectManager * @param Reader $moduleReader + * @param FrontendInterface $cache @deprecated */ public function __construct( ObjectManagerInterface $objectManager, - Reader $moduleReader + Reader $moduleReader, + FrontendInterface $cache ) { $this->_objectManager = $objectManager; $this->moduleReader = $moduleReader; From c0255a1521c2ee3ea2471f2a78f0c845a8d0457b Mon Sep 17 00:00:00 2001 From: Ivan Gerchak <ivang@ven.com> Date: Mon, 1 Apr 2019 12:50:17 +0300 Subject: [PATCH 122/585] Remove fotorama.min.js --- lib/web/fotorama/fotorama.min.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 lib/web/fotorama/fotorama.min.js diff --git a/lib/web/fotorama/fotorama.min.js b/lib/web/fotorama/fotorama.min.js deleted file mode 100644 index 0a0cbd9db7e74..0000000000000 --- a/lib/web/fotorama/fotorama.min.js +++ /dev/null @@ -1 +0,0 @@ -fotoramaVersion="4.6.4";(function(window,document,location,$,undefined){"use strict";var _fotoramaClass="fotorama",_fullscreenClass="fotorama__fullscreen",wrapClass=_fotoramaClass+"__wrap",wrapCss2Class=wrapClass+"--css2",wrapCss3Class=wrapClass+"--css3",wrapVideoClass=wrapClass+"--video",wrapFadeClass=wrapClass+"--fade",wrapSlideClass=wrapClass+"--slide",wrapNoControlsClass=wrapClass+"--no-controls",wrapNoShadowsClass=wrapClass+"--no-shadows",wrapPanYClass=wrapClass+"--pan-y",wrapRtlClass=wrapClass+"--rtl",wrapOnlyActiveClass=wrapClass+"--only-active",wrapNoCaptionsClass=wrapClass+"--no-captions",wrapToggleArrowsClass=wrapClass+"--toggle-arrows",stageClass=_fotoramaClass+"__stage",stageFrameClass=stageClass+"__frame",stageFrameVideoClass=stageFrameClass+"--video",stageShaftClass=stageClass+"__shaft",grabClass=_fotoramaClass+"__grab",pointerClass=_fotoramaClass+"__pointer",arrClass=_fotoramaClass+"__arr",arrDisabledClass=arrClass+"--disabled",arrPrevClass=arrClass+"--prev",arrNextClass=arrClass+"--next",navClass=_fotoramaClass+"__nav",navWrapClass=navClass+"-wrap",navShaftClass=navClass+"__shaft",navShaftVerticalClass=navWrapClass+"--vertical",navShaftListClass=navWrapClass+"--list",navShafthorizontalClass=navWrapClass+"--horizontal",navDotsClass=navClass+"--dots",navThumbsClass=navClass+"--thumbs",navFrameClass=navClass+"__frame",fadeClass=_fotoramaClass+"__fade",fadeFrontClass=fadeClass+"-front",fadeRearClass=fadeClass+"-rear",shadowClass=_fotoramaClass+"__shadow",shadowsClass=shadowClass+"s",shadowsLeftClass=shadowsClass+"--left",shadowsRightClass=shadowsClass+"--right",shadowsTopClass=shadowsClass+"--top",shadowsBottomClass=shadowsClass+"--bottom",activeClass=_fotoramaClass+"__active",selectClass=_fotoramaClass+"__select",hiddenClass=_fotoramaClass+"--hidden",fullscreenClass=_fotoramaClass+"--fullscreen",fullscreenIconClass=_fotoramaClass+"__fullscreen-icon",errorClass=_fotoramaClass+"__error",loadingClass=_fotoramaClass+"__loading",loadedClass=_fotoramaClass+"__loaded",loadedFullClass=loadedClass+"--full",loadedImgClass=loadedClass+"--img",grabbingClass=_fotoramaClass+"__grabbing",imgClass=_fotoramaClass+"__img",imgFullClass=imgClass+"--full",thumbClass=_fotoramaClass+"__thumb",thumbArrLeft=thumbClass+"__arr--left",thumbArrRight=thumbClass+"__arr--right",thumbBorderClass=thumbClass+"-border",htmlClass=_fotoramaClass+"__html",videoContainerClass=_fotoramaClass+"-video-container",videoClass=_fotoramaClass+"__video",videoPlayClass=videoClass+"-play",videoCloseClass=videoClass+"-close",horizontalImageClass=_fotoramaClass+"_horizontal_ratio",verticalImageClass=_fotoramaClass+"_vertical_ratio",fotoramaSpinnerClass=_fotoramaClass+"__spinner",spinnerShowClass=fotoramaSpinnerClass+"--show";var JQUERY_VERSION=$&&$.fn.jquery.split(".");if(!JQUERY_VERSION||JQUERY_VERSION[0]<1||JQUERY_VERSION[0]==1&&JQUERY_VERSION[1]<8){throw"Fotorama requires jQuery 1.8 or later and will not run without it."}var _={};var Modernizr=function(window,document,undefined){var version="2.8.3",Modernizr={},docElement=document.documentElement,mod="modernizr",modElem=document.createElement(mod),mStyle=modElem.style,inputElem,toString={}.toString,prefixes=" -webkit- -moz- -o- -ms- ".split(" "),omPrefixes="Webkit Moz O ms",cssomPrefixes=omPrefixes.split(" "),domPrefixes=omPrefixes.toLowerCase().split(" "),tests={},inputs={},attrs={},classes=[],slice=classes.slice,featureName,injectElementWithStyles=function(rule,callback,nodes,testnames){var style,ret,node,docOverflow,div=document.createElement("div"),body=document.body,fakeBody=body||document.createElement("body");if(parseInt(nodes,10)){while(nodes--){node=document.createElement("div");node.id=testnames?testnames[nodes]:mod+(nodes+1);div.appendChild(node)}}style=["­",'<style id="s',mod,'">',rule,"</style>"].join("");div.id=mod;(body?div:fakeBody).innerHTML+=style;fakeBody.appendChild(div);if(!body){fakeBody.style.background="";fakeBody.style.overflow="hidden";docOverflow=docElement.style.overflow;docElement.style.overflow="hidden";docElement.appendChild(fakeBody)}ret=callback(div,rule);if(!body){fakeBody.parentNode.removeChild(fakeBody);docElement.style.overflow=docOverflow}else{div.parentNode.removeChild(div)}return!!ret},_hasOwnProperty={}.hasOwnProperty,hasOwnProp;if(!is(_hasOwnProperty,"undefined")&&!is(_hasOwnProperty.call,"undefined")){hasOwnProp=function(object,property){return _hasOwnProperty.call(object,property)}}else{hasOwnProp=function(object,property){return property in object&&is(object.constructor.prototype[property],"undefined")}}if(!Function.prototype.bind){Function.prototype.bind=function bind(that){var target=this;if(typeof target!="function"){throw new TypeError}var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var F=function(){};F.prototype=target.prototype;var self=new F;var result=target.apply(self,args.concat(slice.call(arguments)));if(Object(result)===result){return result}return self}else{return target.apply(that,args.concat(slice.call(arguments)))}};return bound}}function setCss(str){mStyle.cssText=str}function setCssAll(str1,str2){return setCss(prefixes.join(str1+";")+(str2||""))}function is(obj,type){return typeof obj===type}function contains(str,substr){return!!~(""+str).indexOf(substr)}function testProps(props,prefixed){for(var i in props){var prop=props[i];if(!contains(prop,"-")&&mStyle[prop]!==undefined){return prefixed=="pfx"?prop:true}}return false}function testDOMProps(props,obj,elem){for(var i in props){var item=obj[props[i]];if(item!==undefined){if(elem===false)return props[i];if(is(item,"function")){return item.bind(elem||obj)}return item}}return false}function testPropsAll(prop,prefixed,elem){var ucProp=prop.charAt(0).toUpperCase()+prop.slice(1),props=(prop+" "+cssomPrefixes.join(ucProp+" ")+ucProp).split(" ");if(is(prefixed,"string")||is(prefixed,"undefined")){return testProps(props,prefixed)}else{props=(prop+" "+domPrefixes.join(ucProp+" ")+ucProp).split(" ");return testDOMProps(props,prefixed,elem)}}tests["touch"]=function(){var bool;if("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch){bool=true}else{injectElementWithStyles(["@media (",prefixes.join("touch-enabled),("),mod,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(node){bool=node.offsetTop===9})}return bool};tests["csstransforms3d"]=function(){var ret=!!testPropsAll("perspective");if(ret&&"webkitPerspective"in docElement.style){injectElementWithStyles("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(node,rule){ret=node.offsetLeft===9&&node.offsetHeight===3})}return ret};tests["csstransitions"]=function(){return testPropsAll("transition")};for(var feature in tests){if(hasOwnProp(tests,feature)){featureName=feature.toLowerCase();Modernizr[featureName]=tests[feature]();classes.push((Modernizr[featureName]?"":"no-")+featureName)}}Modernizr.addTest=function(feature,test){if(typeof feature=="object"){for(var key in feature){if(hasOwnProp(feature,key)){Modernizr.addTest(key,feature[key])}}}else{feature=feature.toLowerCase();if(Modernizr[feature]!==undefined){return Modernizr}test=typeof test=="function"?test():test;if(typeof enableClasses!=="undefined"&&enableClasses){docElement.className+=" "+(test?"":"no-")+feature}Modernizr[feature]=test}return Modernizr};setCss("");modElem=inputElem=null;Modernizr._version=version;Modernizr._prefixes=prefixes;Modernizr._domPrefixes=domPrefixes;Modernizr._cssomPrefixes=cssomPrefixes;Modernizr.testProp=function(prop){return testProps([prop])};Modernizr.testAllProps=testPropsAll;Modernizr.testStyles=injectElementWithStyles;Modernizr.prefixed=function(prop,obj,elem){if(!obj){return testPropsAll(prop,"pfx")}else{return testPropsAll(prop,obj,elem)}};return Modernizr}(window,document);var fullScreenApi={ok:false,is:function(){return false},request:function(){},cancel:function(){},event:"",prefix:""},browserPrefixes="webkit moz o ms khtml".split(" ");if(typeof document.cancelFullScreen!="undefined"){fullScreenApi.ok=true}else{for(var i=0,il=browserPrefixes.length;i<il;i++){fullScreenApi.prefix=browserPrefixes[i];if(typeof document[fullScreenApi.prefix+"CancelFullScreen"]!="undefined"){fullScreenApi.ok=true;break}}}if(fullScreenApi.ok){fullScreenApi.event=fullScreenApi.prefix+"fullscreenchange";fullScreenApi.is=function(){switch(this.prefix){case"":return document.fullScreen;case"webkit":return document.webkitIsFullScreen;default:return document[this.prefix+"FullScreen"]}};fullScreenApi.request=function(el){return this.prefix===""?el.requestFullScreen():el[this.prefix+"RequestFullScreen"]()};fullScreenApi.cancel=function(el){return this.prefix===""?document.cancelFullScreen():document[this.prefix+"CancelFullScreen"]()}}function bez(coOrdArray){var encodedFuncName="bez_"+$.makeArray(arguments).join("_").replace(".","p");if(typeof $["easing"][encodedFuncName]!=="function"){var polyBez=function(p1,p2){var A=[null,null],B=[null,null],C=[null,null],bezCoOrd=function(t,ax){C[ax]=3*p1[ax];B[ax]=3*(p2[ax]-p1[ax])-C[ax];A[ax]=1-C[ax]-B[ax];return t*(C[ax]+t*(B[ax]+t*A[ax]))},xDeriv=function(t){return C[0]+t*(2*B[0]+3*A[0]*t)},xForT=function(t){var x=t,i=0,z;while(++i<14){z=bezCoOrd(x,0)-t;if(Math.abs(z)<.001)break;x-=z/xDeriv(x)}return x};return function(t){return bezCoOrd(xForT(t),1)}};$["easing"][encodedFuncName]=function(x,t,b,c,d){return c*polyBez([coOrdArray[0],coOrdArray[1]],[coOrdArray[2],coOrdArray[3]])(t/d)+b}}return encodedFuncName}var $WINDOW=$(window),$DOCUMENT=$(document),$HTML,$BODY,QUIRKS_FORCE=location.hash.replace("#","")==="quirks",TRANSFORMS3D=Modernizr.csstransforms3d,CSS3=TRANSFORMS3D&&!QUIRKS_FORCE,COMPAT=TRANSFORMS3D||document.compatMode==="CSS1Compat",FULLSCREEN=fullScreenApi.ok,MOBILE=navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i),SLOW=!CSS3||MOBILE,MS_POINTER=navigator.msPointerEnabled,WHEEL="onwheel"in document.createElement("div")?"wheel":document.onmousewheel!==undefined?"mousewheel":"DOMMouseScroll",TOUCH_TIMEOUT=250,TRANSITION_DURATION=300,SCROLL_LOCK_TIMEOUT=1400,AUTOPLAY_INTERVAL=5e3,MARGIN=2,THUMB_SIZE=64,WIDTH=500,HEIGHT=333,STAGE_FRAME_KEY="$stageFrame",NAV_DOT_FRAME_KEY="$navDotFrame",NAV_THUMB_FRAME_KEY="$navThumbFrame",AUTO="auto",BEZIER=bez([.1,0,.25,1]),MAX_WIDTH=1200,thumbsPerSlide=1,OPTIONS={width:null,minwidth:null,maxwidth:"100%",height:null,minheight:null,maxheight:null,ratio:null,margin:MARGIN,nav:"dots",navposition:"bottom",navwidth:null,thumbwidth:THUMB_SIZE,thumbheight:THUMB_SIZE,thumbmargin:MARGIN,thumbborderwidth:MARGIN,allowfullscreen:false,transition:"slide",clicktransition:null,transitionduration:TRANSITION_DURATION,captions:true,startindex:0,loop:false,autoplay:false,stopautoplayontouch:true,keyboard:false,arrows:true,click:true,swipe:false,trackpad:false,shuffle:false,direction:"ltr",shadows:true,showcaption:true,navdir:"horizontal",navarrows:true,navtype:"thumbs"},KEYBOARD_OPTIONS={left:true,right:true,down:true,up:true,space:false,home:false,end:false};function noop(){}function minMaxLimit(value,min,max){return Math.max(isNaN(min)?-Infinity:min,Math.min(isNaN(max)?Infinity:max,value))}function readTransform(css,dir){return css.match(/ma/)&&css.match(/-?\d+(?!d)/g)[css.match(/3d/)?dir==="vertical"?13:12:dir==="vertical"?5:4]}function readPosition($el,dir){if(CSS3){return+readTransform($el.css("transform"),dir)}else{return+$el.css(dir==="vertical"?"top":"left").replace("px","")}}function getTranslate(pos,direction){var obj={};if(CSS3){switch(direction){case"vertical":obj.transform="translate3d(0, "+pos+"px,0)";break;case"list":break;default:obj.transform="translate3d("+pos+"px,0,0)";break}}else{direction==="vertical"?obj.top=pos:obj.left=pos}return obj}function getDuration(time){return{"transition-duration":time+"ms"}}function unlessNaN(value,alternative){return isNaN(value)?alternative:value}function numberFromMeasure(value,measure){return unlessNaN(+String(value).replace(measure||"px",""))}function numberFromPercent(value){return/%$/.test(value)?numberFromMeasure(value,"%"):undefined}function numberFromWhatever(value,whole){return unlessNaN(numberFromPercent(value)/100*whole,numberFromMeasure(value))}function measureIsValid(value){return(!isNaN(numberFromMeasure(value))||!isNaN(numberFromMeasure(value,"%")))&&value}function getPosByIndex(index,side,margin,baseIndex){return(index-(baseIndex||0))*(side+(margin||0))}function getIndexByPos(pos,side,margin,baseIndex){return-Math.round(pos/(side+(margin||0))-(baseIndex||0))}function bindTransitionEnd($el){var elData=$el.data();if(elData.tEnd)return;var el=$el[0],transitionEndEvent={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",msTransition:"MSTransitionEnd",transition:"transitionend"};addEvent(el,transitionEndEvent[Modernizr.prefixed("transition")],function(e){elData.tProp&&e.propertyName.match(elData.tProp)&&elData.onEndFn()});elData.tEnd=true}function afterTransition($el,property,fn,time){var ok,elData=$el.data();if(elData){elData.onEndFn=function(){if(ok)return;ok=true;clearTimeout(elData.tT);fn()};elData.tProp=property;clearTimeout(elData.tT);elData.tT=setTimeout(function(){elData.onEndFn()},time*1.5);bindTransitionEnd($el)}}function stop($el,pos){var dir=$el.navdir||"horizontal";if($el.length){var elData=$el.data();if(CSS3){$el.css(getDuration(0));elData.onEndFn=noop;clearTimeout(elData.tT)}else{$el.stop()}var lockedPos=getNumber(pos,function(){return readPosition($el,dir)});$el.css(getTranslate(lockedPos,dir));return lockedPos}}function getNumber(){var number;for(var _i=0,_l=arguments.length;_i<_l;_i++){number=_i?arguments[_i]():arguments[_i];if(typeof number==="number"){break}}return number}function edgeResistance(pos,edge){return Math.round(pos+(edge-pos)/1.5)}function getProtocol(){getProtocol.p=getProtocol.p||(location.protocol==="https:"?"https://":"http://");return getProtocol.p}function parseHref(href){var a=document.createElement("a");a.href=href;return a}function findVideoId(href,forceVideo){if(typeof href!=="string")return href;href=parseHref(href);var id,type;if(href.host.match(/youtube\.com/)&&href.search){id=href.search.split("v=")[1];if(id){var ampersandPosition=id.indexOf("&");if(ampersandPosition!==-1){id=id.substring(0,ampersandPosition)}type="youtube"}}else if(href.host.match(/youtube\.com|youtu\.be/)){id=href.pathname.replace(/^\/(embed\/|v\/)?/,"").replace(/\/.*/,"");type="youtube"}else if(href.host.match(/vimeo\.com/)){type="vimeo";id=href.pathname.replace(/^\/(video\/)?/,"").replace(/\/.*/,"")}if((!id||!type)&&forceVideo){id=href.href;type="custom"}return id?{id:id,type:type,s:href.search.replace(/^\?/,""),p:getProtocol()}:false}function getVideoThumbs(dataFrame,data,fotorama){var img,thumb,video=dataFrame.video;if(video.type==="youtube"){thumb=getProtocol()+"img.youtube.com/vi/"+video.id+"/default.jpg";img=thumb.replace(/\/default.jpg$/,"/hqdefault.jpg");dataFrame.thumbsReady=true}else if(video.type==="vimeo"){$.ajax({url:getProtocol()+"vimeo.com/api/v2/video/"+video.id+".json",dataType:"jsonp",success:function(json){dataFrame.thumbsReady=true;updateData(data,{img:json[0].thumbnail_large,thumb:json[0].thumbnail_small},dataFrame.i,fotorama)}})}else{dataFrame.thumbsReady=true}return{img:img,thumb:thumb}}function updateData(data,_dataFrame,i,fotorama){for(var _i=0,_l=data.length;_i<_l;_i++){var dataFrame=data[_i];if(dataFrame.i===i&&dataFrame.thumbsReady){var clear={videoReady:true};clear[STAGE_FRAME_KEY]=clear[NAV_THUMB_FRAME_KEY]=clear[NAV_DOT_FRAME_KEY]=false;fotorama.splice(_i,1,$.extend({},dataFrame,clear,_dataFrame));break}}}function getDataFromHtml($el){var data=[];function getDataFromImg($img,imgData,checkVideo){var $child=$img.children("img").eq(0),_imgHref=$img.attr("href"),_imgSrc=$img.attr("src"),_thumbSrc=$child.attr("src"),_video=imgData.video,video=checkVideo?findVideoId(_imgHref,_video===true):false;if(video){_imgHref=false}else{video=_video}getDimensions($img,$child,$.extend(imgData,{video:video,img:imgData.img||_imgHref||_imgSrc||_thumbSrc,thumb:imgData.thumb||_thumbSrc||_imgSrc||_imgHref}))}function getDimensions($img,$child,imgData){var separateThumbFLAG=imgData.thumb&&imgData.img!==imgData.thumb,width=numberFromMeasure(imgData.width||$img.attr("width")),height=numberFromMeasure(imgData.height||$img.attr("height"));$.extend(imgData,{width:width,height:height,thumbratio:getRatio(imgData.thumbratio||numberFromMeasure(imgData.thumbwidth||$child&&$child.attr("width")||separateThumbFLAG||width)/numberFromMeasure(imgData.thumbheight||$child&&$child.attr("height")||separateThumbFLAG||height))})}$el.children().each(function(){var $this=$(this),dataFrame=optionsToLowerCase($.extend($this.data(),{id:$this.attr("id")}));if($this.is("a, img")){getDataFromImg($this,dataFrame,true)}else if(!$this.is(":empty")){getDimensions($this,null,$.extend(dataFrame,{html:this,_html:$this.html()}))}else return;data.push(dataFrame)});return data}function isHidden(el){return el.offsetWidth===0&&el.offsetHeight===0}function isDetached(el){return!$.contains(document.documentElement,el)}function waitFor(test,fn,timeout,i){if(!waitFor.i){waitFor.i=1;waitFor.ii=[true]}i=i||waitFor.i;if(typeof waitFor.ii[i]==="undefined"){waitFor.ii[i]=true}if(test()){fn()}else{waitFor.ii[i]&&setTimeout(function(){waitFor.ii[i]&&waitFor(test,fn,timeout,i)},timeout||100)}return waitFor.i++}waitFor.stop=function(i){waitFor.ii[i]=false};function fit($el,measuresToFit){var elData=$el.data(),measures=elData.measures;if(measures&&(!elData.l||elData.l.W!==measures.width||elData.l.H!==measures.height||elData.l.r!==measures.ratio||elData.l.w!==measuresToFit.w||elData.l.h!==measuresToFit.h)){var height=minMaxLimit(measuresToFit.h,0,measures.height),width=height*measures.ratio;UTIL.setRatio($el,width,height);elData.l={W:measures.width,H:measures.height,r:measures.ratio,w:measuresToFit.w,h:measuresToFit.h}}return true}function setStyle($el,style){var el=$el[0];if(el.styleSheet){el.styleSheet.cssText=style}else{$el.html(style)}}function findShadowEdge(pos,min,max,dir){return min===max?false:dir==="vertical"?pos<=min?"top":pos>=max?"bottom":"top bottom":pos<=min?"left":pos>=max?"right":"left right"}function smartClick($el,fn,_options){_options=_options||{};$el.each(function(){var $this=$(this),thisData=$this.data(),startEvent;if(thisData.clickOn)return;thisData.clickOn=true;$.extend(touch($this,{onStart:function(e){startEvent=e;(_options.onStart||noop).call(this,e)},onMove:_options.onMove||noop,onTouchEnd:_options.onTouchEnd||noop,onEnd:function(result){if(result.moved)return;fn.call(this,startEvent)}}),{noMove:true})})}function div(classes,child){return'<div class="'+classes+'">'+(child||"")+"</div>"}function cls(className){return"."+className}function createVideoFrame(videoItem){var frame='<iframe src="'+videoItem.p+videoItem.type+".com/embed/"+videoItem.id+'" frameborder="0" allowfullscreen></iframe>';return frame}function shuffle(array){var l=array.length;while(l){var i=Math.floor(Math.random()*l--);var t=array[l];array[l]=array[i];array[i]=t}return array}function clone(array){return Object.prototype.toString.call(array)=="[object Array]"&&$.map(array,function(frame){return $.extend({},frame)})}function lockScroll($el,left,top){$el.scrollLeft(left||0).scrollTop(top||0)}function optionsToLowerCase(options){if(options){var opts={};$.each(options,function(key,value){opts[key.toLowerCase()]=value});return opts}}function getRatio(_ratio){if(!_ratio)return;var ratio=+_ratio;if(!isNaN(ratio)){return ratio}else{ratio=_ratio.split("/");return+ratio[0]/+ratio[1]||undefined}}function addEvent(el,e,fn,bool){if(!e)return;el.addEventListener?el.addEventListener(e,fn,!!bool):el.attachEvent("on"+e,fn)}function validateRestrictions(position,restriction){if(position>restriction.max){position=restriction.max}else{if(position<restriction.min){position=restriction.min}}return position}function validateSlidePos(opt,navShaftTouchTail,guessIndex,offsetNav,$guessNavFrame,$navWrap,dir){var position,size,wrapSize;if(dir==="horizontal"){size=opt.thumbwidth;wrapSize=$navWrap.width()}else{size=opt.thumbheight;wrapSize=$navWrap.height()}if((size+opt.margin)*(guessIndex+1)>=wrapSize-offsetNav){if(dir==="horizontal"){position=-$guessNavFrame.position().left}else{position=-$guessNavFrame.position().top}}else{if((size+opt.margin)*guessIndex<=Math.abs(offsetNav)){if(dir==="horizontal"){position=-$guessNavFrame.position().left+wrapSize-(size+opt.margin)}else{position=-$guessNavFrame.position().top+wrapSize-(size+opt.margin)}}else{position=offsetNav}}position=validateRestrictions(position,navShaftTouchTail);return position||0}function elIsDisabled(el){return!!el.getAttribute("disabled")}function disableAttr(FLAG,disable){if(disable){return{disabled:FLAG}}else{return{tabindex:FLAG*-1+"",disabled:FLAG}}}function addEnterUp(el,fn){addEvent(el,"keyup",function(e){elIsDisabled(el)||e.keyCode==13&&fn.call(el,e)})}function addFocus(el,fn){addEvent(el,"focus",el.onfocusin=function(e){fn.call(el,e)},true)}function stopEvent(e,stopPropagation){e.preventDefault?e.preventDefault():e.returnValue=false;stopPropagation&&e.stopPropagation&&e.stopPropagation()}function stubEvent($el,eventType){var isIOS=/ip(ad|hone|od)/i.test(window.navigator.userAgent);if(isIOS&&eventType==="touchend"){$el.on("touchend",function(e){$DOCUMENT.trigger("mouseup",e)})}$el.on(eventType,function(e){stopEvent(e,true);return false})}function getDirectionSign(forward){return forward?">":"<"}var UTIL=function(){function setRatioClass($el,wh,ht){var rateImg=wh/ht;if(rateImg<=1){$el.parent().removeClass(horizontalImageClass);$el.parent().addClass(verticalImageClass)}else{$el.parent().removeClass(verticalImageClass);$el.parent().addClass(horizontalImageClass)}}function setThumbAttr($frame,value,searchAttr){var attr=searchAttr;if(!$frame.attr(attr)&&$frame.attr(attr)!==undefined){$frame.attr(attr,value)}if($frame.find("["+attr+"]").length){$frame.find("["+attr+"]").each(function(){$(this).attr(attr,value)})}}function isExpectedCaption(frameItem,isExpected,undefined){var expected=false,frameExpected;frameItem.showCaption===undefined||frameItem.showCaption===true?frameExpected=true:frameExpected=false;if(!isExpected){return false}if(frameItem.caption&&frameExpected){expected=true}return expected}return{setRatio:setRatioClass,setThumbAttr:setThumbAttr,isExpectedCaption:isExpectedCaption}}(UTIL||{},jQuery);function slide($el,options){var elData=$el.data(),elPos=Math.round(options.pos),onEndFn=function(){if(elData&&elData.sliding){elData.sliding=false}(options.onEnd||noop)()};if(typeof options.overPos!=="undefined"&&options.overPos!==options.pos){elPos=options.overPos}var translate=$.extend(getTranslate(elPos,options.direction),options.width&&{width:options.width},options.height&&{height:options.height});if(elData&&elData.sliding){elData.sliding=true}if(CSS3){$el.css($.extend(getDuration(options.time),translate));if(options.time>10){afterTransition($el,"transform",onEndFn,options.time)}else{onEndFn()}}else{$el.stop().animate(translate,options.time,BEZIER,onEndFn)}}function fade($el1,$el2,$frames,options,fadeStack,chain){var chainedFLAG=typeof chain!=="undefined";if(!chainedFLAG){fadeStack.push(arguments);Array.prototype.push.call(arguments,fadeStack.length);if(fadeStack.length>1)return}$el1=$el1||$($el1);$el2=$el2||$($el2);var _$el1=$el1[0],_$el2=$el2[0],crossfadeFLAG=options.method==="crossfade",onEndFn=function(){if(!onEndFn.done){onEndFn.done=true;var args=(chainedFLAG||fadeStack.shift())&&fadeStack.shift();args&&fade.apply(this,args);(options.onEnd||noop)(!!args)}},time=options.time/(chain||1);$frames.removeClass(fadeRearClass+" "+fadeFrontClass);$el1.stop().addClass(fadeRearClass);$el2.stop().addClass(fadeFrontClass);crossfadeFLAG&&_$el2&&$el1.fadeTo(0,0);$el1.fadeTo(crossfadeFLAG?time:0,1,crossfadeFLAG&&onEndFn);$el2.fadeTo(time,0,onEndFn);_$el1&&crossfadeFLAG||_$el2||onEndFn()}var lastEvent,moveEventType,preventEvent,preventEventTimeout,dragDomEl;function extendEvent(e){var touch=(e.touches||[])[0]||e;e._x=touch.pageX||touch.originalEvent.pageX;e._y=touch.clientY||touch.originalEvent.clientY;e._now=$.now()}function touch($el,options){var el=$el[0],tail={},touchEnabledFLAG,startEvent,$target,controlTouch,touchFLAG,targetIsSelectFLAG,targetIsLinkFlag,tolerance,moved;function onStart(e){$target=$(e.target);tail.checked=targetIsSelectFLAG=targetIsLinkFlag=moved=false;if(touchEnabledFLAG||tail.flow||e.touches&&e.touches.length>1||e.which>1||lastEvent&&lastEvent.type!==e.type&&preventEvent||(targetIsSelectFLAG=options.select&&$target.is(options.select,el)))return targetIsSelectFLAG;touchFLAG=e.type==="touchstart";targetIsLinkFlag=$target.is("a, a *",el);controlTouch=tail.control;tolerance=tail.noMove||tail.noSwipe||controlTouch?16:!tail.snap?4:0;extendEvent(e);startEvent=lastEvent=e;moveEventType=e.type.replace(/down|start/,"move").replace(/Down/,"Move");(options.onStart||noop).call(el,e,{control:controlTouch,$target:$target});touchEnabledFLAG=tail.flow=true;if(!touchFLAG||tail.go)stopEvent(e)}function onMove(e){if(e.touches&&e.touches.length>1||MS_POINTER&&!e.isPrimary||moveEventType!==e.type||!touchEnabledFLAG){touchEnabledFLAG&&onEnd();(options.onTouchEnd||noop)();return}extendEvent(e);var xDiff=Math.abs(e._x-startEvent._x),yDiff=Math.abs(e._y-startEvent._y),xyDiff=xDiff-yDiff,xWin=(tail.go||tail.x||xyDiff>=0)&&!tail.noSwipe,yWin=xyDiff<0;if(touchFLAG&&!tail.checked){if(touchEnabledFLAG=xWin){stopEvent(e)}}else{stopEvent(e);if(movedEnough(xDiff,yDiff)){(options.onMove||noop).call(el,e,{touch:touchFLAG})}}if(!moved&&movedEnough(xDiff,yDiff)&&Math.sqrt(Math.pow(xDiff,2)+Math.pow(yDiff,2))>tolerance){moved=true}tail.checked=tail.checked||xWin||yWin}function movedEnough(xDiff,yDiff){return xDiff>yDiff&&xDiff>1.5}function onEnd(e){(options.onTouchEnd||noop)();var _touchEnabledFLAG=touchEnabledFLAG;tail.control=touchEnabledFLAG=false;if(_touchEnabledFLAG){tail.flow=false}if(!_touchEnabledFLAG||targetIsLinkFlag&&!tail.checked)return;e&&stopEvent(e);preventEvent=true;clearTimeout(preventEventTimeout);preventEventTimeout=setTimeout(function(){preventEvent=false},1e3);(options.onEnd||noop).call(el,{moved:moved,$target:$target,control:controlTouch,touch:touchFLAG,startEvent:startEvent,aborted:!e||e.type==="MSPointerCancel"})}function onOtherStart(){if(tail.flow)return;tail.flow=true}function onOtherEnd(){if(!tail.flow)return;tail.flow=false}if(MS_POINTER){addEvent(el,"MSPointerDown",onStart);addEvent(document,"MSPointerMove",onMove);addEvent(document,"MSPointerCancel",onEnd);addEvent(document,"MSPointerUp",onEnd)}else{addEvent(el,"touchstart",onStart);addEvent(el,"touchmove",onMove);addEvent(el,"touchend",onEnd);addEvent(document,"touchstart",onOtherStart);addEvent(document,"touchend",onOtherEnd);addEvent(document,"touchcancel",onOtherEnd);$WINDOW.on("scroll",onOtherEnd);$el.on("mousedown pointerdown",onStart);$DOCUMENT.on("mousemove pointermove",onMove).on("mouseup pointerup",onEnd)}if(Modernizr.touch){dragDomEl="a"}else{dragDomEl="div"}$el.on("click",dragDomEl,function(e){tail.checked&&stopEvent(e)});return tail}function moveOnTouch($el,options){var el=$el[0],elData=$el.data(),tail={},startCoo,coo,startElPos,moveElPos,edge,moveTrack,startTime,endTime,min,max,snap,dir,slowFLAG,controlFLAG,moved,tracked;function startTracking(e,noStop){tracked=true;startCoo=coo=dir==="vertical"?e._y:e._x;startTime=e._now;moveTrack=[[startTime,startCoo]];startElPos=moveElPos=tail.noMove||noStop?0:stop($el,(options.getPos||noop)());(options.onStart||noop).call(el,e)}function onStart(e,result){min=tail.min;max=tail.max;snap=tail.snap,dir=tail.direction||"horizontal",$el.navdir=dir;slowFLAG=e.altKey;tracked=moved=false;controlFLAG=result.control;if(!controlFLAG&&!elData.sliding){startTracking(e)}}function onMove(e,result){if(!tail.noSwipe){if(!tracked){startTracking(e)}coo=dir==="vertical"?e._y:e._x;moveTrack.push([e._now,coo]);moveElPos=startElPos-(startCoo-coo);edge=findShadowEdge(moveElPos,min,max,dir);if(moveElPos<=min){moveElPos=edgeResistance(moveElPos,min)}else if(moveElPos>=max){moveElPos=edgeResistance(moveElPos,max)}if(!tail.noMove){$el.css(getTranslate(moveElPos,dir));if(!moved){moved=true;result.touch||MS_POINTER||$el.addClass(grabbingClass)}(options.onMove||noop).call(el,e,{pos:moveElPos,edge:edge})}}}function onEnd(result){if(tail.noSwipe&&result.moved)return;if(!tracked){startTracking(result.startEvent,true)}result.touch||MS_POINTER||$el.removeClass(grabbingClass);endTime=$.now();var _backTimeIdeal=endTime-TOUCH_TIMEOUT,_backTime,_timeDiff,_timeDiffLast,backTime=null,backCoo,virtualPos,limitPos,newPos,overPos,time=TRANSITION_DURATION,speed,friction=options.friction;for(var _i=moveTrack.length-1;_i>=0;_i--){_backTime=moveTrack[_i][0];_timeDiff=Math.abs(_backTime-_backTimeIdeal);if(backTime===null||_timeDiff<_timeDiffLast){backTime=_backTime;backCoo=moveTrack[_i][1]}else if(backTime===_backTimeIdeal||_timeDiff>_timeDiffLast){break}_timeDiffLast=_timeDiff}newPos=minMaxLimit(moveElPos,min,max);var cooDiff=backCoo-coo,forwardFLAG=cooDiff>=0,timeDiff=endTime-backTime,longTouchFLAG=timeDiff>TOUCH_TIMEOUT,swipeFLAG=!longTouchFLAG&&moveElPos!==startElPos&&newPos===moveElPos;if(snap){newPos=minMaxLimit(Math[swipeFLAG?forwardFLAG?"floor":"ceil":"round"](moveElPos/snap)*snap,min,max);min=max=newPos}if(swipeFLAG&&(snap||newPos===moveElPos)){speed=-(cooDiff/timeDiff);time*=minMaxLimit(Math.abs(speed),options.timeLow,options.timeHigh);virtualPos=Math.round(moveElPos+speed*time/friction);if(!snap){newPos=virtualPos}if(!forwardFLAG&&virtualPos>max||forwardFLAG&&virtualPos<min){limitPos=forwardFLAG?min:max;overPos=virtualPos-limitPos;if(!snap){newPos=limitPos}overPos=minMaxLimit(newPos+overPos*.03,limitPos-50,limitPos+50);time=Math.abs((moveElPos-overPos)/(speed/friction))}}time*=slowFLAG?10:1;(options.onEnd||noop).call(el,$.extend(result,{moved:result.moved||longTouchFLAG&&snap,pos:moveElPos,newPos:newPos,overPos:overPos,time:time,dir:dir}))}tail=$.extend(touch(options.$wrap,$.extend({},options,{onStart:onStart,onMove:onMove,onEnd:onEnd})),tail);return tail}function wheel($el,options){var el=$el[0],lockFLAG,lastDirection,lastNow,tail={prevent:{}};addEvent(el,WHEEL,function(e){var yDelta=e.wheelDeltaY||-1*e.deltaY||0,xDelta=e.wheelDeltaX||-1*e.deltaX||0,xWin=Math.abs(xDelta)&&!Math.abs(yDelta),direction=getDirectionSign(xDelta<0),sameDirection=lastDirection===direction,now=$.now(),tooFast=now-lastNow<TOUCH_TIMEOUT;lastDirection=direction;lastNow=now;if(!xWin||!tail.ok||tail.prevent[direction]&&!lockFLAG){return}else{stopEvent(e,true);if(lockFLAG&&sameDirection&&tooFast){return}}if(options.shift){lockFLAG=true;clearTimeout(tail.t);tail.t=setTimeout(function(){lockFLAG=false},SCROLL_LOCK_TIMEOUT)}(options.onEnd||noop)(e,options.shift?direction:xDelta)});return tail}jQuery.Fotorama=function($fotorama,opts){$HTML=$("html");$BODY=$("body");var that=this,stamp=$.now(),stampClass=_fotoramaClass+stamp,fotorama=$fotorama[0],data,dataFrameCount=1,fotoramaData=$fotorama.data(),size,$style=$("<style></style>"),$anchor=$(div(hiddenClass)),$wrap=$fotorama.find(cls(wrapClass)),$stage=$wrap.find(cls(stageClass)),stage=$stage[0],$stageShaft=$fotorama.find(cls(stageShaftClass)),$stageFrame=$(),$arrPrev=$fotorama.find(cls(arrPrevClass)),$arrNext=$fotorama.find(cls(arrNextClass)),$arrs=$fotorama.find(cls(arrClass)),$navWrap=$fotorama.find(cls(navWrapClass)),$nav=$navWrap.find(cls(navClass)),$navShaft=$nav.find(cls(navShaftClass)),$navFrame,$navDotFrame=$(),$navThumbFrame=$(),stageShaftData=$stageShaft.data(),navShaftData=$navShaft.data(),$thumbBorder=$fotorama.find(cls(thumbBorderClass)),$thumbArrLeft=$fotorama.find(cls(thumbArrLeft)),$thumbArrRight=$fotorama.find(cls(thumbArrRight)),$fullscreenIcon=$fotorama.find(cls(fullscreenIconClass)),fullscreenIcon=$fullscreenIcon[0],$videoPlay=$(div(videoPlayClass)),$videoClose=$fotorama.find(cls(videoCloseClass)),videoClose=$videoClose[0],$spinner=$fotorama.find(cls(fotoramaSpinnerClass)),$videoPlaying,activeIndex=false,activeFrame,activeIndexes,repositionIndex,dirtyIndex,lastActiveIndex,prevIndex,nextIndex,nextAutoplayIndex,startIndex,o_loop,o_nav,o_navThumbs,o_navTop,o_allowFullScreen,o_nativeFullScreen,o_fade,o_thumbSide,o_thumbSide2,o_transitionDuration,o_transition,o_shadows,o_rtl,o_keyboard,lastOptions={},measures={},measuresSetFLAG,stageShaftTouchTail={},stageWheelTail={},navShaftTouchTail={},navWheelTail={},scrollTop,scrollLeft,showedFLAG,pausedAutoplayFLAG,stoppedAutoplayFLAG,toDeactivate={},toDetach={},measuresStash,touchedFLAG,hoverFLAG,navFrameKey,stageLeft=0,fadeStack=[];$wrap[STAGE_FRAME_KEY]=$('<div class="'+stageFrameClass+'"></div>');$wrap[NAV_THUMB_FRAME_KEY]=$($.Fotorama.jst.thumb());$wrap[NAV_DOT_FRAME_KEY]=$($.Fotorama.jst.dots());toDeactivate[STAGE_FRAME_KEY]=[];toDeactivate[NAV_THUMB_FRAME_KEY]=[];toDeactivate[NAV_DOT_FRAME_KEY]=[];toDetach[STAGE_FRAME_KEY]={};$wrap.addClass(CSS3?wrapCss3Class:wrapCss2Class);fotoramaData.fotorama=this;function checkForVideo(){$.each(data,function(i,dataFrame){if(!dataFrame.i){dataFrame.i=dataFrameCount++;var video=findVideoId(dataFrame.video,true);if(video){var thumbs={};dataFrame.video=video;if(!dataFrame.img&&!dataFrame.thumb){thumbs=getVideoThumbs(dataFrame,data,that)}else{dataFrame.thumbsReady=true}updateData(data,{img:thumbs.img,thumb:thumbs.thumb},dataFrame.i,that)}}})}function allowKey(key){return o_keyboard[key]}function setStagePosition(){if($stage!==undefined){if(opts.navdir=="vertical"){var padding=opts.thumbwidth+opts.thumbmargin;$stage.css("left",padding);$arrNext.css("right",padding);$fullscreenIcon.css("right",padding);$wrap.css("width",$wrap.css("width")+padding);$stageShaft.css("max-width",$wrap.width()-padding)}else{$stage.css("left","");$arrNext.css("right","");$fullscreenIcon.css("right","");$wrap.css("width",$wrap.css("width")+padding);$stageShaft.css("max-width","")}}}function bindGlobalEvents(FLAG){var keydownCommon="keydown."+_fotoramaClass,localStamp=_fotoramaClass+stamp,keydownLocal="keydown."+localStamp,keyupLocal="keyup."+localStamp,resizeLocal="resize."+localStamp+" "+"orientationchange."+localStamp,showParams;if(FLAG){$DOCUMENT.on(keydownLocal,function(e){var catched,index;if($videoPlaying&&e.keyCode===27){catched=true;unloadVideo($videoPlaying,true,true)}else if(that.fullScreen||opts.keyboard&&!that.index){if(e.keyCode===27){catched=true;that.cancelFullScreen()}else if(e.shiftKey&&e.keyCode===32&&allowKey("space")||!e.altKey&&!e.metaKey&&e.keyCode===37&&allowKey("left")||e.keyCode===38&&allowKey("up")&&$(":focus").attr("data-gallery-role")){that.longPress.progress();index="<"}else if(e.keyCode===32&&allowKey("space")||!e.altKey&&!e.metaKey&&e.keyCode===39&&allowKey("right")||e.keyCode===40&&allowKey("down")&&$(":focus").attr("data-gallery-role")){that.longPress.progress();index=">"}else if(e.keyCode===36&&allowKey("home")){that.longPress.progress();index="<<"}else if(e.keyCode===35&&allowKey("end")){that.longPress.progress();index=">>"}}(catched||index)&&stopEvent(e);showParams={index:index,slow:e.altKey,user:true};index&&(that.longPress.inProgress?that.showWhileLongPress(showParams):that.show(showParams))});if(FLAG){$DOCUMENT.on(keyupLocal,function(e){if(that.longPress.inProgress){that.showEndLongPress({user:true})}that.longPress.reset()})}if(!that.index){$DOCUMENT.off(keydownCommon).on(keydownCommon,"textarea, input, select",function(e){!$BODY.hasClass(_fullscreenClass)&&e.stopPropagation()})}$WINDOW.on(resizeLocal,that.resize)}else{$DOCUMENT.off(keydownLocal);$WINDOW.off(resizeLocal)}}function appendElements(FLAG){if(FLAG===appendElements.f)return;if(FLAG){$fotorama.addClass(_fotoramaClass+" "+stampClass).before($anchor).before($style);addInstance(that)}else{$anchor.detach();$style.detach();$fotorama.html(fotoramaData.urtext).removeClass(stampClass);hideInstance(that)}bindGlobalEvents(FLAG);appendElements.f=FLAG}function setData(){data=that.data=data||clone(opts.data)||getDataFromHtml($fotorama);size=that.size=data.length;ready.ok&&opts.shuffle&&shuffle(data);checkForVideo();activeIndex=limitIndex(activeIndex);size&&appendElements(true)}function stageNoMove(){var _noMove=size<2||$videoPlaying;stageShaftTouchTail.noMove=_noMove||o_fade;stageShaftTouchTail.noSwipe=_noMove||!opts.swipe;!o_transition&&$stageShaft.toggleClass(grabClass,!opts.click&&!stageShaftTouchTail.noMove&&!stageShaftTouchTail.noSwipe);MS_POINTER&&$wrap.toggleClass(wrapPanYClass,!stageShaftTouchTail.noSwipe)}function setAutoplayInterval(interval){if(interval===true)interval="";opts.autoplay=Math.max(+interval||AUTOPLAY_INTERVAL,o_transitionDuration*1.5)}function updateThumbArrow(opt){if(opt.navarrows&&opt.nav==="thumbs"){$thumbArrLeft.show();$thumbArrRight.show()}else{$thumbArrLeft.hide();$thumbArrRight.hide()}}function getThumbsInSlide($el,opts){return Math.floor($wrap.width()/(opts.thumbwidth+opts.thumbmargin))}function setOptions(){if(!opts.nav||opts.nav==="dots"){opts.navdir="horizontal"}that.options=opts=optionsToLowerCase(opts);thumbsPerSlide=getThumbsInSlide($wrap,opts);o_fade=opts.transition==="crossfade"||opts.transition==="dissolve";o_loop=opts.loop&&(size>2||o_fade&&(!o_transition||o_transition!=="slide"));o_transitionDuration=+opts.transitionduration||TRANSITION_DURATION;o_rtl=opts.direction==="rtl";o_keyboard=$.extend({},opts.keyboard&&KEYBOARD_OPTIONS,opts.keyboard);updateThumbArrow(opts);var classes={add:[],remove:[]};function addOrRemoveClass(FLAG,value){classes[FLAG?"add":"remove"].push(value)}if(size>1){o_nav=opts.nav;o_navTop=opts.navposition==="top";classes.remove.push(selectClass);$arrs.toggle(!!opts.arrows)}else{o_nav=false;$arrs.hide()}arrsUpdate();stageWheelUpdate();thumbArrUpdate();if(opts.autoplay)setAutoplayInterval(opts.autoplay);o_thumbSide=numberFromMeasure(opts.thumbwidth)||THUMB_SIZE;o_thumbSide2=numberFromMeasure(opts.thumbheight)||THUMB_SIZE;stageWheelTail.ok=navWheelTail.ok=opts.trackpad&&!SLOW;stageNoMove();extendMeasures(opts,[measures]);o_navThumbs=o_nav==="thumbs";if($navWrap.filter(":hidden")&&!!o_nav){$navWrap.show()}if(o_navThumbs){frameDraw(size,"navThumb");$navFrame=$navThumbFrame;navFrameKey=NAV_THUMB_FRAME_KEY;setStyle($style,$.Fotorama.jst.style({w:o_thumbSide,h:o_thumbSide2,b:opts.thumbborderwidth,m:opts.thumbmargin,s:stamp,q:!COMPAT}));$nav.addClass(navThumbsClass).removeClass(navDotsClass)}else if(o_nav==="dots"){frameDraw(size,"navDot");$navFrame=$navDotFrame;navFrameKey=NAV_DOT_FRAME_KEY;$nav.addClass(navDotsClass).removeClass(navThumbsClass)}else{$navWrap.hide();o_nav=false;$nav.removeClass(navThumbsClass+" "+navDotsClass)}if(o_nav){if(o_navTop){$navWrap.insertBefore($stage)}else{$navWrap.insertAfter($stage)}frameAppend.nav=false;frameAppend($navFrame,$navShaft,"nav")}o_allowFullScreen=opts.allowfullscreen;if(o_allowFullScreen){$fullscreenIcon.prependTo($stage);o_nativeFullScreen=FULLSCREEN&&o_allowFullScreen==="native";stubEvent($fullscreenIcon,"touchend")}else{$fullscreenIcon.detach();o_nativeFullScreen=false}addOrRemoveClass(o_fade,wrapFadeClass);addOrRemoveClass(!o_fade,wrapSlideClass);addOrRemoveClass(!opts.captions,wrapNoCaptionsClass);addOrRemoveClass(o_rtl,wrapRtlClass);addOrRemoveClass(opts.arrows,wrapToggleArrowsClass);o_shadows=opts.shadows&&!SLOW;addOrRemoveClass(!o_shadows,wrapNoShadowsClass);$wrap.addClass(classes.add.join(" ")).removeClass(classes.remove.join(" "));lastOptions=$.extend({},opts);setStagePosition()}function normalizeIndex(index){return index<0?(size+index%size)%size:index>=size?index%size:index}function limitIndex(index){return minMaxLimit(index,0,size-1)}function edgeIndex(index){return o_loop?normalizeIndex(index):limitIndex(index)}function getPrevIndex(index){return index>0||o_loop?index-1:false}function getNextIndex(index){return index<size-1||o_loop?index+1:false}function setStageShaftMinmaxAndSnap(){stageShaftTouchTail.min=o_loop?-Infinity:-getPosByIndex(size-1,measures.w,opts.margin,repositionIndex);stageShaftTouchTail.max=o_loop?Infinity:-getPosByIndex(0,measures.w,opts.margin,repositionIndex);stageShaftTouchTail.snap=measures.w+opts.margin}function setNavShaftMinMax(){var isVerticalDir=opts.navdir==="vertical";var param=isVerticalDir?$navShaft.height():$navShaft.width();var mainParam=isVerticalDir?measures.h:measures.nw;navShaftTouchTail.min=Math.min(0,mainParam-param);navShaftTouchTail.max=0;navShaftTouchTail.direction=opts.navdir;$navShaft.toggleClass(grabClass,!(navShaftTouchTail.noMove=navShaftTouchTail.min===navShaftTouchTail.max))}function eachIndex(indexes,type,fn){if(typeof indexes==="number"){indexes=new Array(indexes);var rangeFLAG=true}return $.each(indexes,function(i,index){if(rangeFLAG)index=i;if(typeof index==="number"){var dataFrame=data[normalizeIndex(index)];if(dataFrame){var key="$"+type+"Frame",$frame=dataFrame[key];fn.call(this,i,index,dataFrame,$frame,key,$frame&&$frame.data())}}})}function setMeasures(width,height,ratio,index){if(!measuresSetFLAG||measuresSetFLAG==="*"&&index===startIndex){width=measureIsValid(opts.width)||measureIsValid(width)||WIDTH;height=measureIsValid(opts.height)||measureIsValid(height)||HEIGHT;that.resize({width:width,ratio:opts.ratio||ratio||width/height},0,index!==startIndex&&"*")}}function loadImg(indexes,type,specialMeasures,again){eachIndex(indexes,type,function(i,index,dataFrame,$frame,key,frameData){if(!$frame)return;var fullFLAG=that.fullScreen&&!frameData.$full&&type==="stage";if(frameData.$img&&!again&&!fullFLAG)return;var img=new Image,$img=$(img),imgData=$img.data();frameData[fullFLAG?"$full":"$img"]=$img;var srcKey=type==="stage"?fullFLAG?"full":"img":"thumb",src=dataFrame[srcKey],dummy=fullFLAG?dataFrame["img"]:dataFrame[type==="stage"?"thumb":"img"];if(type==="navThumb")$frame=frameData.$wrap;function triggerTriggerEvent(event){var _index=normalizeIndex(index);triggerEvent(event,{index:_index,src:src,frame:data[_index]})}function error(){$img.remove();$.Fotorama.cache[src]="error";if((!dataFrame.html||type!=="stage")&&dummy&&dummy!==src){dataFrame[srcKey]=src=dummy;frameData.$full=null;loadImg([index],type,specialMeasures,true)}else{if(src&&!dataFrame.html&&!fullFLAG){$frame.trigger("f:error").removeClass(loadingClass).addClass(errorClass);triggerTriggerEvent("error")}else if(type==="stage"){$frame.trigger("f:load").removeClass(loadingClass+" "+errorClass).addClass(loadedClass);triggerTriggerEvent("load");setMeasures()}frameData.state="error";if(size>1&&data[index]===dataFrame&&!dataFrame.html&&!dataFrame.deleted&&!dataFrame.video&&!fullFLAG){dataFrame.deleted=true;that.splice(index,1)}}}function loaded(){$.Fotorama.measures[src]=imgData.measures=$.Fotorama.measures[src]||{width:img.width,height:img.height,ratio:img.width/img.height};setMeasures(imgData.measures.width,imgData.measures.height,imgData.measures.ratio,index);$img.off("load error").addClass(""+(fullFLAG?imgFullClass:imgClass)).attr("aria-hidden","false").prependTo($frame);if($frame.hasClass(stageFrameClass)&&!$frame.hasClass(videoContainerClass)){$frame.attr("href",$img.attr("src"))}fit($img,($.isFunction(specialMeasures)?specialMeasures():specialMeasures)||measures);$.Fotorama.cache[src]=frameData.state="loaded";setTimeout(function(){$frame.trigger("f:load").removeClass(loadingClass+" "+errorClass).addClass(loadedClass+" "+(fullFLAG?loadedFullClass:loadedImgClass));if(type==="stage"){triggerTriggerEvent("load")}else if(dataFrame.thumbratio===AUTO||!dataFrame.thumbratio&&opts.thumbratio===AUTO){dataFrame.thumbratio=imgData.measures.ratio;reset()}},0)}if(!src){error();return}function waitAndLoad(){var _i=10;waitFor(function(){return!touchedFLAG||!_i--&&!SLOW},function(){loaded()})}if(!$.Fotorama.cache[src]){$.Fotorama.cache[src]="*";$img.on("load",waitAndLoad).on("error",error)}else{(function justWait(){if($.Fotorama.cache[src]==="error"){error()}else if($.Fotorama.cache[src]==="loaded"){setTimeout(waitAndLoad,0)}else{setTimeout(justWait,100)}})()}frameData.state="";img.src=src;if(frameData.data.caption){img.alt=frameData.data.caption||""}if(frameData.data.full){$(img).data("original",frameData.data.full)}if(UTIL.isExpectedCaption(dataFrame,opts.showcaption)){$(img).attr("aria-labelledby",dataFrame.labelledby)}})}function updateFotoramaState(){var $frame=activeFrame[STAGE_FRAME_KEY];if($frame&&!$frame.data().state){$spinner.addClass(spinnerShowClass);$frame.on("f:load f:error",function(){$frame.off("f:load f:error");$spinner.removeClass(spinnerShowClass)})}}function addNavFrameEvents(frame){addEnterUp(frame,onNavFrameClick);addFocus(frame,function(){setTimeout(function(){lockScroll($nav)},0);slideNavShaft({time:o_transitionDuration,guessIndex:$(this).data().eq,minMax:navShaftTouchTail})})}function frameDraw(indexes,type){eachIndex(indexes,type,function(i,index,dataFrame,$frame,key,frameData){if($frame)return;$frame=dataFrame[key]=$wrap[key].clone();frameData=$frame.data();frameData.data=dataFrame;var frame=$frame[0],labelledbyValue="labelledby"+$.now();if(type==="stage"){if(dataFrame.html){$('<div class="'+htmlClass+'"></div>').append(dataFrame._html?$(dataFrame.html).removeAttr("id").html(dataFrame._html):dataFrame.html).appendTo($frame)}if(dataFrame.id){labelledbyValue=dataFrame.id||labelledbyValue}dataFrame.labelledby=labelledbyValue;if(UTIL.isExpectedCaption(dataFrame,opts.showcaption)){$($.Fotorama.jst.frameCaption({caption:dataFrame.caption,labelledby:labelledbyValue})).appendTo($frame)}dataFrame.video&&$frame.addClass(stageFrameVideoClass).append($videoPlay.clone());addFocus(frame,function(){setTimeout(function(){lockScroll($stage)},0);clickToShow({index:frameData.eq,user:true})});$stageFrame=$stageFrame.add($frame)}else if(type==="navDot"){addNavFrameEvents(frame);$navDotFrame=$navDotFrame.add($frame)}else if(type==="navThumb"){addNavFrameEvents(frame);frameData.$wrap=$frame.children(":first");$navThumbFrame=$navThumbFrame.add($frame);if(dataFrame.video){frameData.$wrap.append($videoPlay.clone())}}})}function callFit($img,measuresToFit){return $img&&$img.length&&fit($img,measuresToFit)}function stageFramePosition(indexes){eachIndex(indexes,"stage",function(i,index,dataFrame,$frame,key,frameData){if(!$frame)return;var normalizedIndex=normalizeIndex(index);frameData.eq=normalizedIndex;toDetach[STAGE_FRAME_KEY][normalizedIndex]=$frame.css($.extend({left:o_fade?0:getPosByIndex(index,measures.w,opts.margin,repositionIndex)},o_fade&&getDuration(0)));if(isDetached($frame[0])){$frame.appendTo($stageShaft);unloadVideo(dataFrame.$video)}callFit(frameData.$img,measures);callFit(frameData.$full,measures);if($frame.hasClass(stageFrameClass)&&!($frame.attr("aria-hidden")==="false"&&$frame.hasClass(activeClass))){$frame.attr("aria-hidden","true")}})}function thumbsDraw(pos,loadFLAG){var leftLimit,rightLimit,exceedLimit;if(o_nav!=="thumbs"||isNaN(pos))return;leftLimit=-pos;rightLimit=-pos+measures.nw;if(opts.navdir==="vertical"){pos=pos-opts.thumbheight;rightLimit=-pos+measures.h}$navThumbFrame.each(function(){var $this=$(this),thisData=$this.data(),eq=thisData.eq,getSpecialMeasures=function(){return{h:o_thumbSide2,w:thisData.w}},specialMeasures=getSpecialMeasures(),exceedLimit=opts.navdir==="vertical"?thisData.t>rightLimit:thisData.l>rightLimit;specialMeasures.w=thisData.w;if(thisData.l+thisData.w<leftLimit||exceedLimit||callFit(thisData.$img,specialMeasures))return;loadFLAG&&loadImg([eq],"navThumb",getSpecialMeasures)})}function frameAppend($frames,$shaft,type){if(!frameAppend[type]){var thumbsFLAG=type==="nav"&&o_navThumbs,left=0,top=0;$shaft.append($frames.filter(function(){var actual,$this=$(this),frameData=$this.data();for(var _i=0,_l=data.length;_i<_l;_i++){if(frameData.data===data[_i]){actual=true;frameData.eq=_i;break}}return actual||$this.remove()&&false}).sort(function(a,b){return $(a).data().eq-$(b).data().eq}).each(function(){var $this=$(this),frameData=$this.data();UTIL.setThumbAttr($this,frameData.data.caption,"aria-label")}).each(function(){if(!thumbsFLAG)return;var $this=$(this),frameData=$this.data(),thumbwidth=Math.round(o_thumbSide2*frameData.data.thumbratio)||o_thumbSide,thumbheight=Math.round(o_thumbSide/frameData.data.thumbratio)||o_thumbSide2;frameData.t=top;frameData.h=thumbheight;frameData.l=left;frameData.w=thumbwidth;$this.css({width:thumbwidth});top+=thumbheight+opts.thumbmargin;left+=thumbwidth+opts.thumbmargin}));frameAppend[type]=true}}function getDirection(x){return x-stageLeft>measures.w/3}function disableDirrection(i){return!o_loop&&(!(activeIndex+i)||!(activeIndex-size+i))&&!$videoPlaying}function arrsUpdate(){var disablePrev=disableDirrection(0),disableNext=disableDirrection(1);$arrPrev.toggleClass(arrDisabledClass,disablePrev).attr(disableAttr(disablePrev,false));$arrNext.toggleClass(arrDisabledClass,disableNext).attr(disableAttr(disableNext,false))}function thumbArrUpdate(){var isLeftDisable=false,isRightDisable=false;if(opts.navtype==="thumbs"&&!opts.loop){activeIndex==0?isLeftDisable=true:isLeftDisable=false;activeIndex==opts.data.length-1?isRightDisable=true:isRightDisable=false}if(opts.navtype==="slides"){var pos=readPosition($navShaft,opts.navdir);pos>=navShaftTouchTail.max?isLeftDisable=true:isLeftDisable=false;pos<=navShaftTouchTail.min?isRightDisable=true:isRightDisable=false}$thumbArrLeft.toggleClass(arrDisabledClass,isLeftDisable).attr(disableAttr(isLeftDisable,true));$thumbArrRight.toggleClass(arrDisabledClass,isRightDisable).attr(disableAttr(isRightDisable,true))}function stageWheelUpdate(){if(stageWheelTail.ok){stageWheelTail.prevent={"<":disableDirrection(0),">":disableDirrection(1)}}}function getNavFrameBounds($navFrame){var navFrameData=$navFrame.data(),left,top,width,height;if(o_navThumbs){left=navFrameData.l;top=navFrameData.t;width=navFrameData.w;height=navFrameData.h}else{left=$navFrame.position().left;width=$navFrame.width()}var horizontalBounds={c:left+width/2,min:-left+opts.thumbmargin*10,max:-left+measures.w-width-opts.thumbmargin*10};var verticalBounds={c:top+height/2,min:-top+opts.thumbmargin*10,max:-top+measures.h-height-opts.thumbmargin*10};return opts.navdir==="vertical"?verticalBounds:horizontalBounds}function slideThumbBorder(time){var navFrameData=activeFrame[navFrameKey].data();slide($thumbBorder,{time:time*1.2,pos:opts.navdir==="vertical"?navFrameData.t:navFrameData.l,width:navFrameData.w,height:navFrameData.h,direction:opts.navdir})}function slideNavShaft(options){var $guessNavFrame=data[options.guessIndex][navFrameKey],typeOfAnimation=opts.navtype;var overflowFLAG,time,minMax,boundTop,boundLeft,l,pos,x;if($guessNavFrame){if(typeOfAnimation==="thumbs"){overflowFLAG=navShaftTouchTail.min!==navShaftTouchTail.max;minMax=options.minMax||overflowFLAG&&getNavFrameBounds(activeFrame[navFrameKey]);boundTop=overflowFLAG&&(options.keep&&slideNavShaft.t?slideNavShaft.l:minMaxLimit((options.coo||measures.nw/2)-getNavFrameBounds($guessNavFrame).c,minMax.min,minMax.max));boundLeft=overflowFLAG&&(options.keep&&slideNavShaft.l?slideNavShaft.l:minMaxLimit((options.coo||measures.nw/2)-getNavFrameBounds($guessNavFrame).c,minMax.min,minMax.max));l=opts.navdir==="vertical"?boundTop:boundLeft;pos=overflowFLAG&&minMaxLimit(l,navShaftTouchTail.min,navShaftTouchTail.max)||0;time=options.time*1.1;slide($navShaft,{time:time,pos:pos,direction:opts.navdir,onEnd:function(){thumbsDraw(pos,true);thumbArrUpdate()}});setShadow($nav,findShadowEdge(pos,navShaftTouchTail.min,navShaftTouchTail.max,opts.navdir));slideNavShaft.l=l}else{x=readPosition($navShaft,opts.navdir);time=options.time*1.11;pos=validateSlidePos(opts,navShaftTouchTail,options.guessIndex,x,$guessNavFrame,$navWrap,opts.navdir);slide($navShaft,{time:time,pos:pos,direction:opts.navdir,onEnd:function(){thumbsDraw(pos,true);thumbArrUpdate()}});setShadow($nav,findShadowEdge(pos,navShaftTouchTail.min,navShaftTouchTail.max,opts.navdir))}}}function navUpdate(){deactivateFrames(navFrameKey);toDeactivate[navFrameKey].push(activeFrame[navFrameKey].addClass(activeClass).attr("data-active",true))}function deactivateFrames(key){var _toDeactivate=toDeactivate[key];while(_toDeactivate.length){_toDeactivate.shift().removeClass(activeClass).attr("data-active",false)}}function detachFrames(key){var _toDetach=toDetach[key];$.each(activeIndexes,function(i,index){delete _toDetach[normalizeIndex(index)]});$.each(_toDetach,function(index,$frame){delete _toDetach[index];$frame.detach()})}function stageShaftReposition(skipOnEnd){repositionIndex=dirtyIndex=activeIndex;var $frame=activeFrame[STAGE_FRAME_KEY];if($frame){deactivateFrames(STAGE_FRAME_KEY);toDeactivate[STAGE_FRAME_KEY].push($frame.addClass(activeClass).attr("data-active",true));if($frame.hasClass(stageFrameClass)){$frame.attr("aria-hidden","false")}skipOnEnd||that.showStage.onEnd(true);stop($stageShaft,0,true);detachFrames(STAGE_FRAME_KEY);stageFramePosition(activeIndexes);setStageShaftMinmaxAndSnap();setNavShaftMinMax();addEnterUp($stageShaft[0],function(){if(!$fotorama.hasClass(fullscreenClass)){that.requestFullScreen();$fullscreenIcon.focus()}})}}function extendMeasures(options,measuresArray){if(!options)return;$.each(measuresArray,function(i,measures){if(!measures)return;$.extend(measures,{width:options.width||measures.width,height:options.height,minwidth:options.minwidth,maxwidth:options.maxwidth,minheight:options.minheight,maxheight:options.maxheight,ratio:getRatio(options.ratio)})})}function triggerEvent(event,extra){$fotorama.trigger(_fotoramaClass+":"+event,[that,extra])}function onTouchStart(){clearTimeout(onTouchEnd.t);touchedFLAG=1;if(opts.stopautoplayontouch){that.stopAutoplay()}else{pausedAutoplayFLAG=true}}function onTouchEnd(){if(!touchedFLAG)return;if(!opts.stopautoplayontouch){releaseAutoplay();changeAutoplay()}onTouchEnd.t=setTimeout(function(){touchedFLAG=0},TRANSITION_DURATION+TOUCH_TIMEOUT)}function releaseAutoplay(){pausedAutoplayFLAG=!!($videoPlaying||stoppedAutoplayFLAG)}function changeAutoplay(){clearTimeout(changeAutoplay.t);waitFor.stop(changeAutoplay.w);if(!opts.autoplay||pausedAutoplayFLAG){if(that.autoplay){that.autoplay=false;triggerEvent("stopautoplay")}return}if(!that.autoplay){that.autoplay=true;triggerEvent("startautoplay")}var _activeIndex=activeIndex;var frameData=activeFrame[STAGE_FRAME_KEY].data();changeAutoplay.w=waitFor(function(){return frameData.state||_activeIndex!==activeIndex},function(){changeAutoplay.t=setTimeout(function(){if(pausedAutoplayFLAG||_activeIndex!==activeIndex)return;var _nextAutoplayIndex=nextAutoplayIndex,nextFrameData=data[_nextAutoplayIndex][STAGE_FRAME_KEY].data();changeAutoplay.w=waitFor(function(){return nextFrameData.state||_nextAutoplayIndex!==nextAutoplayIndex},function(){if(pausedAutoplayFLAG||_nextAutoplayIndex!==nextAutoplayIndex)return;that.show(o_loop?getDirectionSign(!o_rtl):nextAutoplayIndex)})},opts.autoplay)})}that.startAutoplay=function(interval){if(that.autoplay)return this;pausedAutoplayFLAG=stoppedAutoplayFLAG=false;setAutoplayInterval(interval||opts.autoplay);changeAutoplay();return this};that.stopAutoplay=function(){if(that.autoplay){pausedAutoplayFLAG=stoppedAutoplayFLAG=true;changeAutoplay()}return this};that.showSlide=function(slideDir){var currentPosition=readPosition($navShaft,opts.navdir),pos,time=500*1.1,size=opts.navdir==="horizontal"?opts.thumbwidth:opts.thumbheight,onEnd=function(){thumbArrUpdate()};if(slideDir==="next"){pos=currentPosition-(size+opts.margin)*thumbsPerSlide}if(slideDir==="prev"){pos=currentPosition+(size+opts.margin)*thumbsPerSlide}pos=validateRestrictions(pos,navShaftTouchTail);thumbsDraw(pos,true);slide($navShaft,{time:time,pos:pos,direction:opts.navdir,onEnd:onEnd})};that.showWhileLongPress=function(options){if(that.longPress.singlePressInProgress){return}var index=calcActiveIndex(options);calcGlobalIndexes(index);var time=calcTime(options)/50;var _activeFrame=activeFrame;that.activeFrame=activeFrame=data[activeIndex];var silent=_activeFrame===activeFrame&&!options.user;that.showNav(silent,options,time);return this};that.showEndLongPress=function(options){if(that.longPress.singlePressInProgress){return}var index=calcActiveIndex(options);calcGlobalIndexes(index);var time=calcTime(options)/50;var _activeFrame=activeFrame;that.activeFrame=activeFrame=data[activeIndex];var silent=_activeFrame===activeFrame&&!options.user;that.showStage(silent,options,time);showedFLAG=typeof lastActiveIndex!=="undefined"&&lastActiveIndex!==activeIndex;lastActiveIndex=activeIndex;return this};function calcActiveIndex(options){var index;if(typeof options!=="object"){index=options;options={}}else{index=options.index}index=index===">"?dirtyIndex+1:index==="<"?dirtyIndex-1:index==="<<"?0:index===">>"?size-1:index;index=isNaN(index)?undefined:index;index=typeof index==="undefined"?activeIndex||0:index;return index}function calcGlobalIndexes(index){that.activeIndex=activeIndex=edgeIndex(index);prevIndex=getPrevIndex(activeIndex);nextIndex=getNextIndex(activeIndex);nextAutoplayIndex=normalizeIndex(activeIndex+(o_rtl?-1:1));activeIndexes=[activeIndex,prevIndex,nextIndex];dirtyIndex=o_loop?index:activeIndex}function calcTime(options){var diffIndex=Math.abs(lastActiveIndex-dirtyIndex),time=getNumber(options.time,function(){return Math.min(o_transitionDuration*(1+(diffIndex-1)/12),o_transitionDuration*2)});if(options.slow){time*=10}return time}that.showStage=function(silent,options,time){unloadVideo($videoPlaying,activeFrame.i!==data[normalizeIndex(repositionIndex)].i);frameDraw(activeIndexes,"stage");stageFramePosition(SLOW?[dirtyIndex]:[dirtyIndex,getPrevIndex(dirtyIndex),getNextIndex(dirtyIndex)]);updateTouchTails("go",true);silent||triggerEvent("show",{user:options.user,time:time});pausedAutoplayFLAG=true;var overPos=options.overPos;var onEnd=that.showStage.onEnd=function(skipReposition){if(onEnd.ok)return;onEnd.ok=true;skipReposition||stageShaftReposition(true);if(!silent){triggerEvent("showend",{user:options.user})}if(!skipReposition&&o_transition&&o_transition!==opts.transition){that.setOptions({transition:o_transition});o_transition=false;return}updateFotoramaState();loadImg(activeIndexes,"stage");updateTouchTails("go",false);stageWheelUpdate();stageCursor();releaseAutoplay();changeAutoplay();if(that.fullScreen){activeFrame[STAGE_FRAME_KEY].find("."+imgFullClass).attr("aria-hidden",false);activeFrame[STAGE_FRAME_KEY].find("."+imgClass).attr("aria-hidden",true)}else{activeFrame[STAGE_FRAME_KEY].find("."+imgFullClass).attr("aria-hidden",true);activeFrame[STAGE_FRAME_KEY].find("."+imgClass).attr("aria-hidden",false)}};if(!o_fade){slide($stageShaft,{pos:-getPosByIndex(dirtyIndex,measures.w,opts.margin,repositionIndex),overPos:overPos,time:time,onEnd:onEnd})}else{var $activeFrame=activeFrame[STAGE_FRAME_KEY],$prevActiveFrame=data[lastActiveIndex]&&activeIndex!==lastActiveIndex?data[lastActiveIndex][STAGE_FRAME_KEY]:null;fade($activeFrame,$prevActiveFrame,$stageFrame,{time:time,method:opts.transition,onEnd:onEnd},fadeStack)}arrsUpdate()};that.showNav=function(silent,options,time){thumbArrUpdate();if(o_nav){navUpdate();var guessIndex=limitIndex(activeIndex+minMaxLimit(dirtyIndex-lastActiveIndex,-1,1));slideNavShaft({time:time,coo:guessIndex!==activeIndex&&options.coo,guessIndex:typeof options.coo!=="undefined"?guessIndex:activeIndex,keep:silent});if(o_navThumbs)slideThumbBorder(time)}};that.show=function(options){that.longPress.singlePressInProgress=true;var index=calcActiveIndex(options);calcGlobalIndexes(index);var time=calcTime(options);var _activeFrame=activeFrame;that.activeFrame=activeFrame=data[activeIndex];var silent=_activeFrame===activeFrame&&!options.user;that.showStage(silent,options,time);that.showNav(silent,options,time);showedFLAG=typeof lastActiveIndex!=="undefined"&&lastActiveIndex!==activeIndex;lastActiveIndex=activeIndex;that.longPress.singlePressInProgress=false;return this};that.requestFullScreen=function(){if(o_allowFullScreen&&!that.fullScreen){var isVideo=$((that.activeFrame||{}).$stageFrame||{}).hasClass("fotorama-video-container");if(isVideo){return}scrollTop=$WINDOW.scrollTop();scrollLeft=$WINDOW.scrollLeft();lockScroll($WINDOW);updateTouchTails("x",true);measuresStash=$.extend({},measures);$fotorama.addClass(fullscreenClass).appendTo($BODY.addClass(_fullscreenClass));$HTML.addClass(_fullscreenClass);unloadVideo($videoPlaying,true,true);that.fullScreen=true;if(o_nativeFullScreen){fullScreenApi.request(fotorama)}that.resize();loadImg(activeIndexes,"stage");updateFotoramaState();triggerEvent("fullscreenenter");if(!("ontouchstart"in window)){$fullscreenIcon.focus()}}return this};function cancelFullScreen(){if(that.fullScreen){that.fullScreen=false;if(FULLSCREEN){fullScreenApi.cancel(fotorama)}$BODY.removeClass(_fullscreenClass);$HTML.removeClass(_fullscreenClass);$fotorama.removeClass(fullscreenClass).insertAfter($anchor);measures=$.extend({},measuresStash);unloadVideo($videoPlaying,true,true);updateTouchTails("x",false);that.resize();loadImg(activeIndexes,"stage");lockScroll($WINDOW,scrollLeft,scrollTop);triggerEvent("fullscreenexit")}}that.cancelFullScreen=function(){if(o_nativeFullScreen&&fullScreenApi.is()){fullScreenApi.cancel(document)}else{cancelFullScreen()}return this};that.toggleFullScreen=function(){return that[(that.fullScreen?"cancel":"request")+"FullScreen"]()};that.resize=function(options){if(!data)return this;var time=arguments[1]||0,setFLAG=arguments[2];thumbsPerSlide=getThumbsInSlide($wrap,opts);extendMeasures(!that.fullScreen?optionsToLowerCase(options):{width:$(window).width(),maxwidth:null,minwidth:null,height:$(window).height(),maxheight:null,minheight:null},[measures,setFLAG||that.fullScreen||opts]);var width=measures.width,height=measures.height,ratio=measures.ratio,windowHeight=$WINDOW.height()-(o_nav?$nav.height():0);if(measureIsValid(width)){$wrap.css({width:""});$wrap.css({height:""});$stage.css({width:""});$stage.css({height:""});$stageShaft.css({width:""});$stageShaft.css({height:""});$nav.css({width:""});$nav.css({height:""});$wrap.css({minWidth:measures.minwidth||0,maxWidth:measures.maxwidth||MAX_WIDTH});if(o_nav==="dots"){$navWrap.hide()}width=measures.W=measures.w=$wrap.width();measures.nw=o_nav&&numberFromWhatever(opts.navwidth,width)||width;$stageShaft.css({width:measures.w,marginLeft:(measures.W-measures.w)/2});height=numberFromWhatever(height,windowHeight);height=height||ratio&&width/ratio;if(height){width=Math.round(width);height=measures.h=Math.round(minMaxLimit(height,numberFromWhatever(measures.minheight,windowHeight),numberFromWhatever(measures.maxheight,windowHeight)));$stage.css({width:width,height:height});if(opts.navdir==="vertical"&&!that.fullscreen){$nav.width(opts.thumbwidth+opts.thumbmargin*2)}if(opts.navdir==="horizontal"&&!that.fullscreen){$nav.height(opts.thumbheight+opts.thumbmargin*2)}if(o_nav==="dots"){$nav.width(width).height("auto");$navWrap.show()}if(opts.navdir==="vertical"&&that.fullScreen){$stage.css("height",$WINDOW.height())}if(opts.navdir==="horizontal"&&that.fullScreen){$stage.css("height",$WINDOW.height()-$nav.height())}if(o_nav){switch(opts.navdir){case"vertical":$navWrap.removeClass(navShafthorizontalClass);$navWrap.removeClass(navShaftListClass);$navWrap.addClass(navShaftVerticalClass);$nav.stop().animate({height:measures.h,width:opts.thumbwidth},time);break;case"list":$navWrap.removeClass(navShaftVerticalClass);$navWrap.removeClass(navShafthorizontalClass);$navWrap.addClass(navShaftListClass);break;default:$navWrap.removeClass(navShaftVerticalClass);$navWrap.removeClass(navShaftListClass);$navWrap.addClass(navShafthorizontalClass);$nav.stop().animate({width:measures.nw},time);break}stageShaftReposition();slideNavShaft({guessIndex:activeIndex,time:time,keep:true});if(o_navThumbs&&frameAppend.nav)slideThumbBorder(time)}measuresSetFLAG=setFLAG||true;ready.ok=true;ready()}}stageLeft=$stage.offset().left;setStagePosition();return this};that.setOptions=function(options){$.extend(opts,options);reset();return this};that.shuffle=function(){data&&shuffle(data)&&reset();return this};function setShadow($el,edge){if(o_shadows){$el.removeClass(shadowsLeftClass+" "+shadowsRightClass);$el.removeClass(shadowsTopClass+" "+shadowsBottomClass);edge&&!$videoPlaying&&$el.addClass(edge.replace(/^|\s/g," "+shadowsClass+"--"))}}that.longPress={threshold:1,count:0,thumbSlideTime:20,progress:function(){if(!this.inProgress){this.count++;this.inProgress=this.count>this.threshold}},end:function(){if(this.inProgress){this.isEnded=true}},reset:function(){this.count=0;this.inProgress=false;this.isEnded=false}};that.destroy=function(){that.cancelFullScreen();that.stopAutoplay();data=that.data=null;appendElements();activeIndexes=[];detachFrames(STAGE_FRAME_KEY);reset.ok=false;return this};that.playVideo=function(){var dataFrame=activeFrame,video=dataFrame.video,_activeIndex=activeIndex;if(typeof video==="object"&&dataFrame.videoReady){o_nativeFullScreen&&that.fullScreen&&that.cancelFullScreen();waitFor(function(){return!fullScreenApi.is()||_activeIndex!==activeIndex},function(){if(_activeIndex===activeIndex){dataFrame.$video=dataFrame.$video||$(div(videoClass)).append(createVideoFrame(video));dataFrame.$video.appendTo(dataFrame[STAGE_FRAME_KEY]);$wrap.addClass(wrapVideoClass);$videoPlaying=dataFrame.$video;stageNoMove();$arrs.blur();$fullscreenIcon.blur();triggerEvent("loadvideo")}})}return this};that.stopVideo=function(){unloadVideo($videoPlaying,true,true);return this};that.spliceByIndex=function(index,newImgObj){newImgObj.i=index+1;newImgObj.img&&$.ajax({url:newImgObj.img,type:"HEAD",success:function(){data.splice(index,1,newImgObj);reset()}})};function unloadVideo($video,unloadActiveFLAG,releaseAutoplayFLAG){if(unloadActiveFLAG){$wrap.removeClass(wrapVideoClass);$videoPlaying=false;stageNoMove()}if($video&&$video!==$videoPlaying){$video.remove();triggerEvent("unloadvideo")}if(releaseAutoplayFLAG){releaseAutoplay();changeAutoplay()}}function toggleControlsClass(FLAG){$wrap.toggleClass(wrapNoControlsClass,FLAG)}function stageCursor(e){if(stageShaftTouchTail.flow)return;var x=e?e.pageX:stageCursor.x,pointerFLAG=x&&!disableDirrection(getDirection(x))&&opts.click;if(stageCursor.p!==pointerFLAG&&$stage.toggleClass(pointerClass,pointerFLAG)){stageCursor.p=pointerFLAG;stageCursor.x=x}}$stage.on("mousemove",stageCursor);function clickToShow(showOptions){clearTimeout(clickToShow.t);if(opts.clicktransition&&opts.clicktransition!==opts.transition){setTimeout(function(){var _o_transition=opts.transition;that.setOptions({transition:opts.clicktransition});o_transition=_o_transition;clickToShow.t=setTimeout(function(){that.show(showOptions)},10)},0)}else{that.show(showOptions)}}function onStageTap(e,toggleControlsFLAG){var target=e.target,$target=$(target);if($target.hasClass(videoPlayClass)){that.playVideo()}else if(target===fullscreenIcon){that.toggleFullScreen()}else if($videoPlaying){target===videoClose&&unloadVideo($videoPlaying,true,true)}else if(!$fotorama.hasClass(fullscreenClass)){that.requestFullScreen()}}function updateTouchTails(key,value){stageShaftTouchTail[key]=navShaftTouchTail[key]=value}stageShaftTouchTail=moveOnTouch($stageShaft,{onStart:onTouchStart,onMove:function(e,result){setShadow($stage,result.edge)},onTouchEnd:onTouchEnd,onEnd:function(result){var toggleControlsFLAG;setShadow($stage);toggleControlsFLAG=(MS_POINTER&&!hoverFLAG||result.touch)&&opts.arrows;if((result.moved||toggleControlsFLAG&&result.pos!==result.newPos&&!result.control)&&result.$target[0]!==$fullscreenIcon[0]){var index=getIndexByPos(result.newPos,measures.w,opts.margin,repositionIndex);that.show({index:index,time:o_fade?o_transitionDuration:result.time,overPos:result.overPos,user:true})}else if(!result.aborted&&!result.control){onStageTap(result.startEvent,toggleControlsFLAG)}},timeLow:1,timeHigh:1,friction:2,select:"."+selectClass+", ."+selectClass+" *",$wrap:$stage,direction:"horizontal"});navShaftTouchTail=moveOnTouch($navShaft,{onStart:onTouchStart,onMove:function(e,result){setShadow($nav,result.edge)},onTouchEnd:onTouchEnd,onEnd:function(result){function onEnd(){slideNavShaft.l=result.newPos;releaseAutoplay();changeAutoplay();thumbsDraw(result.newPos,true);thumbArrUpdate()}if(!result.moved){var target=result.$target.closest("."+navFrameClass,$navShaft)[0];target&&onNavFrameClick.call(target,result.startEvent)}else if(result.pos!==result.newPos){pausedAutoplayFLAG=true;slide($navShaft,{time:result.time,pos:result.newPos,overPos:result.overPos,direction:opts.navdir,onEnd:onEnd});thumbsDraw(result.newPos);o_shadows&&setShadow($nav,findShadowEdge(result.newPos,navShaftTouchTail.min,navShaftTouchTail.max,result.dir))}else{onEnd()}},timeLow:.5,timeHigh:2,friction:5,$wrap:$nav,direction:opts.navdir});stageWheelTail=wheel($stage,{shift:true,onEnd:function(e,direction){onTouchStart();onTouchEnd();that.show({index:direction,slow:e.altKey})}});navWheelTail=wheel($nav,{onEnd:function(e,direction){onTouchStart();onTouchEnd();var newPos=stop($navShaft)+direction*.25;$navShaft.css(getTranslate(minMaxLimit(newPos,navShaftTouchTail.min,navShaftTouchTail.max),opts.navdir));o_shadows&&setShadow($nav,findShadowEdge(newPos,navShaftTouchTail.min,navShaftTouchTail.max,opts.navdir));navWheelTail.prevent={"<":newPos>=navShaftTouchTail.max,">":newPos<=navShaftTouchTail.min};clearTimeout(navWheelTail.t);navWheelTail.t=setTimeout(function(){slideNavShaft.l=newPos;thumbsDraw(newPos,true)},TOUCH_TIMEOUT);thumbsDraw(newPos)}});$wrap.hover(function(){setTimeout(function(){if(touchedFLAG)return;toggleControlsClass(!(hoverFLAG=true))},0)},function(){if(!hoverFLAG)return;toggleControlsClass(!(hoverFLAG=false))});function onNavFrameClick(e){var index=$(this).data().eq;if(opts.navtype==="thumbs"){clickToShow({index:index,slow:e.altKey,user:true,coo:e._x-$nav.offset().left})}else{clickToShow({index:index,slow:e.altKey,user:true})}}function onArrClick(e){clickToShow({index:$arrs.index(this)?">":"<",slow:e.altKey,user:true})}smartClick($arrs,function(e){stopEvent(e);onArrClick.call(this,e)},{onStart:function(){onTouchStart();stageShaftTouchTail.control=true},onTouchEnd:onTouchEnd});smartClick($thumbArrLeft,function(e){stopEvent(e);if(opts.navtype==="thumbs"){that.show("<")}else{that.showSlide("prev")}});smartClick($thumbArrRight,function(e){stopEvent(e);if(opts.navtype==="thumbs"){that.show(">")}else{that.showSlide("next")}});function addFocusOnControls(el){addFocus(el,function(){setTimeout(function(){lockScroll($stage)},0);toggleControlsClass(false)})}$arrs.each(function(){addEnterUp(this,function(e){onArrClick.call(this,e)});addFocusOnControls(this)});addEnterUp(fullscreenIcon,function(){if($fotorama.hasClass(fullscreenClass)){that.cancelFullScreen();$stageShaft.focus()}else{that.requestFullScreen();$fullscreenIcon.focus()}});addFocusOnControls(fullscreenIcon);function reset(){setData();setOptions();if(!reset.i){reset.i=true;var _startindex=opts.startindex;activeIndex=repositionIndex=dirtyIndex=lastActiveIndex=startIndex=edgeIndex(_startindex)||0}if(size){if(changeToRtl())return;if($videoPlaying){unloadVideo($videoPlaying,true)}activeIndexes=[];detachFrames(STAGE_FRAME_KEY);reset.ok=true;that.show({index:activeIndex,time:0});that.resize()}else{that.destroy()}}function changeToRtl(){if(!changeToRtl.f===o_rtl){changeToRtl.f=o_rtl;activeIndex=size-1-activeIndex;that.reverse();return true}}$.each("load push pop shift unshift reverse sort splice".split(" "),function(i,method){that[method]=function(){data=data||[];if(method!=="load"){Array.prototype[method].apply(data,arguments)}else if(arguments[0]&&typeof arguments[0]==="object"&&arguments[0].length){data=clone(arguments[0])}reset();return that}});function ready(){if(ready.ok){ready.ok=false;triggerEvent("ready")}}reset()};$.fn.fotorama=function(opts){return this.each(function(){var that=this,$fotorama=$(this),fotoramaData=$fotorama.data(),fotorama=fotoramaData.fotorama;if(!fotorama){waitFor(function(){return!isHidden(that)},function(){fotoramaData.urtext=$fotorama.html();new $.Fotorama($fotorama,$.extend({},OPTIONS,window.fotoramaDefaults,opts,fotoramaData))})}else{fotorama.setOptions(opts,true)}})};$.Fotorama.instances=[];function calculateIndexes(){$.each($.Fotorama.instances,function(index,instance){instance.index=index})}function addInstance(instance){$.Fotorama.instances.push(instance);calculateIndexes()}function hideInstance(instance){$.Fotorama.instances.splice(instance.index,1);calculateIndexes()}$.Fotorama.cache={};$.Fotorama.measures={};$=$||{};$.Fotorama=$.Fotorama||{};$.Fotorama.jst=$.Fotorama.jst||{};$.Fotorama.jst.dots=function(v){var __t,__p="",__e=_.escape;__p+='<div class="fotorama__nav__frame fotorama__nav__frame--dot" tabindex="0" role="button" data-gallery-role="nav-frame" data-nav-type="thumb" aria-label>\r\n <div class="fotorama__dot"></div>\r\n</div>';return __p};$.Fotorama.jst.frameCaption=function(v){var __t,__p="",__e=_.escape;__p+='<div class="fotorama__caption" aria-hidden="true">\r\n <div class="fotorama__caption__wrap" id="'+((__t=v.labelledby)==null?"":__t)+'">'+((__t=v.caption)==null?"":__t)+"</div>\r\n</div>\r\n";return __p};$.Fotorama.jst.style=function(v){var __t,__p="",__e=_.escape;__p+=".fotorama"+((__t=v.s)==null?"":__t)+" .fotorama__nav--thumbs .fotorama__nav__frame{\r\npadding:"+((__t=v.m)==null?"":__t)+"px;\r\nheight:"+((__t=v.h)==null?"":__t)+"px}\r\n.fotorama"+((__t=v.s)==null?"":__t)+" .fotorama__thumb-border{\r\nheight:"+((__t=v.h)==null?"":__t)+"px;\r\nborder-width:"+((__t=v.b)==null?"":__t)+"px;\r\nmargin-top:"+((__t=v.m)==null?"":__t)+"px}";return __p};$.Fotorama.jst.thumb=function(v){var __t,__p="",__e=_.escape;__p+='<div class="fotorama__nav__frame fotorama__nav__frame--thumb" tabindex="0" role="button" data-gallery-role="nav-frame" data-nav-type="thumb" aria-label>\r\n <div class="fotorama__thumb">\r\n </div>\r\n</div>';return __p}})(window,document,location,typeof jQuery!=="undefined"&&jQuery); From 061fa59d8597ebf09e05fff983c663e7fd1161c8 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Mon, 1 Apr 2019 13:05:09 +0300 Subject: [PATCH 123/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Changed default value for "UPS type" setting; --- app/code/Magento/Ups/etc/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ups/etc/config.xml b/app/code/Magento/Ups/etc/config.xml index 791b325c65e3f..73b10dd5ff41b 100644 --- a/app/code/Magento/Ups/etc/config.xml +++ b/app/code/Magento/Ups/etc/config.xml @@ -37,7 +37,7 @@ <negotiated_active>0</negotiated_active> <include_taxes>0</include_taxes> <mode_xml>1</mode_xml> - <type>UPS</type> + <type>UPS_XML</type> <is_account_live>0</is_account_live> <active_rma>0</active_rma> <is_online>1</is_online> From f2f92e6a29ddd9e25305765d3e519443b0984414 Mon Sep 17 00:00:00 2001 From: Ivan Gerchak <ivang@ven.com> Date: Mon, 1 Apr 2019 17:06:08 +0300 Subject: [PATCH 124/585] Add fotorama feature for disabling swipe on the item --- lib/web/fotorama/fotorama.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index 093ee707d3f98..b63b9cd872be7 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -1399,12 +1399,13 @@ fotoramaVersion = '4.6.4'; touchFLAG, targetIsSelectFLAG, targetIsLinkFlag, + isDisabledSwipe, tolerance, moved; function onStart(e) { $target = $(e.target); - tail.checked = targetIsSelectFLAG = targetIsLinkFlag = moved = false; + tail.checked = targetIsSelectFLAG = targetIsLinkFlag = isDisabledSwipe = moved = false; if (touchEnabledFLAG || tail.flow @@ -1415,6 +1416,7 @@ fotoramaVersion = '4.6.4'; touchFLAG = e.type === 'touchstart'; targetIsLinkFlag = $target.is('a, a *', el); + isDisabledSwipe = $target.hasClass('disableSwipe'); controlTouch = tail.control; tolerance = (tail.noMove || tail.noSwipe || controlTouch) ? 16 : !tail.snap ? 4 : 0; @@ -1428,7 +1430,7 @@ fotoramaVersion = '4.6.4'; touchEnabledFLAG = tail.flow = true; - if (!touchFLAG || tail.go) stopEvent(e); + if (!isDisabledSwipe && (!touchFLAG || tail.go)) stopEvent(e); } function onMove(e) { @@ -1441,6 +1443,13 @@ fotoramaVersion = '4.6.4'; return; } + $target = $(e.target); + isDisabledSwipe = $target.hasClass('disableSwipe'); + + if (isDisabledSwipe) { + return; + } + extendEvent(e); var xDiff = Math.abs(e._x - startEvent._x), // opt _x → _pageX From 8c212effaaa663322a7a3d7a729b587cf6ba4ce1 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 1 Apr 2019 09:56:04 -0500 Subject: [PATCH 125/585] MC-4430: Convert ApplyCatalogPriceRulesTest to MFTF --- ...eProductDetailsOnStorefrontActionGroup.xml | 18 ++ ...tProductDetailsOnStorefrontActionGroup.xml | 18 ++ ...sertStorefrontProductPricesActionGroup.xml | 20 ++ ...ubTotalOnStorefrontMinicartActionGroup.xml | 23 ++ ...dSimpleProductToCartWithQtyActionGroup.xml | 21 ++ ...tionDropDownAndAssertPricesActionGroup.xml | 19 ++ ...mOptionRadioAndAssertPricesActionGroup.xml | 20 ++ .../Catalog/Test/Mftf/Data/ProductData.xml | 10 + .../Test/Mftf/Data/ProductOptionData.xml | 29 +++ .../Test/Mftf/Data/ProductOptionValueData.xml | 12 ++ .../Section/StorefrontProductPageSection.xml | 1 + .../CatalogPriceRuleActionGroup.xml | 2 +- .../CatalogSelectCustomerGroupActionGroup.xml | 17 ++ ...aveAndApplyCatalogPriceRuleActionGroup.xml | 16 ++ ...uleForSimpleAndConfigurableProductTest.xml | 182 ++++++++++++++++ ...RuleForSimpleProductAndFixedMethodTest.xml | 109 ++++++++++ ...orSimpleProductForNewCustomerGroupTest.xml | 160 ++++++++++++++ ...eForSimpleProductWithCustomOptionsTest.xml | 199 ++++++++++++++++++ ...CheckOutPaymentOrderSummaryActionGroup.xml | 22 ++ 19 files changed, 897 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertDontSeeProductDetailsOnStorefrontActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertProductDetailsOnStorefrontActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPricesActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertSubTotalOnStorefrontMinicartActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToCartWithQtyActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionRadioAndAssertPricesActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogSelectCustomerGroupActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SaveAndApplyCatalogPriceRuleActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/VerifyCheckOutPaymentOrderSummaryActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertDontSeeProductDetailsOnStorefrontActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertDontSeeProductDetailsOnStorefrontActionGroup.xml new file mode 100644 index 0000000000000..3d0d16d105025 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertDontSeeProductDetailsOnStorefrontActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertDontSeeProductDetailsOnStorefrontActionGroup"> + <arguments> + <argument name="productNumber" type="string"/> + <argument name="productInfo" type="string"/> + </arguments> + <dontSee selector="{{StorefrontCategoryProductSection.ProductInfoByNumber(productNumber)}}" userInput="{{productInfo}}" stepKey="seeProductInfo"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertProductDetailsOnStorefrontActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertProductDetailsOnStorefrontActionGroup.xml new file mode 100644 index 0000000000000..68c6e92b93fa0 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertProductDetailsOnStorefrontActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertProductDetailsOnStorefrontActionGroup"> + <arguments> + <argument name="productNumber" type="string"/> + <argument name="productInfo" type="string"/> + </arguments> + <see selector="{{StorefrontCategoryProductSection.ProductInfoByNumber(productNumber)}}" userInput="{{productInfo}}" stepKey="seeProductInfo"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPricesActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPricesActionGroup.xml new file mode 100644 index 0000000000000..6e90fe7324dc4 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPricesActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontProductPricesActionGroup"> + <arguments> + <argument name="productPrice" type="string"/> + <argument name="productFinalPrice" type="string"/> + </arguments> + <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> + <see selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="productPriceAmount" userInput="{{productPrice}}"/> + <see selector="{{StorefrontProductInfoMainSection.updatedPrice}}" stepKey="productFinalPriceAmount" userInput="{{productFinalPrice}}"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertSubTotalOnStorefrontMinicartActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertSubTotalOnStorefrontMinicartActionGroup.xml new file mode 100644 index 0000000000000..26693771bd1fd --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertSubTotalOnStorefrontMinicartActionGroup.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertSubTotalOnStorefrontMiniCartActionGroup"> + <arguments> + <argument name="subTotal" type="string"/> + </arguments> + <waitForElementVisible selector="{{StorefrontMinicartSection.showCart}}" stepKey="waitForShowCartButtonVisible"/> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <grabTextFrom selector="{{StorefrontMinicartSection.miniCartSubtotalField}}" stepKey="grabTextFromMiniCartSubtotalField"/> + <assertEquals message="Mini shopping cart should contain subtotal {{subTotal}}" stepKey="assertSubtotalFieldFromMiniShoppingCart1"> + <expectedResult type="string">{{subTotal}}</expectedResult> + <actualResult type="variable">grabTextFromMiniCartSubtotalField</actualResult> + </assertEquals> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToCartWithQtyActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToCartWithQtyActionGroup.xml new file mode 100644 index 0000000000000..57882049e2037 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToCartWithQtyActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAddProductToCartWithQtyActionGroup"> + <arguments> + <argument name="productQty" type="string"/> + </arguments> + <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> + <fillField selector="{{StorefrontProductPageSection.qtyInput}}" userInput="{{productQty}}" stepKey="fillProduct1Quantity"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="clickOnAddToCartButton"/> + <waitForPageLoad stepKey="waitForProductToAddInCart1"/> + <seeElement selector="{{StorefrontProductPageSection.successMsg}}" stepKey="seeSuccessSaveMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup.xml new file mode 100644 index 0000000000000..13bbc3c1ac4f8 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup" extends="AssertStorefrontProductPricesActionGroup"> + <arguments> + <argument name="customOption" type="string"/> + <argument name="productPrice" type="string"/> + <argument name="productFinalPrice" type="string"/> + </arguments> + <selectOption selector="{{StorefrontProductPageSection.customOptionDropDown}}" userInput="{{customOption}}" stepKey="selectCustomOption" before="productPriceAmount"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionRadioAndAssertPricesActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionRadioAndAssertPricesActionGroup.xml new file mode 100644 index 0000000000000..6f7bdc46640b7 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionRadioAndAssertPricesActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontSelectCustomOptionRadioAndAssertPricesActionGroup" extends="AssertStorefrontProductPricesActionGroup"> + <arguments> + <argument name="customOption" type="entity"/> + <argument name="customOptionValue" type="entity"/> + <argument name="productPrice" type="string"/> + <argument name="productFinalPrice" type="string"/> + </arguments> + <click selector="{{StorefrontProductInfoMainSection.productAttributeOptionsRadioButtons(customOption.title, customOptionValue.price)}}" stepKey="clickRadioButtonsProductOption" before="productPriceAmount"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 63eb67be31c2e..675eac7412ffe 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -428,6 +428,16 @@ <var key="sku" entityType="product" entityKey="sku" /> <requiredEntity type="product_option">ProductOptionRadiobuttonWithTwoFixedOptions</requiredEntity> </entity> + <entity name="productWithCustomOptions" type="product"> + <var key="sku" entityType="product" entityKey="sku" /> + <data key="file">magento.jpg</data> + <requiredEntity type="product_option">ProductOptionDropDown2</requiredEntity> + </entity> + <entity name="productWithFixedOptions" type="product"> + <var key="sku" entityType="product" entityKey="sku" /> + <data key="file">magento.jpg</data> + <requiredEntity type="product_option">ProductOptionRadioButton2</requiredEntity> + </entity> <entity name="productWithOptions2" type="product"> <var key="sku" entityType="product" entityKey="sku" /> <requiredEntity type="product_option">ProductOptionDropDownWithLongValuesTitle</requiredEntity> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml index 36ec649fdde70..01f2fd4574ab5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml @@ -38,6 +38,16 @@ <data key="price_type">percent</data> <data key="max_characters">0</data> </entity> + <entity name="ProductOptionAreaFixed" type="product_option"> + <var key="product_sku" entityType="product" entityKey="sku" /> + <data key="title">OptionArea</data> + <data key="type">area</data> + <data key="is_require">false</data> + <data key="sort_order">2</data> + <data key="price">100</data> + <data key="price_type">fixed</data> + <data key="max_characters">0</data> + </entity> <entity name="ProductOptionFile" type="product_option"> <var key="product_sku" entityType="product" entityKey="sku" /> <data key="title">OptionFile</data> @@ -59,6 +69,16 @@ <requiredEntity type="product_option_value">ProductOptionValueDropdown1</requiredEntity> <requiredEntity type="product_option_value">ProductOptionValueDropdown2</requiredEntity> </entity> + <entity name="ProductOptionDropDown2" type="product_option"> + <var key="product_sku" entityType="product" entityKey="sku" /> + <data key="title">OptionDropDown</data> + <data key="type">drop_down</data> + <data key="sort_order">4</data> + <data key="is_require">false</data> + <requiredEntity type="product_option_value">ProductOptionValueDropdown1</requiredEntity> + <requiredEntity type="product_option_value">ProductOptionValueDropdown3</requiredEntity> + </entity> + <entity name="ProductOptionDropDownWithLongValuesTitle" type="product_option"> <var key="product_sku" entityType="product" entityKey="sku" /> <data key="title">OptionDropDownWithLongTitles</data> @@ -77,6 +97,15 @@ <requiredEntity type="product_option_value">ProductOptionValueRadioButtons1</requiredEntity> <requiredEntity type="product_option_value">ProductOptionValueRadioButtons2</requiredEntity> </entity> + <entity name="ProductOptionRadioButton2" type="product_option"> + <var key="product_sku" entityType="product" entityKey="sku" /> + <data key="title">OptionRadioButtons</data> + <data key="type">radio</data> + <data key="sort_order">4</data> + <data key="is_require">false</data> + <requiredEntity type="product_option_value">ProductOptionValueRadioButtons1</requiredEntity> + <requiredEntity type="product_option_value">ProductOptionValueRadioButtons4</requiredEntity> + </entity> <entity name="ProductOptionRadiobuttonWithTwoFixedOptions" type="product_option"> <var key="product_sku" entityType="product" entityKey="sku" /> <data key="title">OptionRadioButtons</data> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml index 8e9c0f86b38c7..4be7fcf1fe852 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml @@ -32,6 +32,18 @@ <data key="price">99.99</data> <data key="price_type">percent</data> </entity> + <entity name="ProductOptionValueDropdown3" type="product_option_value"> + <data key="title">OptionValueDropDown3</data> + <data key="sort_order">2</data> + <data key="price">10</data> + <data key="price_type">percent</data> + </entity> + <entity name="ProductOptionValueRadioButtons4" type="product_option_value"> + <data key="title">OptionValueRadioButtons4</data> + <data key="sort_order">1</data> + <data key="price">9.99</data> + <data key="price_type">fixed</data> + </entity> <entity name="ProductOptionValueRadioButtons3" type="product_option_value"> <data key="title">OptionValueRadioButtons3</data> <data key="sort_order">3</data> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml index 028bbe88e2cef..6ab2b00ae2160 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml @@ -24,5 +24,6 @@ <element name="orderTotal" type="input" selector=".grand.totals .amount .price"/> <element name="customOptionDropDown" type="select" selector="//*[@id='product-options-wrapper']//select[contains(@class, 'product-custom-option admin__control-select')]"/> <element name="qtyInputWithProduct" type="input" selector="//tr//strong[contains(.,'{{productName}}')]/../../td[@class='col qty']//input" parameterized="true"/> + <element name="customOptionRadio" type="input" selector="//span[@text='{{var}}']/../../input" parameterized="true"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml index 788355ebf4aaa..90f4f22bcf631 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml @@ -27,8 +27,8 @@ <click stepKey="clickToCalender" selector="{{AdminNewCatalogPriceRule.toDateButton}}"/> <click stepKey="clickToToday" selector="{{AdminNewCatalogPriceRule.todayDate}}"/> <click stepKey="openActionDropdown" selector="{{AdminNewCatalogPriceRule.actionsTab}}"/> - <selectOption stepKey="discountType" selector="{{AdminNewCatalogPriceRuleActions.apply}}" userInput="{{catalogRule.simple_action}}"/> <fillField stepKey="fillDiscountValue" selector="{{AdminNewCatalogPriceRuleActions.discountAmount}}" userInput="{{catalogRule.discount_amount}}"/> + <selectOption stepKey="discountType" selector="{{AdminNewCatalogPriceRuleActions.apply}}" userInput="{{catalogRule.simple_action}}"/> <selectOption stepKey="discardSubsequentRules" selector="{{AdminNewCatalogPriceRuleActions.disregardRules}}" userInput="Yes"/> <!-- Scroll to top and either save or save and apply after the action group --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogSelectCustomerGroupActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogSelectCustomerGroupActionGroup.xml new file mode 100644 index 0000000000000..64cadc5be232e --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogSelectCustomerGroupActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="CatalogSelectCustomerGroupActionGroup"> + <arguments> + <argument name="customer" defaultValue="NOT LOGGED IN" type="entity"/> + </arguments> + <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="{{customer}}" stepKey="selectCustomerGroup"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SaveAndApplyCatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SaveAndApplyCatalogPriceRuleActionGroup.xml new file mode 100644 index 0000000000000..bc75414e0de21 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SaveAndApplyCatalogPriceRuleActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="SaveAndApplyCatalogPriceRuleActionGroup"> + <waitForElementVisible selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="waitForSaveAndApplyButton"/> + <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="saveAndApply"/> + <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccess"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml new file mode 100644 index 0000000000000..ea6e758ba89f4 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -0,0 +1,182 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ApplyCatalogPriceRuleForSimpleProductAndConfigurableProductTest"> + <annotations> + <features value="CatalogRule"/> + <stories value="Apply catalog price rule"/> + <title value="Admin should be able to apply the catalog price rule for simple product and configurable product"/> + <description value="Admin should be able to apply the catalog price rule for simple product and configurable product"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14770"/> + <group value="CatalogRule"/> + <group value="banana"/> + + </annotations> + <before> + + <!-- Login as Admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Create Simple Product --> + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + <field key="price">56.78</field> + </createData> + + <!-- Create the configurable product based on the data in the /data folder --> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + + <!-- Make the configurable product have two options, that are children of the default attribute set --> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + + <!-- Create the 2 children that will be a part of the configurable product --> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + </createData> + <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + </createData> + + <!-- Assign the two products to the configurable product --> + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct1"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct2"/> + </createData> + </before> + <after> + <!-- Delete the catalog price rule --> + <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> + <actionGroup stepKey="deletePriceRule" ref="deleteEntitySecondaryGrid"> + <argument name="name" value="{{_defaultCatalogRule.name}}"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> + </actionGroup> + + <!-- Logout --> + <actionGroup ref="logout" stepKey="logout"/> + + <!-- Delete products and category --> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> + <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> + </after> + <!-- Begin creating a new catalog price rule --> + <actionGroup ref="newCatalogPriceRuleByUIWithConditionIsCategory" stepKey="newCatalogPriceRuleByUIWithConditionIsCategory"> + <argument name ="categoryId" value="$createCategory.id$"/> + </actionGroup> + + <!-- Select not logged in customer group --> + <actionGroup ref="selectNotLoggedInCustomerGroupActionGroup" stepKey="selectNotLoggedInCustomerGroup"/> + + <!-- Save and apply the new catalog price rule --> + <actionGroup ref="SaveAndApplyCatalogPriceRuleActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> + + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + + <!-- Navigate to category on store front --> + <amOnPage url="{{StorefrontProductPage.url($createCategory.name$)}}" stepKey="goToCategoryPage"/> + + <!-- Check simple product name on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct1Name"> + <argument name="productInfo" value="$createSimpleProduct.name$"/> + <argument name="productNumber" value="2"/> + </actionGroup> + + <!-- Check simple product price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct1Price"> + <argument name="productInfo" value="$51.10"/> + <argument name="productNumber" value="2"/> + </actionGroup> + + <!-- Check simple product regular price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct1RegularPrice"> + <argument name="productInfo" value="$56.78"/> + <argument name="productNumber" value="2"/> + </actionGroup> + + <!-- Check configurable product name on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct2Name"> + <argument name="productInfo" value="$createConfigProduct.name$"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Check configurable product price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct2Price"> + <argument name="productInfo" value="$110.70"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Navigate to simple product on store front --> + <amOnPage url="{{StorefrontProductPage.url($createSimpleProduct.name$)}}" stepKey="goToProductPage1"/> + + <!-- Assert regular and special price after selecting ProductOptionValueDropdown1 --> + <actionGroup ref="AssertStorefrontProductPricesActionGroup" stepKey="assertStorefrontProductPrices"> + <argument name="productPrice" value="$56.78"/> + <argument name="productFinalPrice" value="$51.10"/> + </actionGroup> + + <!-- Add simple product to cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="cartAddSimpleProduct1ToCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Open configurable product 1 select option 1 attribute --> + <amOnPage url="{{StorefrontProductPage.url($$createConfigProduct.custom_attributes[url_key]$$)}}" stepKey="amOnConfigurableProductPage"/> + <selectOption selector="{{StorefrontProductInfoMainSection.productOptionSelect('$$createConfigProductAttribute.attribute[frontend_labels][0][label]$$')}}" userInput="$$createConfigProductAttributeOption1.option[store_labels][0][label]$$" stepKey="selectOption"/> + <actionGroup ref="AssertStorefrontProductPricesActionGroup" stepKey="assertStorefrontProductPrices2"> + <argument name="productPrice" value="$123.00"/> + <argument name="productFinalPrice" value="$110.70"/> + </actionGroup> + + <!-- Assert regular and special price after selecting ProductOptionValueDropdown1 --> + + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="cartAddConfigProduct1ToCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Assert sub total on mini shopping cart --> + <actionGroup ref="AssertSubTotalOnStorefrontMiniCartActionGroup" stepKey="assertSubTotalOnStorefrontMiniCart"> + <argument name="subTotal" value="$161.80"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml new file mode 100644 index 0000000000000..5b6aeba2cac17 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ApplyCatalogRuleForSimpleProductAndFixedMethodTest"> + <annotations> + <features value="CatalogRule"/> + <stories value="Apply catalog price rule"/> + <title value="Admin should be able to apply the catalog price rule for simple product with custom options"/> + <description value="Admin should be able to apply the catalog price rule for simple product with custom options"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14771"/> + <group value="CatalogRule"/> + <group value="banana"/> + + </annotations> + <before> + <!-- Login as Admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Create category --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + + <!-- Create Simple Product --> + <createData entity="_defaultProduct" stepKey="createProduct1"> + <requiredEntity createDataKey="createCategory"/> + <field key="price">56.78</field> + </createData> + + <!-- Update all products to have custom options --> + <updateData createDataKey="createProduct1" entity="productWithFixedOptions" stepKey="updateProductWithOptions1"/> + </before> + <after> + <!-- Delete products and category --> + <deleteData createDataKey="createProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete the catalog price rule --> + <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> + <actionGroup stepKey="deletePriceRule" ref="deleteEntitySecondaryGrid"> + <argument name="name" value="{{CatalogRuleByFixed.name}}"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> + </actionGroup> + + <!-- Logout --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!-- 1. Begin creating a new catalog price rule --> + <actionGroup ref="newCatalogPriceRuleByUIWithConditionIsCategory" stepKey="newCatalogPriceRuleByUIWithConditionIsCategory"> + <argument name ="categoryId" value="$createCategory.id$"/> + <argument name ="catalogRule" value="CatalogRuleByFixed"/> + </actionGroup> + + <!-- Select not logged in customer group --> + <actionGroup ref="selectNotLoggedInCustomerGroupActionGroup" stepKey="selectNotLoggedInCustomerGroup"/> + + <!-- Save and apply the new catalog price rule --> + <actionGroup ref="SaveAndApplyCatalogPriceRuleActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + + <!-- Navigate to category on store front --> + <amOnPage url="{{StorefrontProductPage.url($createCategory.name$)}}" stepKey="goToCategoryPage"/> + + <!-- Check product 1 name on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct1Name"> + <argument name="productInfo" value="$createProduct1.name$"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Check product 1 price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct1Price"> + <argument name="productInfo" value="$44.48"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Check product 1 regular price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct1RegularPrice"> + <argument name="productInfo" value="$56.78"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Navigate to product 1 on store front --> + <amOnPage url="{{StorefrontProductPage.url($createProduct1.name$)}}" stepKey="goToProductPage1"/> + + <!-- Assert regular and special price after selecting ProductOptionValueDropdown1 --> + <actionGroup ref="StorefrontSelectCustomOptionRadioAndAssertPricesActionGroup" stepKey="storefrontSelectCustomOptionAndAssertPrices1"> + <argument name="customOption" value="ProductOptionRadioButton2"/> + <argument name="customOptionValue" value="ProductOptionValueRadioButtons1"/> + <argument name="productPrice" value="$156.77"/> + <argument name="productFinalPrice" value="$144.47"/> + </actionGroup> + + <!-- Add product 1 to cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="cartAddSimpleProduct1ToCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Assert sub total on mini shopping cart --> + <actionGroup ref="AssertSubTotalOnStorefrontMiniCartActionGroup" stepKey="assertSubTotalOnStorefrontMiniCart"> + <argument name="subTotal" value="$144.47"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml new file mode 100644 index 0000000000000..a8f3c8ed007a3 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest"> + <annotations> + <features value="CatalogRule"/> + <stories value="Apply catalog price rule"/> + <title value="Admin should be able to apply the catalog price rule for simple product for new customer group"/> + <description value="Admin should be able to apply the catalog price rule for simple product for new customer group"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14772"/> + <group value="CatalogRule"/> + <group value="banana"/> + + </annotations> + <before> + <!-- Login as Admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Create new customer group --> + <createData entity="CustomCustomerGroup" stepKey="customerGroup" /> + + <!--Creating customer--> + <createData entity="Simple_US_Customer" stepKey="createCustomer" > + <field key="group_id">$customerGroup.id$</field> + </createData> + + <!-- Create category --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + + <!-- Create Simple Product --> + <createData entity="_defaultProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + <field key="price">56.78</field> + </createData> + </before> + <after> + <!-- Delete products and category --> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete customer --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <!-- Delete customer group --> + <deleteData createDataKey="customerGroup" stepKey="deleteCustomerGroup"/> + + <!-- Delete the catalog price rule --> + <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> + <actionGroup stepKey="deletePriceRule" ref="deleteEntitySecondaryGrid"> + <argument name="name" value="{{CatalogRuleByFixed.name}}"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> + </actionGroup> + + <!-- Logout --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!-- 1. Begin creating a new catalog price rule --> + <actionGroup ref="newCatalogPriceRuleByUIWithConditionIsCategory" stepKey="newCatalogPriceRuleByUIWithConditionIsCategory"> + <argument name ="categoryId" value="$createCategory.id$"/> + <argument name="catalogRule" value="CatalogRuleByFixed"/> + </actionGroup> + + <!-- Select custom customer group --> + <actionGroup ref="CatalogSelectCustomerGroupActionGroup" stepKey="selectCustomCustomerGroup"> + <argument name="customer" value="$customerGroup.code$"/> + </actionGroup> + + <!-- Save and apply the new catalog price rule --> + <actionGroup ref="SaveAndApplyCatalogPriceRuleActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> + + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + + <!-- Navigate to category on store front --> + <amOnPage url="{{StorefrontProductPage.url($createCategory.name$)}}" stepKey="goToCategoryPage"/> + + <!-- Check product 1 name on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProductName"> + <argument name="productInfo" value="$createSimpleProduct.name$"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Check product 1 has no discounts applied on store front category page --> + <actionGroup ref="AssertDontSeeProductDetailsOnStorefrontActionGroup" stepKey="storefrontProductRegularPrice"> + <argument name="productInfo" value="$44.48"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Check product 1 price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProductPrice"> + <argument name="productInfo" value="$56.78"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Navigate to product 1 on store front --> + <amOnPage url="{{StorefrontProductPage.url($createSimpleProduct.name$)}}" stepKey="goToProductPage"/> + + <!-- Add product 1 to cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="cartAddSimpleProductToCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Assert sub total on mini shopping cart --> + <actionGroup ref="AssertSubTotalOnStorefrontMiniCartActionGroup" stepKey="assertSubTotalOnStorefrontMiniCart"> + <argument name="subTotal" value="$56.78"/> + </actionGroup> + + <!--Login to storefront as previously created customer--> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Navigate to category on store front as customer--> + <amOnPage url="{{StorefrontProductPage.url($createCategory.name$)}}" stepKey="goToCategoryPageAsCustomer"/> + + <!-- Check simple product name on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProductNameAsCustomer"> + <argument name="productInfo" value="$createSimpleProduct.name$"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Check simple product price on store front category page as customer --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProductPriceAsCustomer"> + <argument name="productInfo" value="$44.48"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Check simple product regular price on store front category page as customer --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProductRegularPriceAsCustomer"> + <argument name="productInfo" value="$56.78"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Navigate to simple product on store front as customer --> + <amOnPage url="{{StorefrontProductPage.url($createSimpleProduct.name$)}}" stepKey="goToProductPage1AsCustomer"/> + + <!-- Assert regular and special price as customer--> + <actionGroup ref="AssertStorefrontProductPricesActionGroup" stepKey="assertStorefrontProductPrices"> + <argument name="productPrice" value="$56.78"/> + <argument name="productFinalPrice" value="$44.48"/> + </actionGroup> + + <!-- Add simple product to cart as customer --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="cartAddSimpleProductToCartAsCustomer"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Assert sub total on mini shopping cart as customer --> + <actionGroup ref="AssertSubTotalOnStorefrontMiniCartActionGroup" stepKey="assertSubTotalOnStorefrontMiniCartAsCustomer"> + <argument name="subTotal" value="$88.96"/> + </actionGroup> + + </test> +</tests> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml new file mode 100644 index 0000000000000..0727626749754 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml @@ -0,0 +1,199 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ApplyCatalogRuleForSimpleProductWithCustomOptionsTest"> + <annotations> + <features value="CatalogRule"/> + <stories value="Apply catalog price rule"/> + <title value="Admin should be able to apply the catalog price rule for simple product with custom options"/> + <description value="Admin should be able to apply the catalog price rule for simple product with custom options"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14769"/> + <group value="CatalogRule"/> + <group value="banana"/> + + </annotations> + <before> + <!-- Login as Admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Create category --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + + <!-- Create Simple Product 1 --> + <createData entity="_defaultProduct" stepKey="createProduct1"> + <requiredEntity createDataKey="createCategory"/> + <field key="price">56.78</field> + </createData> + + <!-- Create Simple Product 2 --> + <createData entity="_defaultProduct" stepKey="createProduct2"> + <requiredEntity createDataKey="createCategory"/> + <field key="price">56.78</field> + </createData> + + <!-- Create Simple Product 3 --> + <createData entity="_defaultProduct" stepKey="createProduct3"> + <requiredEntity createDataKey="createCategory"/> + <field key="price">56.78</field> + </createData> + + <!-- Update all products to have custom options --> + <updateData createDataKey="createProduct1" entity="productWithCustomOptions" stepKey="updateProductWithOptions1"/> + <updateData createDataKey="createProduct2" entity="productWithCustomOptions" stepKey="updateProductWithOptions2"/> + <updateData createDataKey="createProduct3" entity="productWithCustomOptions" stepKey="updateProductWithOptions3"/> + </before> + <after> + <!-- Delete products and category --> + <deleteData createDataKey="createProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="createProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="createProduct3" stepKey="deleteProduct3"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Delete the catalog price rule --> + <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> + <actionGroup stepKey="deletePriceRule" ref="deleteEntitySecondaryGrid"> + <argument name="name" value="{{_defaultCatalogRule.name}}"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> + </actionGroup> + + <!-- Logout --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!-- 1. Begin creating a new catalog price rule --> + <actionGroup ref="newCatalogPriceRuleByUIWithConditionIsCategory" stepKey="newCatalogPriceRuleByUIWithConditionIsCategory"> + <argument name ="categoryId" value="$createCategory.id$"/> + </actionGroup> + + <!-- Select not logged in customer group --> + <actionGroup ref="selectNotLoggedInCustomerGroupActionGroup" stepKey="selectNotLoggedInCustomerGroup"/> + + <!-- Save and apply the new catalog price rule --> + <actionGroup ref="SaveAndApplyCatalogPriceRuleActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + + <!-- Navigate to category on store front --> + <amOnPage url="{{StorefrontProductPage.url($createCategory.name$)}}" stepKey="goToCategoryPage"/> + + <!-- Check product 1 name on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct1Name"> + <argument name="productInfo" value="$createProduct1.name$"/> + <argument name="productNumber" value="3"/> + </actionGroup> + + <!-- Check product 1 price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct1Price"> + <argument name="productInfo" value="$51.10"/> + <argument name="productNumber" value="3"/> + </actionGroup> + + <!-- Check product 1 regular price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct1RegularPrice"> + <argument name="productInfo" value="$56.78"/> + <argument name="productNumber" value="3"/> + </actionGroup> + + <!-- Check product 2 name on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct2Name"> + <argument name="productInfo" value="$createProduct2.name$"/> + <argument name="productNumber" value="2"/> + </actionGroup> + + <!-- Check product 1 price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct2Price"> + <argument name="productInfo" value="$51.10"/> + <argument name="productNumber" value="2"/> + </actionGroup> + + <!-- Check product 2 price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct2RegularPrice"> + <argument name="productInfo" value="$56.78"/> + <argument name="productNumber" value="2"/> + </actionGroup> + + <!-- Check product 3 name on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct3Name"> + <argument name="productInfo" value="$createProduct3.name$"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Check product 3 price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct3Price"> + <argument name="productInfo" value="$51.10"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Check product 3 regular price on store front category page --> + <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct3RegularPrice"> + <argument name="productInfo" value="$56.78"/> + <argument name="productNumber" value="1"/> + </actionGroup> + + <!-- Navigate to product 1 on store front --> + <amOnPage url="{{StorefrontProductPage.url($createProduct1.name$)}}" stepKey="goToProductPage1"/> + + <!-- Assert regular and special price after selecting ProductOptionValueDropdown1 --> + <actionGroup ref="StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup" stepKey="storefrontSelectCustomOptionAndAssertPrices1"> + <argument name="customOption" value="{{ProductOptionValueDropdown1.title}} +$0.01"/> + <argument name="productPrice" value="$56.79"/> + <argument name="productFinalPrice" value="$51.11"/> + </actionGroup> + + <!-- Add product 1 to cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="cartAddSimpleProduct1ToCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Navigate to product 2 on store front --> + <amOnPage url="{{StorefrontProductPage.url($createProduct1.name$)}}" stepKey="goToProductPage2"/> + + <!-- Assert regular and special price after selecting ProductOptionValueDropdown3 --> + <actionGroup ref="StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup" stepKey="storefrontSelectCustomOptionAndAssertPrices2"> + <argument name="customOption" value="{{ProductOptionValueDropdown3.title}} +$5.11"/> + <argument name="productPrice" value="$62.46"/> + <argument name="productFinalPrice" value="$56.21"/> + </actionGroup> + + <!-- Add product 2 to cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="cartAddSimpleProduct2ToCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Navigate to product 3 on store front --> + <amOnPage url="{{StorefrontProductPage.url($createProduct3.name$)}}" stepKey="goToProductPage3"/> + + <!-- Add product 3 to cart with no custom option --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="cartAddSimpleProduct3ToCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Assert sub total on mini shopping cart --> + <actionGroup ref="AssertSubTotalOnStorefrontMiniCartActionGroup" stepKey="assertSubTotalOnStorefrontMiniCart"> + <argument name="subTotal" value="$158.42"/> + </actionGroup> + + <!-- Navigate to checkout shipping page --> + <amOnPage stepKey="navigateToShippingPage" url="{{CheckoutShippingPage.url}}"/> + <waitForPageLoad stepKey="waitFoCheckoutShippingPageLoad"/> + + <!-- Fill Shipping information --> + <actionGroup ref="GuestCheckoutFillingShippingSectionActionGroup" stepKey="fillOrderShippingInfo"> + <argument name="customerVar" value="Simple_US_Customer"/> + <argument name="customerAddressVar" value="US_Address_TX"/> + </actionGroup> + + <!-- Verify order summary on payment page --> + <actionGroup ref="VerifyCheckoutPaymentOrderSummaryActionGroup" stepKey="verifyCheckoutPaymentOrderSummaryActionGroup"> + <argument name="orderSummarySubTotal" value="$158.42"/> + <argument name="orderSummaryShippingTotal" value="$15.00"/> + <argument name="orderSummaryTotal" value="$173.42"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/VerifyCheckOutPaymentOrderSummaryActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/VerifyCheckOutPaymentOrderSummaryActionGroup.xml new file mode 100644 index 0000000000000..7937092965f29 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/VerifyCheckOutPaymentOrderSummaryActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!--Fill shipment form for free shipping--> + <actionGroup name="VerifyCheckoutPaymentOrderSummaryActionGroup"> + <arguments> + <argument name="orderSummarySubTotal" type="string"/> + <argument name="orderSummaryShippingTotal" type="string"/> + <argument name="orderSummaryTotal" type="string"/> + </arguments> + <see selector="{{CheckoutPaymentSection.orderSummarySubtotal}}" userInput="{{orderSummarySubTotal}}" stepKey="seeCorrectSubtotal"/> + <see selector="{{CheckoutPaymentSection.orderSummaryShippingTotal}}" userInput="{{orderSummaryShippingTotal}}" stepKey="seeCorrectShipping"/> + <see selector="{{CheckoutPaymentSection.orderSummaryTotal}}" userInput="{{orderSummaryTotal}}" stepKey="seeCorrectOrderTotal"/> + </actionGroup> +</actionGroups> From 09182692dad6a04dea637e63ad6740151d1258ef Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 1 Apr 2019 10:16:46 -0500 Subject: [PATCH 126/585] MC-4430: Convert ApplyCatalogPriceRulesTest to MFTF --- .../Test/Mftf/Section/StorefrontProductPageSection.xml | 2 +- .../ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml | 5 +---- .../ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml | 2 -- ...plyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml | 2 -- ...ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml | 2 -- 5 files changed, 2 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml index 6ab2b00ae2160..c82e26a0e5968 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml @@ -24,6 +24,6 @@ <element name="orderTotal" type="input" selector=".grand.totals .amount .price"/> <element name="customOptionDropDown" type="select" selector="//*[@id='product-options-wrapper']//select[contains(@class, 'product-custom-option admin__control-select')]"/> <element name="qtyInputWithProduct" type="input" selector="//tr//strong[contains(.,'{{productName}}')]/../../td[@class='col qty']//input" parameterized="true"/> - <element name="customOptionRadio" type="input" selector="//span[@text='{{var}}']/../../input" parameterized="true"/> + <element name="customOptionRadio" type="input" selector="//span[@text='{{customOption}}']/../../input" parameterized="true"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml index ea6e758ba89f4..c612dda181868 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -16,11 +16,8 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14770"/> <group value="CatalogRule"/> - <group value="banana"/> - - </annotations> + </annotations> <before> - <!-- Login as Admin --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml index 5b6aeba2cac17..0cb1ead3f2cdf 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml @@ -16,8 +16,6 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14771"/> <group value="CatalogRule"/> - <group value="banana"/> - </annotations> <before> <!-- Login as Admin --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml index a8f3c8ed007a3..adab33d06dacb 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml @@ -16,8 +16,6 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14772"/> <group value="CatalogRule"/> - <group value="banana"/> - </annotations> <before> <!-- Login as Admin --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml index 0727626749754..735562169d5e9 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml @@ -16,8 +16,6 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14769"/> <group value="CatalogRule"/> - <group value="banana"/> - </annotations> <before> <!-- Login as Admin --> From 71e7db2c78bd76c20631cce2e5e75971c07507ab Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 1 Apr 2019 10:29:13 -0500 Subject: [PATCH 127/585] MC-4430: Convert ApplyCatalogPriceRulesTest to MFTF --- .../Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml index c612dda181868..b57a7f0d20029 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -166,7 +166,6 @@ </actionGroup> <!-- Assert regular and special price after selecting ProductOptionValueDropdown1 --> - <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="cartAddConfigProduct1ToCart"> <argument name="productQty" value="1"/> </actionGroup> From c851c190ad72c7f6f7a4443d6ff826415abda42c Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 1 Apr 2019 13:52:48 -0500 Subject: [PATCH 128/585] MC-4430: Convert ApplyCatalogPriceRulesTest to MFTF --- .../Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml | 1 + .../Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml | 1 + .../ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml | 1 + .../ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml | 1 + 4 files changed, 4 insertions(+) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml index b57a7f0d20029..ac44e7e2c72c9 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -16,6 +16,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14770"/> <group value="CatalogRule"/> + <group value="banana"/> </annotations> <before> <!-- Login as Admin --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml index 0cb1ead3f2cdf..1179af8755a93 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml @@ -16,6 +16,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14771"/> <group value="CatalogRule"/> + <group value="banana"/> </annotations> <before> <!-- Login as Admin --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml index adab33d06dacb..e1d701993da02 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml @@ -16,6 +16,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14772"/> <group value="CatalogRule"/> + <group value="banana"/> </annotations> <before> <!-- Login as Admin --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml index 735562169d5e9..f13c1b927a9f6 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml @@ -16,6 +16,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14769"/> <group value="CatalogRule"/> + <group value="banana"/> </annotations> <before> <!-- Login as Admin --> From 2f5f9f6753e15cf3e645115f9b8be3ef543f518e Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 1 Apr 2019 13:56:19 -0500 Subject: [PATCH 129/585] MC-4430: Convert ApplyCatalogPriceRulesTest to MFTF --- .../ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml | 2 +- .../Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml | 2 +- .../ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml | 2 +- .../ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml index ac44e7e2c72c9..be2e31d0766bd 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -16,7 +16,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14770"/> <group value="CatalogRule"/> - <group value="banana"/> + <group value="mtf_migrated"/> </annotations> <before> <!-- Login as Admin --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml index 1179af8755a93..a4e2e1acf62c2 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml @@ -16,7 +16,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14771"/> <group value="CatalogRule"/> - <group value="banana"/> + <group value="mtf_migrated"/> </annotations> <before> <!-- Login as Admin --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml index e1d701993da02..0aea543942976 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml @@ -16,7 +16,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14772"/> <group value="CatalogRule"/> - <group value="banana"/> + <group value="mtf_migrated"/> </annotations> <before> <!-- Login as Admin --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml index f13c1b927a9f6..1f611ffd716aa 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml @@ -16,7 +16,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14769"/> <group value="CatalogRule"/> - <group value="banana"/> + <group value="mtf_migrated"/> </annotations> <before> <!-- Login as Admin --> From 730ad052089241a1d69184896090e37f9bc95020 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 1 Apr 2019 15:33:59 -0500 Subject: [PATCH 130/585] MC-4430: Convert ApplyCatalogPriceRulesTest to MFTF --- ...oup.xml => StorefrontAddProductToCartWithQtyActionGroup.xml} | 2 +- ...oup.xml => VerifyCheckoutPaymentOrderSummaryActionGroup.xml} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename app/code/Magento/Catalog/Test/Mftf/ActionGroup/{StorefrontAddSimpleProductToCartWithQtyActionGroup.xml => StorefrontAddProductToCartWithQtyActionGroup.xml} (93%) rename app/code/Magento/Checkout/Test/Mftf/ActionGroup/{VerifyCheckOutPaymentOrderSummaryActionGroup.xml => VerifyCheckoutPaymentOrderSummaryActionGroup.xml} (100%) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToCartWithQtyActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddProductToCartWithQtyActionGroup.xml similarity index 93% rename from app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToCartWithQtyActionGroup.xml rename to app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddProductToCartWithQtyActionGroup.xml index 57882049e2037..816085cf0ca26 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToCartWithQtyActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddProductToCartWithQtyActionGroup.xml @@ -15,7 +15,7 @@ <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> <fillField selector="{{StorefrontProductPageSection.qtyInput}}" userInput="{{productQty}}" stepKey="fillProduct1Quantity"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="clickOnAddToCartButton"/> - <waitForPageLoad stepKey="waitForProductToAddInCart1"/> + <waitForPageLoad stepKey="waitForProductToAddInCart"/> <seeElement selector="{{StorefrontProductPageSection.successMsg}}" stepKey="seeSuccessSaveMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/VerifyCheckOutPaymentOrderSummaryActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/VerifyCheckoutPaymentOrderSummaryActionGroup.xml similarity index 100% rename from app/code/Magento/Checkout/Test/Mftf/ActionGroup/VerifyCheckOutPaymentOrderSummaryActionGroup.xml rename to app/code/Magento/Checkout/Test/Mftf/ActionGroup/VerifyCheckoutPaymentOrderSummaryActionGroup.xml From 2784faa16967ce107e60ad08da367635475aad5d Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 1 Apr 2019 18:06:00 -0500 Subject: [PATCH 131/585] Issue-230: implementing builtin cache --- .htaccess | 2 +- .../Magento/GraphQl/Controller/GraphQl.php | 38 +++++++++---------- .../Controller/GraphQl/Plugin.php | 4 +- .../Magento/GraphQlCache/etc/graphql/di.xml | 15 ++++++-- .../Model/Controller/Result/BuiltinPlugin.php | 4 +- 5 files changed, 36 insertions(+), 27 deletions(-) diff --git a/.htaccess b/.htaccess index d22b5a1395cae..ecf0ac778dfa1 100644 --- a/.htaccess +++ b/.htaccess @@ -2,7 +2,7 @@ ## overrides deployment configuration mode value ## use command bin/magento deploy:mode:set to switch modes -# SetEnv MAGE_MODE developer + SetEnv MAGE_MODE developer ############################################ ## uncomment these lines for CGI mode diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index d28535e45ac09..f374c29e24a52 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -17,8 +17,9 @@ use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; use Magento\Framework\GraphQl\Schema\SchemaGeneratorInterface; use Magento\Framework\Serialize\SerializerInterface; -use Magento\Framework\Webapi\Response; +use Magento\Framework\Controller\ResultInterface; use Magento\Framework\GraphQl\Query\Fields as QueryFields; +use Magento\Framework\Controller\Result\JsonFactory; /** * Front controller for web API GraphQL area. @@ -27,11 +28,6 @@ */ class GraphQl implements FrontControllerInterface { - /** - * @var Response - */ - private $response; - /** * @var SchemaGeneratorInterface */ @@ -68,7 +64,11 @@ class GraphQl implements FrontControllerInterface private $queryFields; /** - * @param Response $response + * @var JsonFactory + */ + private $jsonFactory; + + /** * @param SchemaGeneratorInterface $schemaGenerator * @param SerializerInterface $jsonSerializer * @param QueryProcessor $queryProcessor @@ -76,18 +76,18 @@ class GraphQl implements FrontControllerInterface * @param \Magento\Framework\GraphQl\Query\Resolver\ContextInterface $resolverContext * @param HttpRequestProcessor $requestProcessor * @param QueryFields $queryFields + * @param JsonFactory $jsonFactory */ public function __construct( - Response $response, SchemaGeneratorInterface $schemaGenerator, SerializerInterface $jsonSerializer, QueryProcessor $queryProcessor, ExceptionFormatter $graphQlError, ContextInterface $resolverContext, HttpRequestProcessor $requestProcessor, - QueryFields $queryFields + QueryFields $queryFields, + JsonFactory $jsonFactory ) { - $this->response = $response; $this->schemaGenerator = $schemaGenerator; $this->jsonSerializer = $jsonSerializer; $this->queryProcessor = $queryProcessor; @@ -95,17 +95,19 @@ public function __construct( $this->resolverContext = $resolverContext; $this->requestProcessor = $requestProcessor; $this->queryFields = $queryFields; + $this->jsonFactory = $jsonFactory; } + /** * Handle GraphQL request * * @param RequestInterface $request - * @return ResponseInterface + * @return ResponseInterface|ResultInterface */ - public function dispatch(RequestInterface $request) : ResponseInterface + public function dispatch(RequestInterface $request) /* : ResponseInterface */ { - $statusCode = 200; + $jsonResult = $this->jsonFactory->create(); try { /** @var Http $request */ $this->requestProcessor->processHeaders($request); @@ -140,12 +142,10 @@ public function dispatch(RequestInterface $request) : ResponseInterface } catch (\Exception $error) { $result['errors'] = isset($result) && isset($result['errors']) ? $result['errors'] : []; $result['errors'][] = $this->graphQlError->create($error); - $statusCode = ExceptionFormatter::HTTP_GRAPH_QL_SCHEMA_ERROR_STATUS; + $jsonResult->setHttpResponseCode(ExceptionFormatter::HTTP_GRAPH_QL_SCHEMA_ERROR_STATUS); } - $this->response->setBody($this->jsonSerializer->serialize($result))->setHeader( - 'Content-Type', - 'application/json' - )->setHttpResponseCode($statusCode); - return $this->response; + + $jsonResult->setData($result); + return $jsonResult; } } diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php index 582fa93e5532c..a4832f262f555 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -37,11 +37,11 @@ public function __construct(CacheTags $cacheTags, AppState $state) public function afterDispatch( FrontControllerInterface $subject, - ResponseInterface $response, + /* \Magento\Framework\App\Response\Http */ $response, RequestInterface $request ) { /** @var \Magento\Framework\App\Request\Http $request */ - /** @var \Magento\Framework\Webapi\Response $response */ + /** @var \Magento\Framework\App\Response\Http $response */ $cacheTags = $this->cacheTags->getCacheTags(); if ($request->isGet() && count($cacheTags)) { // assume that response should be cacheable if it contains cache tags diff --git a/app/code/Magento/GraphQlCache/etc/graphql/di.xml b/app/code/Magento/GraphQlCache/etc/graphql/di.xml index 6007bdd173aa9..93ed92066aafe 100644 --- a/app/code/Magento/GraphQlCache/etc/graphql/di.xml +++ b/app/code/Magento/GraphQlCache/etc/graphql/di.xml @@ -8,12 +8,21 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Framework\App\FrontControllerInterface"> <plugin name="cache" type="Magento\GraphQlCache\Controller\GraphQl\Plugin"/> + <plugin name="front-controller-builtin-cache" type="Magento\PageCache\Model\App\FrontController\BuiltinPlugin"/> + <!--<plugin name="front-controller-varnish-cache" type="Magento\PageCache\Model\App\FrontController\VarnishPlugin"/>--> </type> <type name="Magento\Framework\GraphQl\Query\ResolverInterface"> <plugin name="cache" type="Magento\GraphQlCache\Query\Resolver\Plugin"/> </type> - <type name="Magento\Framework\App\PageCache\Identifier"> - <plugin name="core-app-area-design-exception-plugin" - type="Magento\GraphQl\Model\App\CacheIdentifierPlugin" sortOrder="1"/> + <!--<type name="Magento\Framework\App\PageCache\Identifier">--> + <!--<plugin name="core-app-area-design-exception-plugin"--> + <!--type="Magento\GraphQlCache\Model\App\CacheIdentifierPlugin" sortOrder="1"/>--> + <!--</type>--> + <type name="Magento\Framework\Controller\ResultInterface"> + <plugin name="result-builtin-cache" type="Magento\PageCache\Model\Controller\Result\BuiltinPlugin"/> + <!--<plugin name="result-varnish-cache" type="Magento\PageCache\Model\Controller\Result\VarnishPlugin"/>--> + </type> + <type name="Magento\Framework\App\Response\Http"> + <plugin name="response-http-page-cache" type="Magento\PageCache\Model\App\Response\HttpPlugin"/> </type> </config> diff --git a/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php b/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php index aadae97009cac..871bc511d290a 100644 --- a/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php +++ b/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php @@ -87,8 +87,8 @@ public function afterRenderResult(ResultInterface $subject, ResultInterface $res $tags = []; if ($tagsHeader) { - $tags = explode(',', $tagsHeader->getFieldValue()); - $response->clearHeader('X-Magento-Tags'); + //$tags = explode(',', $tagsHeader->getFieldValue()); + //$response->clearHeader('X-Magento-Tags'); } $tags = array_unique(array_merge($tags, [CacheType::CACHE_TAG])); From 6ba9defd1a7d4789959ef07c88211bbe680bd33e Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 1 Apr 2019 18:07:36 -0500 Subject: [PATCH 132/585] Issue-230: reverting dev mode in htaccess --- .htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.htaccess b/.htaccess index ecf0ac778dfa1..d22b5a1395cae 100644 --- a/.htaccess +++ b/.htaccess @@ -2,7 +2,7 @@ ## overrides deployment configuration mode value ## use command bin/magento deploy:mode:set to switch modes - SetEnv MAGE_MODE developer +# SetEnv MAGE_MODE developer ############################################ ## uncomment these lines for CGI mode From 5c5ebc03171d846e3d0488ba5af9395f6bb03ae7 Mon Sep 17 00:00:00 2001 From: Lilit Sargsyan <Lilit_Sargsyan@epam.com> Date: Tue, 2 Apr 2019 10:11:18 +0400 Subject: [PATCH 133/585] MAGETWO-98522: Adding out of stock items to comparison shows success message but fails - Updated automated test script. --- .../AddOutOfStockProductToCompareListTest.xml | 72 +++++++++++++------ .../DisplayOutOfStockProductActionGroup.xml | 9 +++ .../Test/Mftf/Data/InventoryConfigData.xml | 23 ++++++ .../Mftf/Metadata/inventory_config-meta.xml | 22 ++++++ 4 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml create mode 100644 app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index cc894dcc178aa..7b6f9db8b3ac2 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -7,12 +7,12 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AddOutOfStockProductToCompareListTest"> <annotations> <features value="Catalog"/> - <title value="Adding to compare list if a product is out of stock"/> - <description value="Adding to compare list if a product is out of stock"/> + <title value="Add out of stock product to compare list"/> + <description value="Add out of stock product to compare list"/> <severity value="MAJOR"/> <testCaseId value="MAGETWO-98644"/> <useCaseId value="MAGETWO-98522"/> @@ -20,42 +20,70 @@ </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <createData entity="ApiCategory" stepKey="category"/> - <createData entity="SimpleOutOfStockProduct" stepKey="product"> + <createData entity="DisableDisplayOutOfStock" stepKey="displayOutOfStockNo"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <createData entity="SimpleSubCategory" stepKey="category"/> + <createData entity="SimpleProduct4" stepKey="product"> <requiredEntity createDataKey="category"/> </createData> </before> <after> + <actionGroup ref="setAsDefaultOutOfStockProduct" stepKey="setAsDefaultOutOfStockProduct"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <amOnPage url="{{AdminLogoutPage.url}}" stepKey="amOnLogoutPage"/> - </after> - - <!--Check 'out of stock' is turned off by default--> - <actionGroup ref="noDisplayOutOfStockProduct" stepKey="noDisplayOutOfStockProduct"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> <!--Open product page--> - <amOnPage url="$$product.name$$.html" stepKey="goToSimpleProductPage"/> + <comment userInput="Open product page" stepKey="openProdPage"/> + <amOnPage url="{{StorefrontProductPage.url($$product.name$$)}}" stepKey="goToSimpleProductPage"/> <waitForPageLoad stepKey="waitForSimpleProductPage"/> - <!--'Add to compare' link is not available--> + <comment userInput="'Add to compare' link is not available" stepKey="addToCompareLinkAvailability"/> <dontSeeElement selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="dontSeeAddToCompareLink"/> - - <!--Turn on 'out of stock' config--> - <actionGroup ref="displayOutOfStockProduct" stepKey="displayOutOfStockProduct"/> - - <!--Clear cache--> - <actionGroup ref="ClearCacheActionGroup" stepKey="clearCache" /> - + <!--Turn on 'out on stock' config--> + <comment userInput="Turn on 'out of stock' config" stepKey="onOutOfStockConfig"/> + <createData entity="EnableDisplayOutOfStock" stepKey="displayOutOfStockYes"/> + <!--Clear cache and reindex--> + <comment userInput="Clear cache and reindex" stepKey="cleanCache"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> <!--Open product page--> - <amOnPage url="$$product.name$$.html" stepKey="goToSimpleProductPage2"/> + <comment userInput="Open product page" stepKey="openProductPage"/> + <amOnPage url="{{StorefrontProductPage.url($$product.name$$)}}" stepKey="goToSimpleProductPage2"/> <waitForPageLoad stepKey="waitForSimpleProductPage2"/> - <!--Click on 'Add to Compare' link--> + <comment userInput="Click on 'Add to Compare' link" stepKey="clickOnAddToCompareLink"/> <click selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="clickOnAddToCompare"/> - + <waitForPageLoad stepKey="waitForProdAddToCmpList"/> + <!--Assert success message--> + <comment userInput="Assert success message" stepKey="assertSuccessMsg"/> + <grabTextFrom selector="{{AdminProductMessagesSection.successMessage}}" stepKey="grabTextFromSuccessMessage"/> + <assertEquals expected='You added product $$product.name$$ to the comparison list.' expectedType="string" actual="($grabTextFromSuccessMessage)" stepKey="assertSuccessMessage"/> <!--See product in the comparison list--> + <comment userInput="See product in the comparison list" stepKey="seeProductInComparisonList"/> <amOnPage url="{{StorefrontProductComparePage.url}}" stepKey="navigateToComparePage"/> + <waitForPageLoad stepKey="waitForStorefrontProductComparePageLoad"/> <seeElement selector="{{StorefrontProductCompareMainSection.ProductLinkByName($product.name$)}}" stepKey="seeProductInCompareList"/> + <!--Add product to compare list fom Category page--> + <comment userInput="Add product to compare list fom Category page" stepKey="addToCmpFromCategPage"/> + <amOnPage url="{{StorefrontCategoryPage.url($$category.name$$)}}" stepKey="onCategoryPage"/> + <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> + <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverOverProduct"/> + <click selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="clickAddToCompare"/> + <waitForPageLoad stepKey="waitProdAddingToCmpList"/> + <!--Assert success message--> + <comment userInput="Assert success message" stepKey="assertSuccessMsg2"/> + <grabTextFrom selector="{{AdminProductMessagesSection.successMessage}}" stepKey="grabTextFromSuccessMessage2"/> + <assertEquals expected='You added product $$product.name$$ to the comparison list.' expectedType="string" actual="($grabTextFromSuccessMessage)" stepKey="assertSuccessMessage2"/> + <!--Check that product displays on add to compare widget--> + <comment userInput="Check that product displays on add to compare widget" stepKey="checkProdNameOnWidget"/> + <seeElement selector="{{StorefrontComparisonSidebarSection.ProductTitleByName($$product.name$$)}}" stepKey="seeProdNameOnCmpWidget"/> + <!--See product in the compare page--> + <comment userInput="See product in the compare page" stepKey="seeProductInComparePage"/> + <amOnPage url="{{StorefrontProductComparePage.url}}" stepKey="navigateToComparePage2"/> + <waitForPageLoad stepKey="waitForStorefrontProductComparePageLoad2"/> + <seeElement selector="{{StorefrontProductCompareMainSection.ProductLinkByName($product.name$)}}" stepKey="seeProductInCompareList2"/> </test> </tests> diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml index c7c9126f46803..496284c0a4436 100644 --- a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml +++ b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml @@ -26,4 +26,13 @@ <selectOption selector="{{InventoryConfigSection.DisplayOutOfStockDropdown}}" userInput="No" stepKey="switchToNo" /> <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig" /> </actionGroup> + <actionGroup name="setAsDefaultOutOfStockProduct"> + <amOnPage url="{{InventoryConfigurationPage.url}}" stepKey="navigateToInventoryConfigurationPage"/> + <waitForPageLoad time="30" stepKey="waitForConfigPageToLoad"/> + <conditionalClick selector="{{InventoryConfigSection.ProductStockOptionsTab}}" dependentSelector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" visible="false" stepKey="expandStockOptions"/> + <waitForElementVisible selector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" time="30" stepKey="waitForCheckBoxVisible"/> + <checkOption selector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" stepKey="uncheckUseSystemValue"/> + <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig"/> + <waitForPageLoad time="30" stepKey="waitForConfigPageToLoad2"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml b/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml new file mode 100644 index 0000000000000..6e0501aeba8ff --- /dev/null +++ b/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="AdminDisplayOutOfStockYes" type="enable"> + <data key="value">1</data> + </entity> + <entity name="AdminDisplayOutOfStockNo" type="enable"> + <data key="value">0</data> + </entity> + <entity name="EnableDisplayOutOfStock" type="admin_out_of_stock_products_config"> + <requiredEntity type="enable">AdminDisplayOutOfStockYes</requiredEntity> + </entity> + <entity name="DisableDisplayOutOfStock" type="admin_out_of_stock_products_config"> + <requiredEntity type="enable">AdminDisplayOutOfStockNo</requiredEntity> + </entity> +</entities> diff --git a/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml b/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml new file mode 100644 index 0000000000000..5898c187bd5e7 --- /dev/null +++ b/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> + <operation name="AdminOutOfStockProductsConfig" dataType="admin_out_of_stock_products_config" type="create" auth="adminFormKey" url="/admin/system_config/save/section/cataloginventory/" method="POST"> + <object key="groups" dataType="admin_out_of_stock_products_config"> + <object key="options" dataType="admin_out_of_stock_products_config"> + <object key="fields" dataType="admin_out_of_stock_products_config"> + <object key="show_out_of_stock" dataType="enable"> + <field key="value">string</field> + </object> + </object> + </object> + </object> + </operation> +</operations> From 87ec9055992ea6c42b9f04789086332b1c8dc8f6 Mon Sep 17 00:00:00 2001 From: Ivan Gerchak <ivang@ven.com> Date: Tue, 2 Apr 2019 15:42:12 +0300 Subject: [PATCH 134/585] Remove creating $target --- lib/web/fotorama/fotorama.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index b63b9cd872be7..b38e70d915c9d 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -1443,8 +1443,7 @@ fotoramaVersion = '4.6.4'; return; } - $target = $(e.target); - isDisabledSwipe = $target.hasClass('disableSwipe'); + isDisabledSwipe = $(e.target).hasClass('disableSwipe'); if (isDisabledSwipe) { return; From e0ae403cd85e45139f003b58f8dc0626c54ba3b1 Mon Sep 17 00:00:00 2001 From: Lilit Sargsyan <Lilit_Sargsyan@epam.com> Date: Tue, 2 Apr 2019 18:01:28 +0400 Subject: [PATCH 135/585] MAGETWO-98522: Adding out of stock items to comparison shows success message but fails - Updated automated test script. --- .../AddOutOfStockProductToCompareListTest.xml | 17 +++++++++----- .../DisplayOutOfStockProductActionGroup.xml | 9 -------- .../Test/Mftf/Data/InventoryConfigData.xml | 23 ------------------- .../Mftf/Metadata/inventory_config-meta.xml | 22 ------------------ 4 files changed, 11 insertions(+), 60 deletions(-) delete mode 100644 app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml delete mode 100644 app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index 7b6f9db8b3ac2..4f66395bd0fbf 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -20,7 +20,7 @@ </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <createData entity="DisableDisplayOutOfStock" stepKey="displayOutOfStockNo"/> + <magentoCLI command="config:set cataloginventory/options/show_out_of_stock 0" stepKey="displayOutOfStockNo"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <createData entity="SimpleSubCategory" stepKey="category"/> <createData entity="SimpleProduct4" stepKey="product"> @@ -28,12 +28,11 @@ </createData> </before> <after> - <actionGroup ref="setAsDefaultOutOfStockProduct" stepKey="setAsDefaultOutOfStockProduct"/> + <magentoCLI command="config:set cataloginventory/options/show_out_of_stock 0" stepKey="displayOutOfStockNo2"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> <actionGroup ref="logout" stepKey="logout"/> - </after> <!--Open product page--> <comment userInput="Open product page" stepKey="openProdPage"/> @@ -44,7 +43,7 @@ <dontSeeElement selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="dontSeeAddToCompareLink"/> <!--Turn on 'out on stock' config--> <comment userInput="Turn on 'out of stock' config" stepKey="onOutOfStockConfig"/> - <createData entity="EnableDisplayOutOfStock" stepKey="displayOutOfStockYes"/> + <magentoCLI command="config:set cataloginventory/options/show_out_of_stock 1" stepKey="displayOutOfStockYes"/> <!--Clear cache and reindex--> <comment userInput="Clear cache and reindex" stepKey="cleanCache"/> <magentoCLI command="indexer:reindex" stepKey="reindex"/> @@ -66,10 +65,16 @@ <amOnPage url="{{StorefrontProductComparePage.url}}" stepKey="navigateToComparePage"/> <waitForPageLoad stepKey="waitForStorefrontProductComparePageLoad"/> <seeElement selector="{{StorefrontProductCompareMainSection.ProductLinkByName($product.name$)}}" stepKey="seeProductInCompareList"/> - <!--Add product to compare list fom Category page--> - <comment userInput="Add product to compare list fom Category page" stepKey="addToCmpFromCategPage"/> + <!--Go to Category page and delete product from comparison list--> + <comment userInput="Go to Category page and delete prduct from comparison list" stepKey="deletProdFromCmpList"/> <amOnPage url="{{StorefrontCategoryPage.url($$category.name$$)}}" stepKey="onCategoryPage"/> <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> + <click selector="{{StorefrontComparisonSidebarSection.ClearAll}}" stepKey="clickClearAll"/> + <waitForPageLoad time="30" stepKey="waitForConfirmPageLoad"/> + <click selector="{{AdminDeleteRoleSection.confirm}}" stepKey="confirmProdDelate"/> + <waitForPageLoad time="30" stepKey="waitForConfirmLoad"/> + <!--Add product to compare list from Category page--> + <comment userInput="Add product to compare list fom Category page" stepKey="addToCmpFromCategPage"/> <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverOverProduct"/> <click selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="clickAddToCompare"/> <waitForPageLoad stepKey="waitProdAddingToCmpList"/> diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml index 496284c0a4436..c7c9126f46803 100644 --- a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml +++ b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml @@ -26,13 +26,4 @@ <selectOption selector="{{InventoryConfigSection.DisplayOutOfStockDropdown}}" userInput="No" stepKey="switchToNo" /> <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig" /> </actionGroup> - <actionGroup name="setAsDefaultOutOfStockProduct"> - <amOnPage url="{{InventoryConfigurationPage.url}}" stepKey="navigateToInventoryConfigurationPage"/> - <waitForPageLoad time="30" stepKey="waitForConfigPageToLoad"/> - <conditionalClick selector="{{InventoryConfigSection.ProductStockOptionsTab}}" dependentSelector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" visible="false" stepKey="expandStockOptions"/> - <waitForElementVisible selector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" time="30" stepKey="waitForCheckBoxVisible"/> - <checkOption selector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" stepKey="uncheckUseSystemValue"/> - <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig"/> - <waitForPageLoad time="30" stepKey="waitForConfigPageToLoad2"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml b/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml deleted file mode 100644 index 6e0501aeba8ff..0000000000000 --- a/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> - <entity name="AdminDisplayOutOfStockYes" type="enable"> - <data key="value">1</data> - </entity> - <entity name="AdminDisplayOutOfStockNo" type="enable"> - <data key="value">0</data> - </entity> - <entity name="EnableDisplayOutOfStock" type="admin_out_of_stock_products_config"> - <requiredEntity type="enable">AdminDisplayOutOfStockYes</requiredEntity> - </entity> - <entity name="DisableDisplayOutOfStock" type="admin_out_of_stock_products_config"> - <requiredEntity type="enable">AdminDisplayOutOfStockNo</requiredEntity> - </entity> -</entities> diff --git a/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml b/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml deleted file mode 100644 index 5898c187bd5e7..0000000000000 --- a/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> - <operation name="AdminOutOfStockProductsConfig" dataType="admin_out_of_stock_products_config" type="create" auth="adminFormKey" url="/admin/system_config/save/section/cataloginventory/" method="POST"> - <object key="groups" dataType="admin_out_of_stock_products_config"> - <object key="options" dataType="admin_out_of_stock_products_config"> - <object key="fields" dataType="admin_out_of_stock_products_config"> - <object key="show_out_of_stock" dataType="enable"> - <field key="value">string</field> - </object> - </object> - </object> - </object> - </operation> -</operations> From d9b330c2bec0dab01b242eddb840eaa429d9b667 Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Tue, 2 Apr 2019 09:10:29 -0500 Subject: [PATCH 136/585] MC-4788: Convert DeleteSalesRuleEntityTest to MFTF Addressing second set of review comments --- .../AdminCreateCartPriceRuleActionsSectionActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml index dc67dfd68d589..6dfa10f95e7e6 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml @@ -25,7 +25,7 @@ </actionGroup> <actionGroup name="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup"> <arguments> - <argument name="ruleName" type="entity"/> + <argument name="ruleName" type="string"/> </arguments> <selectOption selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{ruleName.simple_free_shipping}}" stepKey="selectForMatchingItemsOnly"/> </actionGroup> From b78405cdbd04257ac760fea0d257ff54d5eea97c Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Tue, 2 Apr 2019 09:22:30 -0500 Subject: [PATCH 137/585] MC-4788: Convert DeleteSalesRuleEntityTest to MFTF Addressing third set of review comments --- .../AdminCreateCartPriceRuleActionsSectionActionGroup.xml | 2 +- ...SalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml index 6dfa10f95e7e6..66f89bfc37365 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml @@ -27,6 +27,6 @@ <arguments> <argument name="ruleName" type="string"/> </arguments> - <selectOption selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{ruleName.simple_free_shipping}}" stepKey="selectForMatchingItemsOnly"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{ruleName}}" stepKey="selectForMatchingItemsOnly"/> </actionGroup> </actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml index 20476858d58ce..4403010e1ffc9 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml @@ -44,7 +44,7 @@ <actionGroup ref="AdminCreateCartPriceRuleActionsSectionShippingAmountActionGroup" stepKey="createActiveCartPriceRuleShippingAmountActionsSection"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionSubsequentRulesActionGroup" stepKey="createActiveCartPriceRuleDiscardSubsequentRulesActionsSection"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> - <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> + <argument name="ruleName" value="{{ActiveSalesRuleWithComplexConditions.simple_free_shipping}}"/> </actionGroup> <!--Fill values for Labels Section--> <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> From a5ce676104e8d957e4f2405011256e1520f6eca6 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 2 Apr 2019 10:59:57 -0500 Subject: [PATCH 138/585] MC-4788: Convert DeleteSalesRuleEntityTest to MFTF - Remove unecessary click before selectOption --- .../AdminCreateCartPriceRuleConditionsSectionActionGroup.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml index 3c9e015300327..ab45aae46db1d 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml @@ -29,8 +29,6 @@ <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition2}}" stepKey="selectCondition2"/> <waitForPageLoad stepKey="waitForSecondConditionLoad"/> <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickTheEllipsis"/> - <click selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" stepKey="clickSelectCountryDropdown"/> - <waitForPageLoad stepKey="waitForDropdownLoad"/> <selectOption selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" userInput="{{ruleName.shippingCountry}}" stepKey="fillShippingCountryParameter"/> </actionGroup> <actionGroup name="AdminCreateCartPriceRuleConditionsSectionShippingPostcodeActionGroup"> From 716e27cd100c70f76cc905eb62543692b79ddfe8 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Tue, 2 Apr 2019 11:25:51 -0500 Subject: [PATCH 139/585] Issue-230: adding varnish --- app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php | 2 +- app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php | 3 +++ app/code/Magento/GraphQlCache/etc/graphql/di.xml | 4 ++-- .../PageCache/Model/Controller/Result/BuiltinPlugin.php | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php index a4832f262f555..fc7170619e79c 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -43,7 +43,7 @@ public function afterDispatch( /** @var \Magento\Framework\App\Request\Http $request */ /** @var \Magento\Framework\App\Response\Http $response */ $cacheTags = $this->cacheTags->getCacheTags(); - if ($request->isGet() && count($cacheTags)) { + if (count($cacheTags)) { // assume that response should be cacheable if it contains cache tags $response->setHeader('Pragma', 'cache', true); // TODO: Take from configuration diff --git a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php b/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php index 65b05bf71da0b..ba8b7ecf8b16b 100644 --- a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php +++ b/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php @@ -27,6 +27,9 @@ public function __construct(CacheTags $cacheTags) $this->cacheTags = $cacheTags; } + /** + * @inheritdoc + */ public function afterResolve( ResolverInterface $subject, $resolvedValue, diff --git a/app/code/Magento/GraphQlCache/etc/graphql/di.xml b/app/code/Magento/GraphQlCache/etc/graphql/di.xml index 93ed92066aafe..ae403e0c56bac 100644 --- a/app/code/Magento/GraphQlCache/etc/graphql/di.xml +++ b/app/code/Magento/GraphQlCache/etc/graphql/di.xml @@ -9,7 +9,7 @@ <type name="Magento\Framework\App\FrontControllerInterface"> <plugin name="cache" type="Magento\GraphQlCache\Controller\GraphQl\Plugin"/> <plugin name="front-controller-builtin-cache" type="Magento\PageCache\Model\App\FrontController\BuiltinPlugin"/> - <!--<plugin name="front-controller-varnish-cache" type="Magento\PageCache\Model\App\FrontController\VarnishPlugin"/>--> + <plugin name="front-controller-varnish-cache" type="Magento\PageCache\Model\App\FrontController\VarnishPlugin"/> </type> <type name="Magento\Framework\GraphQl\Query\ResolverInterface"> <plugin name="cache" type="Magento\GraphQlCache\Query\Resolver\Plugin"/> @@ -20,7 +20,7 @@ <!--</type>--> <type name="Magento\Framework\Controller\ResultInterface"> <plugin name="result-builtin-cache" type="Magento\PageCache\Model\Controller\Result\BuiltinPlugin"/> - <!--<plugin name="result-varnish-cache" type="Magento\PageCache\Model\Controller\Result\VarnishPlugin"/>--> + <plugin name="result-varnish-cache" type="Magento\PageCache\Model\Controller\Result\VarnishPlugin"/> </type> <type name="Magento\Framework\App\Response\Http"> <plugin name="response-http-page-cache" type="Magento\PageCache\Model\App\Response\HttpPlugin"/> diff --git a/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php b/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php index 871bc511d290a..aadae97009cac 100644 --- a/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php +++ b/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php @@ -87,8 +87,8 @@ public function afterRenderResult(ResultInterface $subject, ResultInterface $res $tags = []; if ($tagsHeader) { - //$tags = explode(',', $tagsHeader->getFieldValue()); - //$response->clearHeader('X-Magento-Tags'); + $tags = explode(',', $tagsHeader->getFieldValue()); + $response->clearHeader('X-Magento-Tags'); } $tags = array_unique(array_merge($tags, [CacheType::CACHE_TAG])); From 0f4a75d7c7521bf51adcdacc2284c0f4ede5ff78 Mon Sep 17 00:00:00 2001 From: pganapat <prabhuramgr28493@gmail.com> Date: Tue, 2 Apr 2019 11:45:27 -0500 Subject: [PATCH 140/585] 230: Implement cache tag generation for GraphQL queries - Modified schema stitcher to parse CacheTags from graphql schema - Modified Graphql plugin to gather resolved item ids - Validated the requests to be cached --- .../CatalogGraphQl/etc/schema.graphqls | 12 ++--- .../Controller/GraphQl/Plugin.php | 15 ++++++ .../GraphQlCache/Query/Resolver/Plugin.php | 47 ++++++++++++++++--- .../GraphQl/Config/Element/Field.php | 18 +++++++ .../GraphQl/Config/Element/FieldFactory.php | 10 +++- .../MetaReader/CacheTagReader.php | 34 ++++++++++++++ .../MetaReader/FieldMetaReader.php | 23 +++++++-- .../GraphQlReader/Reader/InputObjectType.php | 21 ++++++++- .../GraphQlReader/Reader/InterfaceType.php | 22 +++++++-- .../GraphQlReader/Reader/ObjectType.php | 19 +++++++- 10 files changed, 195 insertions(+), 26 deletions(-) create mode 100644 lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index f86ecea9e075d..11e447621eba1 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -9,11 +9,11 @@ type Query { currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") ): Products - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @cache(tag: "cat_p") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The test products query searches for products that match the criteria specified in the search and filter attributes") @cacheable(cache_tag: "cat_p") category ( id: Int @doc(description: "Id of the category") ): CategoryTree - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The test products query searches for products that match the criteria specified in the search and filter attributes") @cacheable(cache_tag: "cat_c") } enum CurrencyEnum @doc(description: "The list of available currency codes") { @@ -244,7 +244,7 @@ type ProductTierPrices @doc(description: "The ProductTierPrices object defines a website_id: Float @doc(description: "The ID assigned to the website") } -interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductInterfaceTypeResolverComposite") @doc(description: "The ProductInterface contains attributes that are common to all types of products. Note that descriptions may not be available for custom and EAV attributes.") { +interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductInterfaceTypeResolverComposite") @doc(description: "The ProductInterface contains attributes that are common to all types of products. Note that descriptions may not be available for custom and EAV attributes.") @cacheable(cache_tag: "cat_p") { id: Int @doc(description: "The ID number assigned to the product") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\EntityIdToId") name: String @doc(description: "The product name. Customers use this name to identify the product.") sku: String @doc(description: "A number or code assigned to a product to identify the product, options, price, and manufacturer") @@ -378,9 +378,9 @@ interface CustomizableProductInterface @typeResolver(class: "Magento\\CatalogGra options: [CustomizableOptionInterface] @doc(description: "An array of options for a customizable product") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Options") } -interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\CategoryInterfaceTypeResolver") @doc(description: "CategoryInterface contains the full set of attributes that can be returned in a category search") { +interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\CategoryInterfaceTypeResolver") @cacheable(cache_tag: "cat_c") @doc(description: "CategoryInterface contains the full set of attributes that can be returned in a category search") { id: Int @doc(description: "An ID that uniquely identifies the category") - description: String @doc(description: "An optional description of the category") @resolver(class: "\\Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryHtmlAttribute") + description: String @doc(description: "An optional description ofm the category") @resolver(class: "\\Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryHtmlAttribute") name: String @doc(description: "The display name of the category") path: String @doc(description: "Category Path") path_in_store: String @doc(description: "Category path in store") @@ -396,7 +396,7 @@ interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."), currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") - ): CategoryProducts @doc(description: "The list of products assigned to the category") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") + ): CategoryProducts @cacheable(cache_tag: "cat_p") @doc(description: "The list of products assigned to the category") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") breadcrumbs: [Breadcrumb] @doc(description: "Breadcrumbs, parent categories info") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Breadcrumbs") } diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php index fc7170619e79c..dc893322a6097 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -13,6 +13,11 @@ use Magento\GraphQlCache\Model\CacheTags; use Magento\Framework\App\State as AppState; +/** + * Class Plugin + + * @package Magento\GraphQlCache\Controller\GraphQl + */ class Plugin { /** @@ -26,6 +31,8 @@ class Plugin private $state; /** + * Constructor + * * @param CacheTags $cacheTags * @param AppState $state */ @@ -35,6 +42,14 @@ public function __construct(CacheTags $cacheTags, AppState $state) $this->state = $state; } + /** + * Plugin for GraphQL Controller + * + * @param FrontControllerInterface $subject + * @param ResponseInterface $response + * @param RequestInterface $request + * @return ResponseInterface|\Magento\Framework\Webapi\Response + */ public function afterDispatch( FrontControllerInterface $subject, /* \Magento\Framework\App\Response\Http */ $response, diff --git a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php b/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php index ba8b7ecf8b16b..c6a9ebb9180c5 100644 --- a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php +++ b/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php @@ -10,8 +10,15 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\GraphQl\Model\Query\Resolver\Context; use Magento\GraphQlCache\Model\CacheTags; +use Magento\Framework\App\RequestInterface; +/** + * Class Plugin + * + * @package Magento\GraphQlCache\Query\Resolver + */ class Plugin { /** @@ -20,15 +27,33 @@ class Plugin private $cacheTags; /** + * @var Request + */ + private $request; + + /** + * Constructor + * * @param CacheTags $cacheTags + * @param RequestInterface $request */ - public function __construct(CacheTags $cacheTags) + public function __construct(CacheTags $cacheTags, RequestInterface $request) { $this->cacheTags = $cacheTags; + $this->request = $request; } /** * @inheritdoc + * + * @param ResolverInterface $subject + * @param Object $resolvedValue + * @param Field $field + * @param Context $context + * @param ResolveInfo $info + * @param array|null $value + * @param array|null $args + * @return mixed */ public function afterResolve( ResolverInterface $subject, @@ -39,12 +64,8 @@ public function afterResolve( array $value = null, array $args = null ) { - if ($field->getName() == 'products') { - // TODO: Read cache tag value from the GraphQL schema and make it accessible via $field - $cacheTag = 'cat_p'; - } - // TODO: Can be optimized to avoid tags calculation for POST requests - if (!empty($cacheTag)) { + $cacheTag = $field->getCacheTag(); + if (!empty($cacheTag) && $this->request->isGet()) { $cacheTags = [$cacheTag]; // Resolved value must have cache IDs defined $resolvedItemsIds = $this->extractResolvedItemsIds($resolvedValue); @@ -56,6 +77,12 @@ public function afterResolve( return $resolvedValue; } + /** + * Extract ids for resolved items + * + * @param Object $resolvedValue + * @return array + */ private function extractResolvedItemsIds($resolvedValue) { // TODO: Implement safety checks and think about additional places which can hold items IDs @@ -66,6 +93,11 @@ private function extractResolvedItemsIds($resolvedValue) return array_keys($resolvedValue['items']); } $ids = []; + if (isset($resolvedValue['id'])) { + $ids[] = $resolvedValue['id']; + return $ids; + } + if (is_array($resolvedValue)) { foreach ($resolvedValue as $item) { if (isset($item['id'])) { @@ -73,5 +105,6 @@ private function extractResolvedItemsIds($resolvedValue) } } } + return $ids; } } diff --git a/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php b/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php index 76cfa06f9c11f..907b43424f08a 100644 --- a/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php +++ b/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php @@ -48,6 +48,11 @@ class Field implements OutputFieldInterface */ private $description; + /** + * @var string + */ + private $cacheTag; + /** * @param string $name * @param string $type @@ -56,6 +61,7 @@ class Field implements OutputFieldInterface * @param string $itemType * @param string $resolver * @param string $description + * @param string $cacheTag * @param array $arguments */ public function __construct( @@ -66,6 +72,7 @@ public function __construct( string $itemType = '', string $resolver = '', string $description = '', + string $cacheTag = '', array $arguments = [] ) { $this->name = $name; @@ -75,6 +82,7 @@ public function __construct( $this->resolver = $resolver; $this->description = $description; $this->arguments = $arguments; + $this->cacheTag = $cacheTag; } /** @@ -146,4 +154,14 @@ public function getDescription() : string { return $this->description; } + + /** + * Return the cache tag for the field. + * + * @return string|null + */ + public function getCacheTag() : string + { + return $this->cacheTag; + } } diff --git a/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php b/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php index b9ec1dd87d122..70805f2b51ba9 100644 --- a/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php +++ b/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php @@ -52,6 +52,13 @@ public function createFromConfigData( $fieldData['itemType'] = str_replace('[]', '', $fieldData['type']); } + if (isset($fieldData['description'])) { + if ($fieldData['description'] == "The list of products assigned to the category") { + $fieldType = $fieldData['type']; + } + } + + return $this->objectManager->create( Field::class, [ @@ -62,7 +69,8 @@ public function createFromConfigData( 'itemType' => isset($fieldData['itemType']) ? $fieldData['itemType'] : '', 'resolver' => isset($fieldData['resolver']) ? $fieldData['resolver'] : '', 'description' => isset($fieldData['description']) ? $fieldData['description'] : '', - 'arguments' => $arguments + 'cacheTag' => isset($fieldData['cacheable']) ? $fieldData['cacheable'] : false, + 'arguments' => $arguments, ] ); } diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php new file mode 100644 index 0000000000000..b2141a7ec8b9f --- /dev/null +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader; + +/** + * Reads documentation from the annotation @cacheable of an AST node + */ +class CacheTagReader +{ + /** + * Read documentation annotation for a specific node if exists + * + * @param \GraphQL\Language\AST\NodeList $directives + * @return string + */ + public function read(\GraphQL\Language\AST\NodeList $directives) : string + { + foreach ($directives as $directive) { + if ($directive->name->value == 'cacheable') { + foreach ($directive->arguments as $directiveArgument) { + if ($directiveArgument->name->value == 'cache_tag') { + return $directiveArgument->value->value; + } + } + } + } + return ''; + } +} diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php index 736a944711004..e916aae5ddfc8 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php @@ -7,8 +7,6 @@ namespace Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader; -use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\TypeMetaWrapperReader; - /** * Reads fields and possible arguments from a meta field */ @@ -25,13 +23,24 @@ class FieldMetaReader private $docReader; /** - * @param TypeMetaWrapperReader $typeMetaReader + * @var CacheTagReader + */ + private $cacheTagReader; + + /** + * FieldMetaReader constructor. + * @param \Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\TypeMetaWrapperReader $typeMetaReader * @param DocReader $docReader + * @param CacheTagReader $cacheTagReader */ - public function __construct(TypeMetaWrapperReader $typeMetaReader, DocReader $docReader) - { + public function __construct( + TypeMetaWrapperReader $typeMetaReader, + DocReader $docReader, + CacheTagReader $cacheTagReader + ) { $this->typeMetaReader = $typeMetaReader; $this->docReader = $docReader; + $this->cacheTagReader = $cacheTagReader; } /** @@ -63,6 +72,10 @@ public function read(\GraphQL\Type\Definition\FieldDefinition $fieldMeta) : arra $result['description'] = $this->docReader->read($fieldMeta->astNode->directives); } + if ($this->docReader->read($fieldMeta->astNode->directives)) { + $result['cacheable'] = $this->cacheTagReader->read($fieldMeta->astNode->directives); + } + $arguments = $fieldMeta->args; foreach ($arguments as $argumentMeta) { $argumentName = $argumentMeta->name; diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php index 3aea555e67f98..94326b8946698 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php @@ -10,6 +10,8 @@ use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\TypeMetaReaderInterface; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\TypeMetaWrapperReader; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\DocReader; +use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheTagReader; + /** * Composite configuration reader to handle the input object type meta @@ -27,13 +29,24 @@ class InputObjectType implements TypeMetaReaderInterface private $docReader; /** + * @var CacheTagReader + */ + private $cacheTagReader; + + /** + * InputObjectType constructor. * @param TypeMetaWrapperReader $typeMetaReader * @param DocReader $docReader + * @param CacheTagReader $cacheTagReader */ - public function __construct(TypeMetaWrapperReader $typeMetaReader, DocReader $docReader) - { + public function __construct( + TypeMetaWrapperReader $typeMetaReader, + DocReader $docReader, + CacheTagReader $cacheTagReader + ) { $this->typeMetaReader = $typeMetaReader; $this->docReader = $docReader; + $this->cacheTagReader = $cacheTagReader; } /** @@ -56,6 +69,10 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array if ($this->docReader->read($typeMeta->astNode->directives)) { $result['description'] = $this->docReader->read($typeMeta->astNode->directives); } + + if ($this->docReader->read($typeMeta->astNode->directives)) { + $result['cacheable'] = $this->cacheTagReader->read($typeMeta->astNode->directives); + } return $result; } else { return []; diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php index dd934ffebc2c1..bc1a65440ca09 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php @@ -10,6 +10,7 @@ use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\TypeMetaReaderInterface; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\FieldMetaReader; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\DocReader; +use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheTagReader; /** * Composite configuration reader to handle the interface object type meta @@ -27,17 +28,28 @@ class InterfaceType implements TypeMetaReaderInterface private $docReader; /** + * @var CacheTagReader + */ + private $cacheTagReader; + + /** + * InterfaceType constructor. * @param FieldMetaReader $fieldMetaReader * @param DocReader $docReader + * @param CacheTagReader $cacheTagReader */ - public function __construct(FieldMetaReader $fieldMetaReader, DocReader $docReader) - { + public function __construct( + FieldMetaReader $fieldMetaReader, + DocReader $docReader, + CacheTagReader $cacheTagReader + ) { $this->fieldMetaReader = $fieldMetaReader; $this->docReader = $docReader; + $this->cacheTagReader = $cacheTagReader; } /** - * {@inheritdoc} + * @inheritdoc */ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array { @@ -63,6 +75,10 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array $result['description'] = $this->docReader->read($typeMeta->astNode->directives); } + if ($this->docReader->read($typeMeta->astNode->directives)) { + $result['cacheable'] = $this->cacheTagReader->read($typeMeta->astNode->directives); + } + return $result; } else { return []; diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php index fb015922087b6..cf0545a21c4c3 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php @@ -11,6 +11,8 @@ use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\FieldMetaReader; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\DocReader; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\ImplementsReader; +use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheTagReader; + /** * Composite configuration reader to handle the object type meta @@ -33,22 +35,31 @@ class ObjectType implements TypeMetaReaderInterface private $implementsAnnotation; /** + * @var CacheTagReader + */ + private $cacheTagReader; + + /** + * ObjectType constructor. * @param FieldMetaReader $fieldMetaReader * @param DocReader $docReader * @param ImplementsReader $implementsAnnotation + * @param CacheTagReader $cacheTagReader */ public function __construct( FieldMetaReader $fieldMetaReader, DocReader $docReader, - ImplementsReader $implementsAnnotation + ImplementsReader $implementsAnnotation, + CacheTagReader $cacheTagReader ) { $this->fieldMetaReader = $fieldMetaReader; $this->docReader = $docReader; $this->implementsAnnotation = $implementsAnnotation; + $this->cacheTagReader = $cacheTagReader; } /** - * {@inheritdoc} + * @inheritdoc */ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array { @@ -77,6 +88,10 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array $result['description'] = $this->docReader->read($typeMeta->astNode->directives); } + if ($this->docReader->read($typeMeta->astNode->directives)) { + $result['cacheable'] = $this->cacheTagReader->read($typeMeta->astNode->directives); + } + return $result; } else { return []; From 6b3d4d688be5e747410e56fdda1f277767234205 Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Tue, 2 Apr 2019 16:02:56 -0500 Subject: [PATCH 141/585] MAGETWO-99022: Braintree Displaying Incorrect Ship-To Name --- .../Model/Paypal/Helper/QuoteUpdater.php | 28 +++++++++++++++++-- .../Model/Paypal/Helper/QuoteUpdaterTest.php | 6 ++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php b/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php index aa23fa767d1ed..11c51e07f1dd9 100644 --- a/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php +++ b/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php @@ -123,8 +123,8 @@ private function updateShippingAddress(Quote $quote, array $details) { $shippingAddress = $quote->getShippingAddress(); - $shippingAddress->setLastname($details['lastName']); - $shippingAddress->setFirstname($details['firstName']); + $shippingAddress->setLastname($this->getShippingRecipientLastName($details)); + $shippingAddress->setFirstname($this->getShippingRecipientFirstName($details)); $shippingAddress->setEmail($details['email']); $shippingAddress->setCollectShippingRates(true); @@ -188,4 +188,28 @@ private function updateAddressData(Address $address, array $addressData) $address->setSameAsBilling(false); $address->setCustomerAddressId(null); } + + /** + * Returns shipping recipient first name. + * + * @param array $details + * @return string + */ + private function getShippingRecipientFirstName(array $details) + { + return explode(' ', $details['shippingAddress']['recipientName'], 2)[0] + ?? $details['firstName']; + } + + /** + * Returns shipping recipient last name. + * + * @param array $details + * @return string + */ + private function getShippingRecipientLastName(array $details) + { + return explode(' ', $details['shippingAddress']['recipientName'], 2)[1] + ?? $details['lastName']; + } } diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Paypal/Helper/QuoteUpdaterTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Paypal/Helper/QuoteUpdaterTest.php index a2b5380d2884b..c2678d1c78437 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/Paypal/Helper/QuoteUpdaterTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/Paypal/Helper/QuoteUpdaterTest.php @@ -165,7 +165,7 @@ private function getDetails(): array 'region' => 'IL', 'postalCode' => '60618', 'countryCodeAlpha2' => 'US', - 'recipientName' => 'John Doe', + 'recipientName' => 'Jane Smith', ], 'billingAddress' => [ 'streetAddress' => '123 Billing Street', @@ -186,9 +186,9 @@ private function getDetails(): array private function updateShippingAddressStep(array $details): void { $this->shippingAddress->method('setLastname') - ->with($details['lastName']); + ->with('Smith'); $this->shippingAddress->method('setFirstname') - ->with($details['firstName']); + ->with('Jane'); $this->shippingAddress->method('setEmail') ->with($details['email']); $this->shippingAddress->method('setCollectShippingRates') From a09b0861e56e475d4d541c8c655e734cdc16a4c6 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Tue, 2 Apr 2019 16:15:14 -0500 Subject: [PATCH 142/585] MC-4440: Convert CreateScheduledProductUpdateTest to MFTF --- .../Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml index 83b541458ee9b..59fbeee142dfe 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml @@ -11,6 +11,5 @@ <section name="AdminProductMessagesSection"> <element name="successMessage" type="text" selector=".message-success"/> <element name="errorMessage" type="text" selector=".message.message-error.error"/> - <element name="adminMessage" type="text" selector="//*[contains(@class, 'message-error')]"/> </section> </sections> From 0cf8e69f56fc1a43c50c3e64a177b0960969d221 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Tue, 2 Apr 2019 16:49:53 -0500 Subject: [PATCH 143/585] Issue-230: refactor builtin cache to support store context --- .../HttpHeaderProcessor/StoreProcessor.php | 32 ++++++++-- .../Controller/GraphQl/Plugin.php | 61 ++++++++++--------- 2 files changed, 61 insertions(+), 32 deletions(-) diff --git a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php b/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php index e92ff374eb355..3571a7588d116 100644 --- a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php +++ b/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php @@ -11,6 +11,7 @@ use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\GraphQl\Controller\HttpHeaderProcessorInterface; use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\App\Http\Context as HttpContext; /** * Process the "Store" header entry @@ -23,13 +24,20 @@ class StoreProcessor implements HttpHeaderProcessorInterface private $storeManager; /** - * StoreProcessor constructor. - * + * @var HttpContext + */ + private $httpContext; + + /** * @param StoreManagerInterface $storeManager + * @param HttpContext $httpContext */ - public function __construct(StoreManagerInterface $storeManager) - { + public function __construct( + StoreManagerInterface $storeManager, + HttpContext $httpContext + ) { $this->storeManager = $storeManager; + $this->httpContext = $httpContext; } /** @@ -45,6 +53,7 @@ public function processHeaderValue(string $headerValue, HttpRequestInterface $re $stores = $this->storeManager->getStores(false, true); if (isset($stores[$storeCode])) { $this->storeManager->setCurrentStore($storeCode); + $this->updateContext($storeCode); } elseif (strtolower($storeCode) !== 'default') { throw new GraphQlInputException( new \Magento\Framework\Phrase('Store code %1 does not exist', [$storeCode]) @@ -52,4 +61,19 @@ public function processHeaderValue(string $headerValue, HttpRequestInterface $re } } } + + /** + * Update context accordingly to the store code found. + * + * @param string $store + * @return void + */ + private function updateContext(string $storeCode) : void + { + $this->httpContext->setValue( + StoreManagerInterface::CONTEXT_STORE, + $storeCode, + $this->storeManager->getDefaultStoreView()->getCode() + ); + } } diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php index dc893322a6097..151e044c32bef 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -10,13 +10,13 @@ use Magento\Framework\App\FrontControllerInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\ResponseInterface; +use Magento\Framework\App\Response\Http as HttpResponse; +use Magento\Framework\Controller\ResultInterface; use Magento\GraphQlCache\Model\CacheTags; -use Magento\Framework\App\State as AppState; +use Magento\PageCache\Model\Config; /** * Class Plugin - - * @package Magento\GraphQlCache\Controller\GraphQl */ class Plugin { @@ -26,48 +26,53 @@ class Plugin private $cacheTags; /** - * @var AppState + * @var Config */ - private $state; + private $config; + + /** + * @var HttpResponse + */ + private $response; /** - * Constructor - * * @param CacheTags $cacheTags - * @param AppState $state + * @param Config $config + * @param HttpResponse $response */ - public function __construct(CacheTags $cacheTags, AppState $state) - { + public function __construct( + CacheTags $cacheTags, + Config $config, + HttpResponse $response + ) { $this->cacheTags = $cacheTags; - $this->state = $state; + $this->config = $config; + $this->response = $response; } /** - * Plugin for GraphQL Controller + * Plugin for GraphQL after dispatch to set tag and cache headers + * + * The $response doesn't have a set type because it's alternating between ResponseInterface and ResultInterface. * * @param FrontControllerInterface $subject - * @param ResponseInterface $response + * @param ResponseInterface | ResultInterface $response * @param RequestInterface $request - * @return ResponseInterface|\Magento\Framework\Webapi\Response + * @return ResponseInterface | ResultInterface + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function afterDispatch( FrontControllerInterface $subject, - /* \Magento\Framework\App\Response\Http */ $response, + $response, RequestInterface $request ) { - /** @var \Magento\Framework\App\Request\Http $request */ - /** @var \Magento\Framework\App\Response\Http $response */ - $cacheTags = $this->cacheTags->getCacheTags(); - if (count($cacheTags)) { - // assume that response should be cacheable if it contains cache tags - $response->setHeader('Pragma', 'cache', true); - // TODO: Take from configuration - $response->setHeader('Cache-Control', 'max-age=86400, public, s-maxage=86400', true); - $response->setHeader('X-Magento-Tags', implode(',', $cacheTags), true); - } - - if ($request->isGet() && $this->state->getMode() == AppState::MODE_DEVELOPER) { - $response->setHeader('X-Magento-Debug', 1); + if ($this->config->isEnabled()) { + $this->response->setPublicHeaders($this->config->getTtl()); + $cacheTags = $this->cacheTags->getCacheTags(); + if (!empty($cacheTags)) { + // assume that response should be cacheable if it contains cache tags + $this->response->setHeader('X-Magento-Tags', implode(',', $cacheTags), true); + } } return $response; From 2022307ea1cb8b0310ced73026ac2a10e4910bdc Mon Sep 17 00:00:00 2001 From: Yuriy <yvechirko@magecom.net> Date: Wed, 3 Apr 2019 15:00:10 +0300 Subject: [PATCH 144/585] Error on design configuration save with imageUploader form element populated from gallery #21032 --- app/code/Magento/Theme/Model/Design/Backend/File.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Theme/Model/Design/Backend/File.php b/app/code/Magento/Theme/Model/Design/Backend/File.php index 511fe30f79dcd..037434b1c5268 100644 --- a/app/code/Magento/Theme/Model/Design/Backend/File.php +++ b/app/code/Magento/Theme/Model/Design/Backend/File.php @@ -237,7 +237,7 @@ private function getMime() */ private function getRelativeMediaPath(string $path): string { - return str_replace('/pub/media/', '', $path); + return preg_replace('/\/(pub\/)?media\//', '', $path); } /** From c79c277b3ccccae78be46f5e08aa2a57fea02119 Mon Sep 17 00:00:00 2001 From: Niklas <niklas@lynks.se> Date: Wed, 3 Apr 2019 14:12:44 +0200 Subject: [PATCH 145/585] setAttributeSetFilter accepts both integer and integer-array --- .../Eav/Model/ResourceModel/Entity/Attribute/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php index cec415e513677..d70e2e0e06e96 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php @@ -128,7 +128,7 @@ public function setEntityTypeFilter($type) /** * Specify attribute set filter * - * @param int $setId + * @param int|int[] $setId * @return $this */ public function setAttributeSetFilter($setId) From bc3ef7ad15b23869face298c51b2b3bd301326f8 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Tue, 2 Apr 2019 12:43:09 +0300 Subject: [PATCH 146/585] Fix static tests. --- lib/internal/Magento/Framework/App/Http.php | 11 ++++-- .../Framework/App/Test/Unit/HttpTest.php | 2 +- .../Test/Unit/Transfer/Adapter/HttpTest.php | 4 +++ .../Framework/File/Transfer/Adapter/Http.php | 34 +++++++++++++------ 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Http.php b/lib/internal/Magento/Framework/App/Http.php index 5c436ffdbc149..3564e5e0ecb9b 100644 --- a/lib/internal/Magento/Framework/App/Http.php +++ b/lib/internal/Magento/Framework/App/Http.php @@ -3,17 +3,18 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App; use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Debug; -use Magento\Framework\ObjectManager\ConfigLoaderInterface; use Magento\Framework\App\Request\Http as RequestHttp; use Magento\Framework\App\Response\Http as ResponseHttp; use Magento\Framework\App\Response\HttpInterface; use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\Debug; use Magento\Framework\Event; use Magento\Framework\Filesystem; +use Magento\Framework\ObjectManager\ConfigLoaderInterface; /** * HTTP web application. Called from webroot index.php to serve web requests. @@ -154,6 +155,7 @@ public function launch() /** * Handle HEAD requests by adding the Content-Length header and removing the body from the response. + * * @return void */ private function handleHeadRequest() @@ -266,7 +268,7 @@ private function redirectToSetup(Bootstrap $bootstrap, \Exception $exception) . "because the Magento setup directory cannot be accessed. \n" . 'You can install Magento using either the command line or you must restore access ' . 'to the following directory: ' . $setupInfo->getDir($projectRoot) . "\n"; - + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception($newMessage, 0, $exception); } } @@ -282,6 +284,7 @@ private function handleBootstrapErrors(Bootstrap $bootstrap, \Exception &$except { $bootstrapCode = $bootstrap->getErrorCode(); if (Bootstrap::ERR_MAINTENANCE == $bootstrapCode) { + // phpcs:ignore Magento2.Security.IncludeFile require $this->_filesystem->getDirectoryRead(DirectoryList::PUB)->getAbsolutePath('errors/503.php'); return true; } @@ -322,6 +325,7 @@ private function handleInitException(\Exception $exception) { if ($exception instanceof \Magento\Framework\Exception\State\InitException) { $this->getLogger()->critical($exception); + // phpcs:ignore Magento2.Security.IncludeFile require $this->_filesystem->getDirectoryRead(DirectoryList::PUB)->getAbsolutePath('errors/404.php'); return true; } @@ -353,6 +357,7 @@ private function handleGenericReport(Bootstrap $bootstrap, \Exception $exception if (isset($params['SCRIPT_NAME'])) { $reportData['script_name'] = $params['SCRIPT_NAME']; } + // phpcs:ignore Magento2.Security.IncludeFile require $this->_filesystem->getDirectoryRead(DirectoryList::PUB)->getAbsolutePath('errors/report.php'); return true; } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php index b2d041ac175f5..48a1242a90d4f 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php @@ -175,6 +175,7 @@ public function testLaunchException() $this->frontControllerMock->expects($this->once())->method('dispatch')->with($this->requestMock)->will( $this->returnCallback( function () { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Message'); } ) @@ -182,7 +183,6 @@ function () { $this->http->launch(); } - /** * Test that HEAD requests lead to an empty body and a Content-Length header matching the original body size. * @dataProvider dataProviderForTestLaunchHeadRequest diff --git a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php index 56375d5178820..92db004ae8e8e 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php @@ -3,10 +3,14 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\File\Test\Unit\Transfer\Adapter; use \Magento\Framework\File\Transfer\Adapter\Http; +/** + * Tests http transfer adapter. + */ class HttpTest extends \PHPUnit\Framework\TestCase { /** diff --git a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php index 386ee0e5bb940..7cafb826f766d 100644 --- a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php +++ b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php @@ -6,9 +6,11 @@ namespace Magento\Framework\File\Transfer\Adapter; +/** + * File adapter to send the file to the client. + */ class Http { - /** * @var \Magento\Framework\HTTP\PhpEnvironment\Response */ @@ -25,7 +27,7 @@ class Http private $request; /** - * @param \Magento\Framework\App\Response\Http $response + * @param \Magento\Framework\HTTP\PhpEnvironment\Response $response * @param \Magento\Framework\File\Mime $mime * @param \Magento\Framework\App\Request\Http|null $request */ @@ -56,14 +58,7 @@ public function send($options = null) throw new \InvalidArgumentException("File '{$filepath}' does not exists."); } - $mimeType = $this->mime->getMimeType($filepath); - if (is_array($options) && isset($options['headers']) && $options['headers'] instanceof \Zend\Http\Headers) { - $this->response->setHeaders($options['headers']); - } - $this->response->setHeader('Content-length', filesize($filepath)); - $this->response->setHeader('Content-Type', $mimeType); - - $this->response->sendHeaders(); + $this->prepareResponse($options, $filepath); if ($this->request->isHead()) { // Do not send the body on HEAD requests. @@ -73,6 +68,7 @@ public function send($options = null) $handle = fopen($filepath, 'r'); if ($handle) { while (($buffer = fgets($handle, 4096)) !== false) { + // phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput echo $buffer; } if (!feof($handle)) { @@ -103,4 +99,22 @@ private function getFilePath($options): string return $filePath; } + + /** + * Set and send all necessary headers. + * + * @param array $options + * @param string $filepath + */ + protected function prepareResponse($options, string $filepath): void + { + $mimeType = $this->mime->getMimeType($filepath); + if (is_array($options) && isset($options['headers']) && $options['headers'] instanceof \Zend\Http\Headers) { + $this->response->setHeaders($options['headers']); + } + $this->response->setHeader('Content-length', filesize($filepath)); + $this->response->setHeader('Content-Type', $mimeType); + + $this->response->sendHeaders(); + } } From 887001d4b731f9cd1f326cfed056657df7e475ca Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Thu, 4 Apr 2019 00:15:57 +0530 Subject: [PATCH 147/585] Added Confirmation field in customer form --- .../Customer/Model/Customer/DataProviderWithDefaultAddresses.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/Customer/DataProviderWithDefaultAddresses.php b/app/code/Magento/Customer/Model/Customer/DataProviderWithDefaultAddresses.php index 4d1bb2e6b9e99..07b8681df91ac 100644 --- a/app/code/Magento/Customer/Model/Customer/DataProviderWithDefaultAddresses.php +++ b/app/code/Magento/Customer/Model/Customer/DataProviderWithDefaultAddresses.php @@ -39,7 +39,6 @@ class DataProviderWithDefaultAddresses extends \Magento\Ui\DataProvider\Abstract private static $forbiddenCustomerFields = [ 'password_hash', 'rp_token', - 'confirmation', ]; /** From 4c04f5513ce93072c4fca53ebd99d2dac94b28fd Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Thu, 4 Apr 2019 00:18:19 +0530 Subject: [PATCH 148/585] Fixed #22052 Customer account confirmation is overwritten by backend customer save --- .../Customer/view/base/ui_component/customer_form.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml index 7e6b7bbe9cd09..e87997dbdb5e9 100644 --- a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml +++ b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml @@ -74,6 +74,17 @@ <visible>false</visible> </settings> </field> + <field name="confirmation" formElement="input"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + <settings> + <dataType>text</dataType> + <visible>false</visible> + </settings> + </field> <field name="created_in" formElement="input"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> From 8d33059afbfe9cf2204722928c35320614b0c649 Mon Sep 17 00:00:00 2001 From: pganapat <prabhuramgr28493@gmail.com> Date: Wed, 3 Apr 2019 14:00:38 -0500 Subject: [PATCH 149/585] 230: Implement cache tag generation for GraphQL queries - Used @cache to parse cache tags - Fetched ttl from config - Refactoring --- .../CatalogGraphQl/etc/schema.graphqls | 14 ++-- .../Controller/GraphQl/Plugin.php | 50 +++++++++----- .../Magento/GraphQlCache/Model/CacheInfo.php | 67 +++++++++++++++++++ .../Magento/GraphQlCache/Model/CacheTags.php | 36 ---------- .../GraphQlCache/Query/Resolver/Plugin.php | 33 ++++++--- .../GraphQl/Config/Element/Field.php | 16 ++--- .../GraphQl/Config/Element/FieldFactory.php | 2 +- .../MetaReader/CacheTagReader.php | 20 ++++-- .../MetaReader/FieldMetaReader.php | 2 +- .../GraphQlReader/Reader/InputObjectType.php | 2 +- .../GraphQlReader/Reader/InterfaceType.php | 2 +- .../GraphQlReader/Reader/ObjectType.php | 2 +- 12 files changed, 159 insertions(+), 87 deletions(-) create mode 100644 app/code/Magento/GraphQlCache/Model/CacheInfo.php delete mode 100644 app/code/Magento/GraphQlCache/Model/CacheTags.php diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 11e447621eba1..8b74e5cc2cd76 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -9,11 +9,11 @@ type Query { currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") ): Products - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The test products query searches for products that match the criteria specified in the search and filter attributes") @cacheable(cache_tag: "cat_p") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_p", cacheable: true) category ( id: Int @doc(description: "Id of the category") ): CategoryTree - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The test products query searches for products that match the criteria specified in the search and filter attributes") @cacheable(cache_tag: "cat_c") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_c", cacheable: true) } enum CurrencyEnum @doc(description: "The list of available currency codes") { @@ -244,7 +244,7 @@ type ProductTierPrices @doc(description: "The ProductTierPrices object defines a website_id: Float @doc(description: "The ID assigned to the website") } -interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductInterfaceTypeResolverComposite") @doc(description: "The ProductInterface contains attributes that are common to all types of products. Note that descriptions may not be available for custom and EAV attributes.") @cacheable(cache_tag: "cat_p") { +interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductInterfaceTypeResolverComposite") @doc(description: "The ProductInterface contains attributes that are common to all types of products. Note that descriptions may not be available for custom and EAV attributes.") { id: Int @doc(description: "The ID number assigned to the product") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\EntityIdToId") name: String @doc(description: "The product name. Customers use this name to identify the product.") sku: String @doc(description: "A number or code assigned to a product to identify the product, options, price, and manufacturer") @@ -275,7 +275,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available") manufacturer: Int @doc(description: "A number representing the product's manufacturer") - categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") + categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @cache(cache_tag: "cat_c", cacheable: true) @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") canonical_url: String @doc(description: "Canonical URL") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\CanonicalUrl") } @@ -378,9 +378,9 @@ interface CustomizableProductInterface @typeResolver(class: "Magento\\CatalogGra options: [CustomizableOptionInterface] @doc(description: "An array of options for a customizable product") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Options") } -interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\CategoryInterfaceTypeResolver") @cacheable(cache_tag: "cat_c") @doc(description: "CategoryInterface contains the full set of attributes that can be returned in a category search") { +interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\CategoryInterfaceTypeResolver") @doc(description: "CategoryInterface contains the full set of attributes that can be returned in a category search") { id: Int @doc(description: "An ID that uniquely identifies the category") - description: String @doc(description: "An optional description ofm the category") @resolver(class: "\\Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryHtmlAttribute") + description: String @doc(description: "An optional description of the category") @resolver(class: "\\Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryHtmlAttribute") name: String @doc(description: "The display name of the category") path: String @doc(description: "Category Path") path_in_store: String @doc(description: "Category path in store") @@ -396,7 +396,7 @@ interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."), currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") - ): CategoryProducts @cacheable(cache_tag: "cat_p") @doc(description: "The list of products assigned to the category") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") + ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cache_tag: "cat_p", cacheable: true) @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") breadcrumbs: [Breadcrumb] @doc(description: "Breadcrumbs, parent categories info") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Breadcrumbs") } diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php index dc893322a6097..0770aead72893 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -10,20 +10,23 @@ use Magento\Framework\App\FrontControllerInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\ResponseInterface; -use Magento\GraphQlCache\Model\CacheTags; +use Magento\GraphQlCache\Model\CacheInfo; use Magento\Framework\App\State as AppState; +use \Magento\Framework\App\Config\ScopeConfigInterface; /** * Class Plugin - + * * @package Magento\GraphQlCache\Controller\GraphQl */ class Plugin { + const CACHE_TTL = 'system/full_page_cache/ttl'; + /** - * @var CacheTags + * @var CacheInfo */ - private $cacheTags; + private $cacheInfo; /** * @var AppState @@ -31,15 +34,21 @@ class Plugin private $state; /** - * Constructor - * - * @param CacheTags $cacheTags + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * Plugin constructor. + * @param CacheInfo $cacheInfo * @param AppState $state + * @param ScopeConfigInterface $scopeConfig */ - public function __construct(CacheTags $cacheTags, AppState $state) + public function __construct(CacheInfo $cacheInfo, AppState $state, ScopeConfigInterface $scopeConfig) { - $this->cacheTags = $cacheTags; + $this->cacheInfo = $cacheInfo; $this->state = $state; + $this->scopeConfig = $scopeConfig; } /** @@ -55,14 +64,13 @@ public function afterDispatch( /* \Magento\Framework\App\Response\Http */ $response, RequestInterface $request ) { - /** @var \Magento\Framework\App\Request\Http $request */ - /** @var \Magento\Framework\App\Response\Http $response */ - $cacheTags = $this->cacheTags->getCacheTags(); - if (count($cacheTags)) { - // assume that response should be cacheable if it contains cache tags + $cacheTags = $this->cacheInfo->getCacheTags(); + $isCacheValid = $this->cacheInfo->isCacheable(); + $ttl = $this->getTtl(); + + if (count($cacheTags) && $isCacheValid) { $response->setHeader('Pragma', 'cache', true); - // TODO: Take from configuration - $response->setHeader('Cache-Control', 'max-age=86400, public, s-maxage=86400', true); + $response->setHeader('Cache-Control', 'max-age='.$ttl.', public, s-maxage='.$ttl.'', true); $response->setHeader('X-Magento-Tags', implode(',', $cacheTags), true); } @@ -72,4 +80,14 @@ public function afterDispatch( return $response; } + + /** + * Return page lifetime + * + * @return int + */ + private function getTtl() + { + return $this->scopeConfig->getValue(self::CACHE_TTL); + } } diff --git a/app/code/Magento/GraphQlCache/Model/CacheInfo.php b/app/code/Magento/GraphQlCache/Model/CacheInfo.php new file mode 100644 index 0000000000000..57c46f6c2139d --- /dev/null +++ b/app/code/Magento/GraphQlCache/Model/CacheInfo.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Model; + +use Magento\Eav\Model\Attribute\Data\Boolean; + +/** + * CacheInfo object is a registry for collecting cache related info and tags of all entities. + */ +class CacheInfo +{ + /** + * @var string[] + */ + private $cacheTags = []; + + /** + * @var bool + */ + private $cacheable = true; + + /** + * Return cache tags + * + * @return array + */ + public function getCacheTags(): array + { + return $this->cacheTags; + } + + /** + * Add Cache Tags + * + * @param array $cacheTags + * @return void + */ + public function addCacheTags(array $cacheTags): void + { + $this->cacheTags = array_merge($this->cacheTags, $cacheTags); + } + + /** + * Returns if its valid to cache the response + * + * @return bool + */ + public function isCacheable(): bool + { + return $this->cacheable; + } + + /** + * Sets cache validity + * + * @param bool $cacheable + */ + public function setCacheValidity(bool $cacheable): void + { + $this->cacheable = $cacheable; + } +} diff --git a/app/code/Magento/GraphQlCache/Model/CacheTags.php b/app/code/Magento/GraphQlCache/Model/CacheTags.php deleted file mode 100644 index 6889a873a3f05..0000000000000 --- a/app/code/Magento/GraphQlCache/Model/CacheTags.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQlCache\Model; - -/** - * Cache tags object is a registry for collecting cache tags of all entities used in the GraphQL query response. - */ -class CacheTags -{ - /** - * @var string[] - */ - private $cacheTags = []; - - /** - * @return string[] - */ - public function getCacheTags(): array - { - return $this->cacheTags; - } - - /** - * @param string[] $tags - * @return void - */ - public function addCacheTags(array $cacheTags): void - { - $this->cacheTags = array_merge($this->cacheTags, $cacheTags); - } -} diff --git a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php b/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php index c6a9ebb9180c5..2ff9c8a10b18f 100644 --- a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php +++ b/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php @@ -11,7 +11,7 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\GraphQl\Model\Query\Resolver\Context; -use Magento\GraphQlCache\Model\CacheTags; +use Magento\GraphQlCache\Model\CacheInfo; use Magento\Framework\App\RequestInterface; /** @@ -22,9 +22,9 @@ class Plugin { /** - * @var CacheTags + * @var CacheInfo */ - private $cacheTags; + private $cacheInfo; /** * @var Request @@ -34,12 +34,12 @@ class Plugin /** * Constructor * - * @param CacheTags $cacheTags + * @param CacheInfo $cacheInfo * @param RequestInterface $request */ - public function __construct(CacheTags $cacheTags, RequestInterface $request) + public function __construct(CacheInfo $cacheInfo, RequestInterface $request) { - $this->cacheTags = $cacheTags; + $this->cacheInfo = $cacheInfo; $this->request = $request; } @@ -64,16 +64,19 @@ public function afterResolve( array $value = null, array $args = null ) { - $cacheTag = $field->getCacheTag(); - if (!empty($cacheTag) && $this->request->isGet()) { + $cache = $field->getCache(); + $cacheTag = isset($cache['cache_tag']) ? $cache['cache_tag'] : []; + $cacheable = isset($cache['cacheable']) ? $cache['cacheable'] : true; + if (!empty($cacheTag) && $this->request->isGet() && $cacheable) { $cacheTags = [$cacheTag]; // Resolved value must have cache IDs defined $resolvedItemsIds = $this->extractResolvedItemsIds($resolvedValue); foreach ($resolvedItemsIds as $itemId) { $cacheTags[] = $cacheTag . '_' . $itemId; } - $this->cacheTags->addCacheTags($cacheTags); + $this->cacheInfo->addCacheTags($cacheTags); } + $this->setCacheValidity($cacheable); return $resolvedValue; } @@ -85,7 +88,6 @@ public function afterResolve( */ private function extractResolvedItemsIds($resolvedValue) { - // TODO: Implement safety checks and think about additional places which can hold items IDs if (isset($resolvedValue['ids']) && is_array($resolvedValue['ids'])) { return $resolvedValue['ids']; } @@ -107,4 +109,15 @@ private function extractResolvedItemsIds($resolvedValue) } return $ids; } + + /** + * Set cache validity for the graphql request + * + * @param bool $isValid + */ + private function setCacheValidity(bool $isValid): void + { + $cacheValidity = $this->cacheInfo->isCacheable() && $isValid; + $this->cacheInfo->setCacheValidity($cacheValidity); + } } diff --git a/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php b/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php index 907b43424f08a..dc59e490a0203 100644 --- a/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php +++ b/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php @@ -49,9 +49,9 @@ class Field implements OutputFieldInterface private $description; /** - * @var string + * @var array */ - private $cacheTag; + private $cache; /** * @param string $name @@ -61,7 +61,7 @@ class Field implements OutputFieldInterface * @param string $itemType * @param string $resolver * @param string $description - * @param string $cacheTag + * @param array $cache * @param array $arguments */ public function __construct( @@ -72,7 +72,7 @@ public function __construct( string $itemType = '', string $resolver = '', string $description = '', - string $cacheTag = '', + array $cache = [], array $arguments = [] ) { $this->name = $name; @@ -82,7 +82,7 @@ public function __construct( $this->resolver = $resolver; $this->description = $description; $this->arguments = $arguments; - $this->cacheTag = $cacheTag; + $this->cache = $cache; } /** @@ -158,10 +158,10 @@ public function getDescription() : string /** * Return the cache tag for the field. * - * @return string|null + * @return array|null */ - public function getCacheTag() : string + public function getCache() : array { - return $this->cacheTag; + return $this->cache; } } diff --git a/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php b/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php index 70805f2b51ba9..000fcc298708e 100644 --- a/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php +++ b/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php @@ -69,7 +69,7 @@ public function createFromConfigData( 'itemType' => isset($fieldData['itemType']) ? $fieldData['itemType'] : '', 'resolver' => isset($fieldData['resolver']) ? $fieldData['resolver'] : '', 'description' => isset($fieldData['description']) ? $fieldData['description'] : '', - 'cacheTag' => isset($fieldData['cacheable']) ? $fieldData['cacheable'] : false, + 'cache' => isset($fieldData['cache']) ? $fieldData['cache'] : [], 'arguments' => $arguments, ] ); diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php index b2141a7ec8b9f..6fa66b80a8c81 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php @@ -16,19 +16,29 @@ class CacheTagReader * Read documentation annotation for a specific node if exists * * @param \GraphQL\Language\AST\NodeList $directives - * @return string + * @return array */ - public function read(\GraphQL\Language\AST\NodeList $directives) : string + public function read(\GraphQL\Language\AST\NodeList $directives) : array { + $argMap = []; foreach ($directives as $directive) { - if ($directive->name->value == 'cacheable') { + if ($directive->name->value == 'cache') { foreach ($directive->arguments as $directiveArgument) { if ($directiveArgument->name->value == 'cache_tag') { - return $directiveArgument->value->value; + $argMap = array_merge( + $argMap, + ["cache_tag" => $directiveArgument->value->value] + ); + } + if ($directiveArgument->name->value == 'cacheable') { + $argMap = array_merge( + $argMap, + ["cacheable" => $directiveArgument->value->value] + ); } } } } - return ''; + return $argMap; } } diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php index e916aae5ddfc8..97f169054a071 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php @@ -73,7 +73,7 @@ public function read(\GraphQL\Type\Definition\FieldDefinition $fieldMeta) : arra } if ($this->docReader->read($fieldMeta->astNode->directives)) { - $result['cacheable'] = $this->cacheTagReader->read($fieldMeta->astNode->directives); + $result['cache'] = $this->cacheTagReader->read($fieldMeta->astNode->directives); } $arguments = $fieldMeta->args; diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php index 94326b8946698..e8c4f2721f65e 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php @@ -71,7 +71,7 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array } if ($this->docReader->read($typeMeta->astNode->directives)) { - $result['cacheable'] = $this->cacheTagReader->read($typeMeta->astNode->directives); + $result['cache'] = $this->cacheTagReader->read($typeMeta->astNode->directives); } return $result; } else { diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php index bc1a65440ca09..2020f42dcaefe 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php @@ -76,7 +76,7 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array } if ($this->docReader->read($typeMeta->astNode->directives)) { - $result['cacheable'] = $this->cacheTagReader->read($typeMeta->astNode->directives); + $result['cache'] = $this->cacheTagReader->read($typeMeta->astNode->directives); } return $result; diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php index cf0545a21c4c3..5d38d1444e4fd 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php @@ -89,7 +89,7 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array } if ($this->docReader->read($typeMeta->astNode->directives)) { - $result['cacheable'] = $this->cacheTagReader->read($typeMeta->astNode->directives); + $result['cache'] = $this->cacheTagReader->read($typeMeta->astNode->directives); } return $result; From 436c2dd80309e22379c34626f5e3a102201d737a Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Wed, 3 Apr 2019 15:25:53 -0500 Subject: [PATCH 150/585] MAGETWO-99022: Braintree Displaying Incorrect Ship-To Name - Logger added to controller - Recipient name array cell check added --- .../Magento/Braintree/Controller/Paypal/Review.php | 13 ++++++++++++- .../Braintree/Model/Paypal/Helper/QuoteUpdater.php | 10 ++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Braintree/Controller/Paypal/Review.php b/app/code/Magento/Braintree/Controller/Paypal/Review.php index eb2de7c7b6e39..eb11a2e1adf5e 100644 --- a/app/code/Magento/Braintree/Controller/Paypal/Review.php +++ b/app/code/Magento/Braintree/Controller/Paypal/Review.php @@ -14,6 +14,7 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Payment\Model\Method\Logger; /** * Class Review @@ -25,6 +26,11 @@ class Review extends AbstractAction implements HttpPostActionInterface, HttpGetA */ private $quoteUpdater; + /** + * @var Logger + */ + private $logger; + /** * @var string */ @@ -37,15 +43,18 @@ class Review extends AbstractAction implements HttpPostActionInterface, HttpGetA * @param Config $config * @param Session $checkoutSession * @param QuoteUpdater $quoteUpdater + * @param Logger $logger */ public function __construct( Context $context, Config $config, Session $checkoutSession, - QuoteUpdater $quoteUpdater + QuoteUpdater $quoteUpdater, + Logger $logger ) { parent::__construct($context, $config, $checkoutSession); $this->quoteUpdater = $quoteUpdater; + $this->logger = $logger; } /** @@ -84,6 +93,8 @@ public function execute() return $resultPage; } catch (\Exception $e) { $this->messageManager->addExceptionMessage($e, $e->getMessage()); + } finally { + $this->logger->debug($requestData); } /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ diff --git a/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php b/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php index 11c51e07f1dd9..ae2b1b1423640 100644 --- a/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php +++ b/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php @@ -197,8 +197,9 @@ private function updateAddressData(Address $address, array $addressData) */ private function getShippingRecipientFirstName(array $details) { - return explode(' ', $details['shippingAddress']['recipientName'], 2)[0] - ?? $details['firstName']; + return isset($details['shippingAddress']['recipientName']) + ? explode(' ', $details['shippingAddress']['recipientName'], 2)[0] + : $details['firstName']; } /** @@ -209,7 +210,8 @@ private function getShippingRecipientFirstName(array $details) */ private function getShippingRecipientLastName(array $details) { - return explode(' ', $details['shippingAddress']['recipientName'], 2)[1] - ?? $details['lastName']; + return isset($details['shippingAddress']['recipientName']) + ? explode(' ', $details['shippingAddress']['recipientName'], 2)[1] + : $details['lastName']; } } From 9c309fce24d21c86fab5e60f551bc65277c5bcf5 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Wed, 3 Apr 2019 16:38:52 -0500 Subject: [PATCH 151/585] MC-4571: Convert CreateCustomerSegmentEntityWithCustomerConditionsPartOneTest to MFTF --- ...CheckCartDiscountAndSummaryActionGroup.xml | 22 +++++++++ .../Customer/Test/Mftf/Data/CustomerData.xml | 13 ++++++ .../StorefrontNewsletterManageSection.xml | 1 + .../AdminCreateCartPriceRuleActionGroup.xml | 5 +++ .../AdminDeleteCartPriceRuleActionGroup.xml | 22 +++++++++ ...WIthSegmentForCartPriceRuleActionGroup.xml | 45 +++++++++++++++++++ .../Test/Mftf/Data/SalesRuleData.xml | 16 +++++++ .../AdminCartPriceRulesFormSection.xml | 9 ++++ 8 files changed, 133 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminDeleteCartPriceRuleActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml new file mode 100644 index 0000000000000..b8a989ba2cf35 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Open the Minicart and check Summary --> + <actionGroup name="StorefrontCheckCartDiscountAndSummaryActionGroup"> + <arguments> + <argument name="product" type="entity"/> + <argument name="total" type="string"/> + <argument name="discount" type="string"/> + </arguments> + <waitForPageLoad stepKey="waitForSummary"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-${{discount}}" stepKey="assertDiscount"/> + <see selector="{{CheckoutCartSummarySection.total}}" userInput="${{total}}" stepKey="assertTotal"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index 4796fd73e104f..636c404b2458b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -216,4 +216,17 @@ <data key="store_id">0</data> <data key="website_id">0</data> </entity> + <entity name="Retailer_Customer" type="customer"> + <data key="group_id">3</data> + <data key="default_billing">true</data> + <data key="default_shipping">true</data> + <data key="email" unique="prefix">John.Doe@example.com</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="fullname">John Doe</data> + <data key="password">pwdTest123!</data> + <data key="store_id">0</data> + <data key="website_id">0</data> + <requiredEntity type="address">US_Address_CA</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml b/app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml index 96a944a4952ac..9248970d9e623 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontNewsletterManageSection"> <element name="subscriptionCheckbox" type="checkbox" selector="#subscription" /> + <element name="saveButton" type="button" selector="div.primary>button"/> </section> </sections> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml index cc165e0b5dc96..b690d0190bdd1 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml @@ -24,6 +24,11 @@ <see selector="{{AdminCartPriceRulesFormSection.successMessage}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleAndStayOnEditActionGroup" extends="AdminCreateCartPriceRuleActionGroup" > + <click selector="{{AdminCartPriceRulesFormSection.discardSubsequentRules}}" stepKey="setYesDiscardSubsequentRule" after="clickToExpandActions"/> + <click selector="{{AdminCartPriceRulesFormSection.saveAndContinue}}" stepKey="clickSaveButton"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleWithCouponCode" extends="AdminCreateCartPriceRuleActionGroup"> <arguments> <argument name="couponCode" defaultValue="_defaultCoupon.code"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminDeleteCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminDeleteCartPriceRuleActionGroup.xml new file mode 100644 index 0000000000000..88f9bf2fbe54d --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminDeleteCartPriceRuleActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminDeleteCartPriceRuleActionGroup"> + <arguments> + <argument name="ruleName" type="entity"/> + </arguments> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="goToCartPriceRules"/> + <waitForPageLoad stepKey="waitForCartPriceRules"/> + <fillField selector="{{AdminCartPriceRulesSection.filterByNameInput}}" userInput="{{ruleName.name}}" stepKey="filterByName"/> + <click selector="{{AdminCartPriceRulesSection.searchButton}}" stepKey="doFilter"/> + <click selector="{{AdminCartPriceRulesSection.rowByIndex('1')}}" stepKey="goToEditRulePage"/> + <click selector="{{AdminCartPriceRulesFormSection.delete}}" stepKey="clickDeleteButton"/> + <click selector="{{AdminCartPriceRulesFormSection.modalAcceptButton}}" stepKey="confirmDelete"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup.xml new file mode 100644 index 0000000000000..855da5228d493 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"><!--Set condition for Customer Segment--> + <actionGroup name="SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup"> + <arguments> + <argument name="attributeName" type="string"/> + <argument name="value" type="entity"/> + </arguments> + + <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToActionTab"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeaderOpen}}" visible="false" stepKey="openActionTab"/> + <click selector="{{AdminCartPriceRulesFormSection.conditions}}" stepKey="applyRuleForConditions"/> + + <waitForPageLoad stepKey="waitForDropDownOpened"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.childAttribute}}" userInput="{{attributeName}}" stepKey="selectAttribute"/> + + <waitForPageLoad time="20" stepKey="waitForOperator"/> + <click selector="{{AdminCartPriceRulesFormSection.condition('...')}}" stepKey="clickToChooseOption1"/> + <click selector="{{AdminCartPriceRulesFormSection.openList}}" stepKey="openList" /> + <waitForPageLoad time="20" stepKey="waitForGrid"/> + <fillField selector="{{AdminCartPriceRulesFormSection.searchSegmentName}}" userInput="{{value.name}}" stepKey="fillSegmentName"/> + <click selector="{{AdminCartPriceRulesFormSection.searchButton}}" stepKey="clickButtonSearch"/> + + <waitForPageLoad stepKey="waitForResults"/> + <checkOption selector="{{AdminCartPriceRulesFormSection.selectAll}}" stepKey="checkAll"/> + <waitForPageLoad stepKey="waitForChecking"/> + <moveMouseOver selector="{{AdminCartPriceRulesFormSection.setSegment}}" stepKey="moveOnButton"/> + <click selector="{{AdminCartPriceRulesFormSection.setSegment}}" stepKey="setCustomerSegment"/> + <click selector="{{AdminMainActionsSection.saveAndContinue}}" stepKey="clickSaveButton"/> + <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> + </actionGroup> + <actionGroup name="SetCartAttributeConditionWhenMatchForCartPriceRuleActionGroup" extends="SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup"> + <arguments> + <argument name="operatorType" type="string" defaultValue="matches"/> + </arguments> + <click selector="{{AdminCartPriceRulesFormSection.condition('matches')}}" stepKey="clickToChooseOption" after="waitForOperator"/> + <selectOption userInput="{{operatorType}}" selector="{{AdminCartPriceRulesFormSection.conditionsOperator}}" stepKey="setOperatorType" after="clickToChooseOption"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml index 8f6e63534b0ca..aa0220ea523f4 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml @@ -193,4 +193,20 @@ <entity name="SalesRuleNoCouponWithFixedDiscount" extends="ApiCartRule"> <data key="simple_action">by_fixed</data> </entity> + + <entity name="RetailerCartPriceRule" type="SalesRule"> + <data key="name" unique="suffix">Cart Price Rule</data> + <data key="websites">Main Website</data> + <data key="customerGroups">'Retailer'</data> + <data key="apply">Percent of product price discount</data> + <data key="discountAmount">50</data> + </entity> + + <entity name="SegmentCartPriceRule" type="SalesRule"> + <data key="name" unique="suffix">Cart Price Rule</data> + <data key="websites">Main Website</data> + <data key="customerGroups">'General'</data> + <data key="apply">Percent of product price discount</data> + <data key="discountAmount">50</data> + </entity> </entities> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml index c8da82407457d..48d2a2685fcbe 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml @@ -40,6 +40,14 @@ <element name="openChooser" type="button" selector="//label[@for='conditions__{{arg}}__value']" parameterized="true"/> <element name="categoryCheckbox" type="checkbox" selector="//span[contains(text(), '{{arg}}')]/parent::a/preceding-sibling::input[@type='checkbox']" parameterized="true"/> + <!--Conditions checker --> + <element name="openList" type="button" selector="a.rule-chooser-trigger>img.v-middle.rule-chooser-trigger"/> + <element name="searchSegmentName" type="input" selector="//div[@class='rule-chooser']//input[@name='grid_segment_name']"/> + <element name="searchButton" type="button" selector="div.admin__filter-actions>button.action-default.scalable.action-secondary" timeout="10" /> + <element name="selectAll" type="checkbox" selector="//*[@class='rule-chooser']//input[contains(@class, 'admin__control-checkbox')]" timeout="10"/> + <element name="resetSearchFilter" type="button" selector="//div[@class='admin__filter-actions']//button[@title='Reset Filter']"/> + <element name="setSegment" type="button" selector="//*[@class='rule-tree-wrapper']//a[@class='rule-param-apply']"/> + <!-- Actions sub-form --> <element name="actionsTab" type="text" selector="//div[@data-index='actions']//span[contains(.,'Actions')][1]"/> <element name="actionsHeader" type="button" selector="div[data-index='actions']" timeout="30"/> @@ -57,6 +65,7 @@ <element name="actionOperator" type="select" selector=".rule-param-edit select"/> <element name="applyDiscountToShipping" type="checkbox" selector="input[name='apply_to_shipping']"/> <element name="applyDiscountToShippingLabel" type="checkbox" selector="input[name='apply_to_shipping']+label"/> + <element name="discardSubsequentRules" type="checkbox" selector="input[name='stop_rules_processing']+label"/> <element name="discountAmount" type="input" selector="input[name='discount_amount']"/> <element name="discountStep" type="input" selector="input[name='discount_step']"/> <element name="addRewardPoints" type="input" selector="input[name='extension_attributes[reward_points_delta]']"/> From 7a888a02edf0a04185cccc1949e58a958df294bd Mon Sep 17 00:00:00 2001 From: Davit_Zakharyan <davit_zakharyan@epam.com> Date: Thu, 4 Apr 2019 11:33:24 +0400 Subject: [PATCH 152/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Added automated test script. --- .../Test/Mftf/Data/ShippingMethodsData.xml | 17 +++++++ .../shipping_methods_ups_type_config-meta.xml | 21 +++++++++ .../Page/AdminShippingMethodsConfigPage.xml | 14 ++++++ .../AdminShippingMethodsUpsSection.xml | 16 +++++++ .../Mftf/Test/DefaultConfigForUPSTypeTest.xml | 45 +++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 app/code/Magento/Ups/Test/Mftf/Data/ShippingMethodsData.xml create mode 100644 app/code/Magento/Ups/Test/Mftf/Metadata/shipping_methods_ups_type_config-meta.xml create mode 100644 app/code/Magento/Ups/Test/Mftf/Page/AdminShippingMethodsConfigPage.xml create mode 100644 app/code/Magento/Ups/Test/Mftf/Section/AdminShippingMethodsUpsSection.xml create mode 100644 app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml diff --git a/app/code/Magento/Ups/Test/Mftf/Data/ShippingMethodsData.xml b/app/code/Magento/Ups/Test/Mftf/Data/ShippingMethodsData.xml new file mode 100644 index 0000000000000..d4156d4f3358b --- /dev/null +++ b/app/code/Magento/Ups/Test/Mftf/Data/ShippingMethodsData.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="ShippingMethodsUpsTypeSetDefault" type="shipping_methods_ups_type_config"> + <requiredEntity type="ups_type_inherit">ShippingMethodsUpsTypeDefault</requiredEntity> + </entity> + <entity name="ShippingMethodsUpsTypeDefault" type="ups_type_inherit"> + <data key="inherit">true</data> + </entity> +</entities> diff --git a/app/code/Magento/Ups/Test/Mftf/Metadata/shipping_methods_ups_type_config-meta.xml b/app/code/Magento/Ups/Test/Mftf/Metadata/shipping_methods_ups_type_config-meta.xml new file mode 100644 index 0000000000000..d642b7923282e --- /dev/null +++ b/app/code/Magento/Ups/Test/Mftf/Metadata/shipping_methods_ups_type_config-meta.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> + <operation name="ShippingMethodsUpsTypeConfig" dataType="shipping_methods_ups_type_config" type="create" auth="adminFormKey" url="admin/system_config/save/section/carriers/" method="POST"> + <object key="groups" dataType="shipping_methods_ups_type_config"> + <object key="ups" dataType="shipping_methods_ups_type_config"> + <object key="fields" dataType="shipping_methods_ups_type_config"> + <object key="type" dataType="ups_type_inherit"> + <field key="inherit">boolean</field> + </object> + </object> + </object> + </object> + </operation> +</operations> diff --git a/app/code/Magento/Ups/Test/Mftf/Page/AdminShippingMethodsConfigPage.xml b/app/code/Magento/Ups/Test/Mftf/Page/AdminShippingMethodsConfigPage.xml new file mode 100644 index 0000000000000..ebc44aace6dfb --- /dev/null +++ b/app/code/Magento/Ups/Test/Mftf/Page/AdminShippingMethodsConfigPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminShippingMethodsConfigPage" url="admin/system_config/edit/section/carriers/" area="admin" module="Magento_Ups"> + <section name="AdminShippingMethodsUpsSection"/> + </page> +</pages> diff --git a/app/code/Magento/Ups/Test/Mftf/Section/AdminShippingMethodsUpsSection.xml b/app/code/Magento/Ups/Test/Mftf/Section/AdminShippingMethodsUpsSection.xml new file mode 100644 index 0000000000000..4107f17dbc18c --- /dev/null +++ b/app/code/Magento/Ups/Test/Mftf/Section/AdminShippingMethodsUpsSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminShippingMethodsUpsSection"> + <element name="carriersUpsTab" type="button" selector="#carriers_ups-head"/> + <element name="carriersUpsType" type="select" selector="#carriers_ups_type"/> + <element name="selectedUpsType" type="text" selector="#carriers_ups_type option[selected]"/> + </section> +</sections> diff --git a/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml b/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml new file mode 100644 index 0000000000000..9a168f0bd6197 --- /dev/null +++ b/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="DefaultConfigForUPSTypeTest"> + <annotations> + <title value="Default Configuration for UPS Type"/> + <description value="Default Configuration for UPS Type"/> + <features value="Ups"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-99012"/> + <useCaseId value="MAGETWO-98947"/> + <group value="ups"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!--Collapse UPS tab and logout--> + <comment userInput="Collapse UPS tab and logout" stepKey="collapseTabAndLogout"/> + <click selector="{{AdminShippingMethodsUpsSection.carriersUpsTab}}" stepKey="collapseTab"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!-- Set shipping methods UPS type to default --> + <comment userInput="Set shipping methods UPS type to default" stepKey="setToDefaultShippingMethodsUpsType"/> + <createData entity="ShippingMethodsUpsTypeSetDefault" stepKey="setShippingMethodsUpsTypeToDefault"/> + <!-- Navigate to Stores -> Configuration -> Sales -> Shipping Methods Page --> + <comment userInput="Navigate to Stores -> Configuration -> Sales -> Shipping Methods Page" stepKey="goToAdminShippingMethodsPage"/> + <amonPage url="{{AdminShippingMethodsConfigPage.url}}" stepKey="navigateToAdminShippingMethodsPage"/> + <waitForPageLoad stepKey="waitPageToLoad"/> + <!-- Expand 'UPS' tab --> + <comment userInput="Expand UPS tab" stepKey="expandUpsTab"/> + <conditionalClick selector="{{AdminShippingMethodsUpsSection.carriersUpsTab}}" dependentSelector="{{AdminShippingMethodsUpsSection.carriersUpsType}}" visible="false" stepKey="expandTab"/> + <waitForElementVisible selector="{{AdminShippingMethodsUpsSection.carriersUpsType}}" stepKey="waitTabToExpand"/> + <!-- Assert that selected UPS type by default is 'United Parcel Service XML' --> + <comment userInput="Check that selected UPS type by default is 'United Parcel Service XML'" stepKey="assertDefUpsType"/> + <grabTextFrom selector="{{AdminShippingMethodsUpsSection.selectedUpsType}}" stepKey="grabSelectedOptionText"/> + <assertEquals expected='United Parcel Service XML' expectedType="string" actual="($grabSelectedOptionText)" stepKey="assertDefaultUpsType"/> + </test> +</tests> From 719ed40200caeedc87bd56545d4727afb889bed0 Mon Sep 17 00:00:00 2001 From: Vishal Sutariya <vishalsutariya7037@gmail.com> Date: Thu, 4 Apr 2019 14:06:46 +0530 Subject: [PATCH 153/585] Fixed shipping & payment section design for create order layout --- .../templates/order/create/data.phtml | 18 ++++++++++-------- .../web/css/source/module/_order.less | 1 + 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml index 170fea937348d..fdbaae2347398 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml @@ -47,15 +47,17 @@ </div> </section> - <section id="shipping-methods" class="admin__page-section order-methods"> - <div id="order-shipping_method" class="admin__page-section-item order-shipping-method"> - <?= $block->getChildHtml('shipping_method') ?> + <section id="order-methods" class="admin__page-section order-methods"> + <div class="admin__page-section-title"> + <span class="title"><?= /* @escapeNotVerified */ __('Payment & Shipping Information') ?></span> </div> - </section> - - <section id="payment-methods" class="admin__page-section payment-methods"> - <div id="order-billing_method" class="admin__page-section-item order-billing-method"> - <?= $block->getChildHtml('billing_method') ?> + <div class="admin__page-section-content"> + <div id="order-billing_method" class="admin__page-section-item order-billing-method"> + <?= $block->getChildHtml('billing_method') ?> + </div> + <div id="order-shipping_method" class="admin__page-section-item order-shipping-method"> + <?= $block->getChildHtml('shipping_method') ?> + </div> </div> </section> diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less index 480fc57c1149d..ffa5ee963952c 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less @@ -55,6 +55,7 @@ } .order-billing-address, + .order-billing-method, .order-history, .order-information, .order-payment-method, From d661d613c17ba25304f2aa1f21e67bc97dff509d Mon Sep 17 00:00:00 2001 From: priti <priti@twojay.in> Date: Thu, 4 Apr 2019 16:26:05 +0530 Subject: [PATCH 154/585] Can't-scroll-in-modal-popup-on-iOS --- .../blank/web/css/source/components/_modals_extend.less | 3 +-- .../Magento/luma/web/css/source/components/_modals_extend.less | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less b/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less index 5cdb1444094e9..2ab9f061c60c1 100644 --- a/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less +++ b/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less @@ -148,10 +148,9 @@ } } } -} -.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { .modal-popup { + pointer-events: auto; &.modal-slide { .modal-inner-wrap[class] { .lib-css(background-color, @modal-slide-mobile__background-color); diff --git a/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less b/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less index 3814341efd05a..48a8b0bc6b591 100644 --- a/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less +++ b/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less @@ -148,10 +148,9 @@ } } } -} -.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { .modal-popup { + pointer-events: auto; &.modal-slide { .modal-inner-wrap[class] { .lib-css(background-color, @modal-slide-mobile__background-color); From 70e7580f7c1f326c6a6773269c74165c48ef9e16 Mon Sep 17 00:00:00 2001 From: Arnoud Beekman <arnoud.beekman@mediact.nl> Date: Thu, 4 Apr 2019 14:46:15 +0200 Subject: [PATCH 155/585] Remove duplicate styling This styling was defined exactly the same twice. --- .../blank/Magento_Catalog/web/css/source/_module.less | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less index d3b314836ae8e..299c138832064 100644 --- a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less @@ -507,17 +507,6 @@ min-height: inherit; } } - - // - // Category page 1 column layout - // --------------------------------------------- - - .catalog-category-view.page-layout-1column { - .column.main { - min-height: inherit; - } - } - } // From e5c1b94d1b254af46d06c162466b7137cb120a06 Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Thu, 4 Apr 2019 20:54:04 +0530 Subject: [PATCH 156/585] Fixed Unit test failure --- .../Unit/Model/Customer/DataProviderWithDefaultAddressesTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderWithDefaultAddressesTest.php b/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderWithDefaultAddressesTest.php index 2fc3cdb927723..d5eaecb3ef35f 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderWithDefaultAddressesTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderWithDefaultAddressesTest.php @@ -339,7 +339,6 @@ public function testGetData(): void 'default_shipping' => 2, 'password_hash' => 'password_hash', 'rp_token' => 'rp_token', - 'confirmation' => 'confirmation', ]; $address = $this->getMockBuilder(\Magento\Customer\Model\Address::class) From 9b9044330cea0735b6743b3a4d29d846597785b0 Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Thu, 4 Apr 2019 11:02:50 -0500 Subject: [PATCH 157/585] MAGETWO-99022: Braintree Displaying Incorrect Ship-To Name - Logging moved from finally block --- app/code/Magento/Braintree/Controller/Paypal/Review.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Braintree/Controller/Paypal/Review.php b/app/code/Magento/Braintree/Controller/Paypal/Review.php index eb11a2e1adf5e..2923db6fa88c3 100644 --- a/app/code/Magento/Braintree/Controller/Paypal/Review.php +++ b/app/code/Magento/Braintree/Controller/Paypal/Review.php @@ -66,6 +66,7 @@ public function execute() $this->getRequest()->getPostValue('result', '{}'), true ); + $this->logger->debug($requestData); $quote = $this->checkoutSession->getQuote(); try { @@ -93,8 +94,6 @@ public function execute() return $resultPage; } catch (\Exception $e) { $this->messageManager->addExceptionMessage($e, $e->getMessage()); - } finally { - $this->logger->debug($requestData); } /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ From 81cec7fb17e44a1e865f24775e9ca26e33e76a66 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Thu, 4 Apr 2019 11:31:34 -0500 Subject: [PATCH 158/585] MC-4328: Convert AddProductsToCartBySkuFromCustomerAccountTest to MFTF --- ...inAddMinimumAdvertisedPriceActionGroup.xml | 21 +++++++++++++++ .../Catalog/Test/Mftf/Data/ProductData.xml | 26 +++++++++++++++++++ .../Test/Mftf/Data/ProductOptionData.xml | 9 +++++++ .../Test/Mftf/Data/ProductOptionValueData.xml | 14 ++++++++++ .../Catalog/Test/Mftf/Data/TierPriceData.xml | 8 ++++++ ...AdminProductFormAdvancedPricingSection.xml | 1 + .../Section/CheckoutCartProductSection.xml | 1 + .../Magento/Msrp/Test/Mftf/Data/MsrpData.xml | 14 ++++++++++ 8 files changed, 94 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddMinimumAdvertisedPriceActionGroup.xml create mode 100644 app/code/Magento/Msrp/Test/Mftf/Data/MsrpData.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddMinimumAdvertisedPriceActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddMinimumAdvertisedPriceActionGroup.xml new file mode 100644 index 0000000000000..f0eef98748f8d --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddMinimumAdvertisedPriceActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminAddMinimumAdvertisedPriceActionGroup"> + <arguments> + <argument name="msrpData" type="entity"/> + </arguments> + <waitForPageLoad stepKey="waitForPageLoad"/> + <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.msrp}}" stepKey="waitSpecialPrice"/> + <fillField selector="{{AdminProductFormAdvancedPricingSection.msrp}}" userInput="{{msrpData.msrp}}" stepKey="fillMinimumAdvertisedPrice"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.msrpType}}" userInput="{{msrpData.msrp_display_actual_price_type}}" stepKey="selectPriceType"/> + <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDone"/> + <waitForElementNotVisible selector="{{AdminProductFormAdvancedPricingSection.msrp}}" stepKey="waitForCloseModalWindow"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 63eb67be31c2e..a4d6d152ef38f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -163,6 +163,28 @@ <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity> </entity> + <entity name="SimpleProductDisabled" type="product"> + <data key="sku" unique="suffix">simple_product_disabled</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="name" unique="suffix">Simple Product Disabled</data> + <data key="price">123.00</data> + <data key="visibility">4</data> + <data key="status">2</data> + <data key="quantity">1001</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + </entity> + <entity name="SimpleProductNotVisibleIndividually" type="product"> + <data key="sku" unique="suffix">simple_product_not_visible_individually</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="name" unique="suffix">Simple Product Not Visible Individually</data> + <data key="price">123.00</data> + <data key="visibility">1</data> + <data key="status">1</data> + <data key="quantity">1000</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + </entity> <entity name="NewSimpleProduct" type="product"> <data key="price">321.00</data> </entity> @@ -432,6 +454,10 @@ <var key="sku" entityType="product" entityKey="sku" /> <requiredEntity type="product_option">ProductOptionDropDownWithLongValuesTitle</requiredEntity> </entity> + <entity name="productWithDropdownOption" type="product"> + <var key="sku" entityType="product" entityKey="sku" /> + <requiredEntity type="product_option">ProductOptionValueDropdown</requiredEntity> + </entity> <entity name="ProductWithTextFieldAndAreaOptions" type="product"> <var key="sku" entityType="product" entityKey="sku" /> <requiredEntity type="product_option">ProductOptionField</requiredEntity> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml index 36ec649fdde70..e91438dc7ce44 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml @@ -68,6 +68,15 @@ <requiredEntity type="product_option_value">ProductOptionValueDropdownLongTitle1</requiredEntity> <requiredEntity type="product_option_value">ProductOptionValueDropdownLongTitle2</requiredEntity> </entity> + <entity name="ProductOptionValueDropdown" type="product_option"> + <var key="product_sku" entityType="product" entityKey="sku" /> + <data key="title">OptionDropDown</data> + <data key="type">drop_down</data> + <data key="sort_order">4</data> + <data key="is_require">true</data> + <requiredEntity type="product_option_value">ProductDropdownOption1</requiredEntity> + <requiredEntity type="product_option_value">ProductDropdownOption2</requiredEntity> + </entity> <entity name="ProductOptionRadiobutton" type="product_option"> <var key="product_sku" entityType="product" entityKey="sku" /> <data key="title">OptionRadioButtons</data> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml index 8e9c0f86b38c7..94778edebf066 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml @@ -68,4 +68,18 @@ <data key="price">20</data> <data key="price_type">percent</data> </entity> + <entity name="ProductDropdownOption1" type="product_option_value"> + <data key="title">ProductDropdownOption1</data> + <data key="sort_order">1</data> + <data key="price">10</data> + <data key="price_type">fixed</data> + <data key="sku">product_dropdown_option_1_sku</data> + </entity> + <entity name="ProductDropdownOption2" type="product_option_value"> + <data key="title">ProductDropdownOption2</data> + <data key="sort_order">1</data> + <data key="price">10</data> + <data key="price_type">fixed</data> + <data key="sku">product_dropdown_option_2_sku</data> + </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml index e5070340421a9..0c88c666a20ca 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml @@ -56,4 +56,12 @@ <data key="quantity">2</data> <var key="sku" entityType="product2" entityKey="sku" /> </entity> + <entity name="tierProductPriceDefault" type="catalogTierPrice"> + <data key="price">90.00</data> + <data key="price_type">fixed</data> + <data key="website_id">0</data> + <data key="customer_group">ALL GROUPS</data> + <data key="quantity">30</data> + <var key="sku" entityType="product" entityKey="sku" /> + </entity> </entities> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml index 697648cedb7ba..a2cce12da663e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml @@ -21,6 +21,7 @@ <element name="specialPrice" type="input" selector="input[name='product[special_price]']"/> <element name="doneButton" type="button" selector=".product_form_product_form_advanced_pricing_modal button.action-primary" timeout="5"/> <element name="msrp" type="input" selector="//input[@name='product[msrp]']" timeout="30"/> + <element name="msrpType" type="select" selector="//select[@name='product[msrp_display_actual_price_type]']" timeout="30"/> <element name="save" type="button" selector="#save-button"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml index 1fdbf11d48f1d..d406ef05ef210 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml @@ -34,5 +34,6 @@ <element name="productSubtotalByName" type="input" selector="//main//table[@id='shopping-cart-table']//tbody//tr[..//strong[contains(@class, 'product-item-name')]//a/text()='{{var1}}'][1]//td[contains(@class, 'subtotal')]//span[@class='price']" parameterized="true"/> <element name="updateShoppingCartButton" type="button" selector="#form-validate button[type='submit'].update" timeout="30"/> <element name="qty" type="input" selector="//input[@data-cart-item-id='{{var}}'][@title='Qty']" parameterized="true"/> + <element name="emptyCart" selector=".cart-empty" type="text"/> </section> </sections> diff --git a/app/code/Magento/Msrp/Test/Mftf/Data/MsrpData.xml b/app/code/Magento/Msrp/Test/Mftf/Data/MsrpData.xml new file mode 100644 index 0000000000000..f311e3c06e9ff --- /dev/null +++ b/app/code/Magento/Msrp/Test/Mftf/Data/MsrpData.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="MsrpBeforeOrderConfirmation" type="minimum_advertised_price"> + <data key="msrp">600</data> + <data key="msrp_display_actual_price_type">Before Order Confirmation</data> + </entity> +</entities> From aa44e8106948d52151485ae7520bcb94f8ae7e47 Mon Sep 17 00:00:00 2001 From: pganapat <prabhuramgr28493@gmail.com> Date: Thu, 4 Apr 2019 12:05:00 -0500 Subject: [PATCH 159/585] 230: Implement cache tag generation for GraphQL queries - Configured vcl to consume store and currency as a part of header key. --- app/code/Magento/PageCache/etc/varnish4.vcl | 7 +++++++ app/code/Magento/PageCache/etc/varnish5.vcl | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/app/code/Magento/PageCache/etc/varnish4.vcl b/app/code/Magento/PageCache/etc/varnish4.vcl index 8068447e5ca99..35c43171cd9be 100644 --- a/app/code/Magento/PageCache/etc/varnish4.vcl +++ b/app/code/Magento/PageCache/etc/varnish4.vcl @@ -122,6 +122,13 @@ sub vcl_hash { hash_data(server.ip); } + if (req.http.store) { + hash_data(req.http.store); + } + if (req.http.Content-Currency) { + hash_data(req.http.Content-Currency); + } + # To make sure http users don't see ssl warning if (req.http./* {{ ssl_offloaded_header }} */) { hash_data(req.http./* {{ ssl_offloaded_header }} */); diff --git a/app/code/Magento/PageCache/etc/varnish5.vcl b/app/code/Magento/PageCache/etc/varnish5.vcl index 6c8414a5cb641..67f9786bd3cd2 100644 --- a/app/code/Magento/PageCache/etc/varnish5.vcl +++ b/app/code/Magento/PageCache/etc/varnish5.vcl @@ -128,6 +128,13 @@ sub vcl_hash { hash_data(req.http./* {{ ssl_offloaded_header }} */); } /* {{ design_exceptions_code }} */ + + if (req.http.store) { + hash_data(req.http.store); + } + if (req.http.Content-Currency) { + hash_data(req.http.Content-Currency); + } } sub vcl_backend_response { From b71ba967a3ba4efb76778da425529ed9ec94a9cc Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 4 Apr 2019 13:20:20 -0500 Subject: [PATCH 160/585] MAGETWO-98853: reporting_system_updates table exceptionally large (4gb) --- .../Model/Module/Collect.php | 4 +-- .../Test/Unit/Model/Module/CollectTest.php | 12 -------- .../Model/Module/CollectTest.php | 29 +++++++++++++++++++ 3 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php diff --git a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php index 7e381762f5d27..75adb46987fb3 100644 --- a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php +++ b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php @@ -277,9 +277,7 @@ public function getModuleData($refresh = true) $changes = array_diff($module, $changeTest); $changesCleanArray = $this->getCleanChangesArray($changes); - if (count($changesCleanArray) > 0 || - ($this->moduleManager->isOutputEnabled($changeTest['name']) && - $module['setup_version'] != null)) { + if ($changesCleanArray) { $data = [ 'entity_id' => $changeTest['entity_id'], 'name' => $changeTest['name'], diff --git a/app/code/Magento/NewRelicReporting/Test/Unit/Model/Module/CollectTest.php b/app/code/Magento/NewRelicReporting/Test/Unit/Model/Module/CollectTest.php index 8d8e6255ab8d3..4286406d6e9ab 100644 --- a/app/code/Magento/NewRelicReporting/Test/Unit/Model/Module/CollectTest.php +++ b/app/code/Magento/NewRelicReporting/Test/Unit/Model/Module/CollectTest.php @@ -162,10 +162,6 @@ public function testGetModuleDataWithoutRefresh() ->method('getNames') ->willReturn($enabledModulesMockArray); - $this->moduleManagerMock->expects($this->any())->method('isOutputEnabled')->will( - $this->returnValue(false) - ); - $this->assertInternalType( 'array', $this->model->getModuleData() @@ -256,10 +252,6 @@ public function testGetModuleDataRefresh($data) ->method('getNames') ->willReturn($enabledModulesMockArray); - $this->moduleManagerMock->expects($this->any())->method('isOutputEnabled')->will( - $this->returnValue(true) - ); - $this->assertInternalType( 'array', $this->model->getModuleData() @@ -350,10 +342,6 @@ public function testGetModuleDataRefreshOrStatement($data) ->method('getNames') ->willReturn($enabledModulesMockArray); - $this->moduleManagerMock->expects($this->any())->method('isOutputEnabled')->will( - $this->returnValue(true) - ); - $this->assertInternalType( 'array', $this->model->getModuleData() diff --git a/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php new file mode 100644 index 0000000000000..4243ca7ab626d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\NewRelicReporting\Model\Module; + +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +class CollectTest extends TestCase +{ + /** + * @var Collect + */ + private $collect; + + protected function setUp() + { + $this->collect = Bootstrap::getObjectManager()->create(Collect::class); + } + + public function testReport() + { + $this->collect->getModuleData(); + $moduleData = $this->collect->getModuleData(); + $this->assertEmpty($moduleData['changes']); + } +} From a56559cfa4c4cdb75605d92a08b8ac6aefa0c896 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 4 Apr 2019 13:48:32 -0500 Subject: [PATCH 161/585] MAGETWO-98853: reporting_system_updates table exceptionally large (4gb) --- app/code/Magento/NewRelicReporting/Model/Module/Collect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php index 75adb46987fb3..ac7e4df9331c3 100644 --- a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php +++ b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php @@ -277,7 +277,7 @@ public function getModuleData($refresh = true) $changes = array_diff($module, $changeTest); $changesCleanArray = $this->getCleanChangesArray($changes); - if ($changesCleanArray) { + if (!empty($changesCleanArray)) { $data = [ 'entity_id' => $changeTest['entity_id'], 'name' => $changeTest['name'], From 9677f7370d914060b0e812bcc3bcfab5fbbf52ca Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 4 Apr 2019 14:36:57 -0500 Subject: [PATCH 162/585] Issue-230: implementing builtin cache - fix the builtin to work with store cookie - address headers processing - remove x magento vary cookie support --- .../HttpHeaderProcessor/CurrencyProcessor.php | 84 +++++++++++++++++++ .../DirectoryGraphQl/etc/graphql/di.xml | 16 ++++ .../Magento/GraphQl/Controller/GraphQl.php | 15 +--- .../ContentTypeProcessor.php | 4 +- app/code/Magento/GraphQl/composer.json | 1 - app/code/Magento/GraphQl/etc/graphql/di.xml | 1 - app/code/Magento/GraphQl/etc/module.xml | 1 - .../Controller/GraphQl/Plugin.php | 30 ++++++- .../Model/App/CacheIdentifierPlugin.php | 43 +++++++--- app/code/Magento/GraphQlCache/composer.json | 1 + .../Magento/GraphQlCache/etc/graphql/di.xml | 11 +-- .../HttpHeaderProcessor/StoreProcessor.php | 35 +++++++- app/code/Magento/StoreGraphQl/composer.json | 4 +- .../Magento/StoreGraphQl/etc/graphql/di.xml | 16 ++++ app/code/Magento/StoreGraphQl/etc/module.xml | 1 + 15 files changed, 219 insertions(+), 44 deletions(-) create mode 100644 app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php create mode 100644 app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml rename app/code/Magento/{GraphQl => StoreGraphQl}/Controller/HttpHeaderProcessor/StoreProcessor.php (66%) create mode 100644 app/code/Magento/StoreGraphQl/etc/graphql/di.xml diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php new file mode 100644 index 0000000000000..23e1a2f1d4cf5 --- /dev/null +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php @@ -0,0 +1,84 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor; + +use Magento\Framework\App\HttpRequestInterface; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\GraphQl\Controller\HttpHeaderProcessorInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\App\Http\Context as HttpContext; + +/** + * Process the "Currency" header entry + */ +class CurrencyProcessor implements HttpHeaderProcessorInterface +{ + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var HttpContext + */ + private $httpContext; + + /** + * @var \Magento\Framework\Session\SessionManagerInterface + */ + private $session; + + /** + * @param StoreManagerInterface $storeManager + * @param HttpContext $httpContext + */ + public function __construct( + StoreManagerInterface $storeManager, + HttpContext $httpContext, + \Magento\Framework\Session\SessionManagerInterface $session + ) { + $this->storeManager = $storeManager; + $this->httpContext = $httpContext; + $this->session = $session; + } + + /** + * Handle the header 'Content-Currency' value. + * + * @inheritDoc + * @throws GraphQlInputException + */ + public function processHeaderValue(string $headerValue, HttpRequestInterface $request) : void + { + /** @var \Magento\Store\Model\Store $defaultStore */ + $defaultStore = $this->storeManager->getWebsite()->getDefaultStore(); + /** @var \Magento\Store\Model\Store $currentStore */ + $currentStore = $this->storeManager->getStore(); + + if (!empty($headerValue)) { + $headerCurrency = strtoupper(ltrim(rtrim($headerValue))); + if (in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes())) { + $currentStore->setCurrentCurrencyCode($headerCurrency); + } else { + throw new GraphQlInputException( + new \Magento\Framework\Phrase('Currency not allowed for store %1', [$currentStore->getStoreId()]) + ); + } + } else { + if ($this->session->getCurrencyCode()) { + $currentStore->setCurrentCurrencyCode($this->session->getCurrencyCode()); + } else { + $this->httpContext->setValue( + HttpContext::CONTEXT_CURRENCY, + $defaultStore->getCurrentCurrencyCode(), + $defaultStore->getDefaultCurrencyCode() + ); + } + } + } +} diff --git a/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml b/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml new file mode 100644 index 0000000000000..515ffef4892cb --- /dev/null +++ b/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\GraphQl\Controller\HttpRequestProcessor"> + <arguments> + <argument name="graphQlHeaders" xsi:type="array"> + <item name="Content-Currency" xsi:type="object">Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor\CurrencyProcessor</item> + </argument> + </arguments> + </type> +</config> diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index f374c29e24a52..27836a5d2a023 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -8,7 +8,7 @@ namespace Magento\GraphQl\Controller; use Magento\Framework\App\FrontControllerInterface; -use Magento\Framework\App\Request\Http; +use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\ResponseInterface; use Magento\Framework\Exception\LocalizedException; @@ -53,11 +53,6 @@ class GraphQl implements FrontControllerInterface */ private $resolverContext; - /** - * @var HttpRequestProcessor - */ - private $requestProcessor; - /** * @var QueryFields */ @@ -74,7 +69,6 @@ class GraphQl implements FrontControllerInterface * @param QueryProcessor $queryProcessor * @param \Magento\Framework\GraphQl\Exception\ExceptionFormatter $graphQlError * @param \Magento\Framework\GraphQl\Query\Resolver\ContextInterface $resolverContext - * @param HttpRequestProcessor $requestProcessor * @param QueryFields $queryFields * @param JsonFactory $jsonFactory */ @@ -84,7 +78,6 @@ public function __construct( QueryProcessor $queryProcessor, ExceptionFormatter $graphQlError, ContextInterface $resolverContext, - HttpRequestProcessor $requestProcessor, QueryFields $queryFields, JsonFactory $jsonFactory ) { @@ -93,7 +86,6 @@ public function __construct( $this->queryProcessor = $queryProcessor; $this->graphQlError = $graphQlError; $this->resolverContext = $resolverContext; - $this->requestProcessor = $requestProcessor; $this->queryFields = $queryFields; $this->jsonFactory = $jsonFactory; } @@ -105,12 +97,11 @@ public function __construct( * @param RequestInterface $request * @return ResponseInterface|ResultInterface */ - public function dispatch(RequestInterface $request) /* : ResponseInterface */ + public function dispatch(RequestInterface $request) { $jsonResult = $this->jsonFactory->create(); try { - /** @var Http $request */ - $this->requestProcessor->processHeaders($request); + /** @var HttpRequest $request */ if ($request->isPost()) { $data = $this->jsonSerializer->unserialize($request->getContent()); } else { diff --git a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/ContentTypeProcessor.php b/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/ContentTypeProcessor.php index 69201f93ab4ea..cff6cd3db6197 100644 --- a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/ContentTypeProcessor.php +++ b/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/ContentTypeProcessor.php @@ -24,9 +24,7 @@ class ContentTypeProcessor implements HttpHeaderProcessorInterface */ public function processHeaderValue(string $headerValue, HttpRequestInterface $request) : void { - if ($request->isPost() - && (!$headerValue || strpos($headerValue, 'application/json') === false) - ) { + if ((empty($headerValue) || strpos($headerValue, 'application/json') === false)) { throw new LocalizedException( new \Magento\Framework\Phrase('Request content type must be application/json') ); diff --git a/app/code/Magento/GraphQl/composer.json b/app/code/Magento/GraphQl/composer.json index 3e821b0909444..a81fb61984e0c 100644 --- a/app/code/Magento/GraphQl/composer.json +++ b/app/code/Magento/GraphQl/composer.json @@ -5,7 +5,6 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/module-authorization": "*", - "magento/module-store": "*", "magento/module-eav": "*", "magento/framework": "*" }, diff --git a/app/code/Magento/GraphQl/etc/graphql/di.xml b/app/code/Magento/GraphQl/etc/graphql/di.xml index f4e6ca59364b2..124a235f4fc25 100644 --- a/app/code/Magento/GraphQl/etc/graphql/di.xml +++ b/app/code/Magento/GraphQl/etc/graphql/di.xml @@ -29,7 +29,6 @@ <arguments> <argument name="graphQlHeaders" xsi:type="array"> <item name="Content-Type" xsi:type="object">Magento\GraphQl\Controller\HttpHeaderProcessor\ContentTypeProcessor</item> - <item name="Store" xsi:type="object">Magento\GraphQl\Controller\HttpHeaderProcessor\StoreProcessor</item> </argument> </arguments> </type> diff --git a/app/code/Magento/GraphQl/etc/module.xml b/app/code/Magento/GraphQl/etc/module.xml index 4d8b2090a8514..af0f5d06d3bae 100644 --- a/app/code/Magento/GraphQl/etc/module.xml +++ b/app/code/Magento/GraphQl/etc/module.xml @@ -9,7 +9,6 @@ <module name="Magento_GraphQl" > <sequence> <module name="Magento_Authorization"/> - <module name="Magento_Store"/> <module name="Magento_Eav"/> </sequence> </module> diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php index 151e044c32bef..ae501386aea5d 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -14,6 +14,7 @@ use Magento\Framework\Controller\ResultInterface; use Magento\GraphQlCache\Model\CacheTags; use Magento\PageCache\Model\Config; +use Magento\GraphQl\Controller\HttpRequestProcessor; /** * Class Plugin @@ -35,25 +36,50 @@ class Plugin */ private $response; + /** + * @var HttpRequestProcessor + */ + private $requestProcessor; + /** * @param CacheTags $cacheTags * @param Config $config * @param HttpResponse $response + * @param HttpRequestProcessor $requestProcessor */ public function __construct( CacheTags $cacheTags, Config $config, - HttpResponse $response + HttpResponse $response, + HttpRequestProcessor $requestProcessor ) { $this->cacheTags = $cacheTags; $this->config = $config; $this->response = $response; + $this->requestProcessor = $requestProcessor; + } + + /** + * Process graphql headers + * + * @param FrontControllerInterface $subject + * @param RequestInterface $request + * @return void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeDispatch( + FrontControllerInterface $subject, + RequestInterface $request + ) { + /** @var \Magento\Framework\App\Request\Http $request */ + $this->requestProcessor->processHeaders($request); } /** * Plugin for GraphQL after dispatch to set tag and cache headers * - * The $response doesn't have a set type because it's alternating between ResponseInterface and ResultInterface. + * The $response doesn't have a set type because it's alternating between ResponseInterface and ResultInterface + * depending if it comes from builtin cache or the dispatch. * * @param FrontControllerInterface $subject * @param ResponseInterface | ResultInterface $response diff --git a/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php b/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php index e279395e43d43..9b70f4305fc76 100644 --- a/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php +++ b/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php @@ -6,6 +6,8 @@ namespace Magento\GraphQlCache\Model\App; +use Magento\Framework\Serialize\Serializer\Json; + /** * Class CachePlugin * Should add unique identifier for graphql query @@ -13,37 +15,58 @@ class CacheIdentifierPlugin { /** - * Constructor - * - * @param \Magento\Framework\App\RequestInterface $request + * @var \Magento\Framework\App\Request\Http + */ + private $request; + + /** + * @var \Magento\Framework\App\Http\Context + */ + private $context; + + /** + * @var \Magento\Framework\Serialize\Serializer\Json + */ + private $serializer; + + /** + * @var \Magento\PageCache\Model\Config + */ + private $config; + + /** + * @param \Magento\Framework\App\Request\Http $request + * @param \Magento\Framework\App\Http\Context $context + * @param \Magento\Framework\Serialize\Serializer\Json $serializer * @param \Magento\PageCache\Model\Config $config */ public function __construct( - \Magento\Framework\App\RequestInterface $request, + \Magento\Framework\App\Request\Http $request, + \Magento\Framework\App\Http\Context $context, + \Magento\Framework\Serialize\Serializer\Json $serializer, \Magento\PageCache\Model\Config $config ) { $this->request = $request; + $this->context = $context; + $this->serializer = $serializer; $this->config = $config; } /** - * Adds a unique key identifier for graphql specific query and variables + * Adds a unique key identifier for graphql specific query and variables that skips X-Magento-Vary cookie * * @param \Magento\Framework\App\PageCache\Identifier $identifier * @param string $result * @return string * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function afterGetValue(\Magento\Framework\App\PageCache\Identifier $identifier, $result) + public function afterGetValue(\Magento\Framework\App\PageCache\Identifier $identifier, string $result) { - //If full page cache is enabled if ($this->config->isEnabled()) { - //we need to compute unique query identifier from the 3 variables and removing whitespaces $data = [ $this->request->isSecure(), $this->request->getUriString(), - $this->request->get(\Magento\Framework\App\Response\Http::COOKIE_VARY_STRING) - ?: $this->context->getVaryString() + $this->context->getVaryString() ]; $result = sha1($this->serializer->serialize($data)); } diff --git a/app/code/Magento/GraphQlCache/composer.json b/app/code/Magento/GraphQlCache/composer.json index 7b5e6137895f9..54e6573cb61c0 100644 --- a/app/code/Magento/GraphQlCache/composer.json +++ b/app/code/Magento/GraphQlCache/composer.json @@ -5,6 +5,7 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/module-graph-ql": "*" + "magento/module-page-cache": "*" }, "license": [ "OSL-3.0", diff --git a/app/code/Magento/GraphQlCache/etc/graphql/di.xml b/app/code/Magento/GraphQlCache/etc/graphql/di.xml index ae403e0c56bac..5c13dbb02e066 100644 --- a/app/code/Magento/GraphQlCache/etc/graphql/di.xml +++ b/app/code/Magento/GraphQlCache/etc/graphql/di.xml @@ -14,15 +14,12 @@ <type name="Magento\Framework\GraphQl\Query\ResolverInterface"> <plugin name="cache" type="Magento\GraphQlCache\Query\Resolver\Plugin"/> </type> - <!--<type name="Magento\Framework\App\PageCache\Identifier">--> - <!--<plugin name="core-app-area-design-exception-plugin"--> - <!--type="Magento\GraphQlCache\Model\App\CacheIdentifierPlugin" sortOrder="1"/>--> - <!--</type>--> + <type name="Magento\Framework\App\PageCache\Identifier"> + <plugin name="core-app-area-design-exception-plugin" + type="Magento\GraphQlCache\Model\App\CacheIdentifierPlugin" sortOrder="1"/> + </type> <type name="Magento\Framework\Controller\ResultInterface"> <plugin name="result-builtin-cache" type="Magento\PageCache\Model\Controller\Result\BuiltinPlugin"/> <plugin name="result-varnish-cache" type="Magento\PageCache\Model\Controller\Result\VarnishPlugin"/> </type> - <type name="Magento\Framework\App\Response\Http"> - <plugin name="response-http-page-cache" type="Magento\PageCache\Model\App\Response\HttpPlugin"/> - </type> </config> diff --git a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php similarity index 66% rename from app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php rename to app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php index 3571a7588d116..7036ac5f75942 100644 --- a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php +++ b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php @@ -5,13 +5,14 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\Controller\HttpHeaderProcessor; +namespace Magento\StoreGraphQl\Controller\HttpHeaderProcessor; use Magento\Framework\App\HttpRequestInterface; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\GraphQl\Controller\HttpHeaderProcessorInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\Framework\App\Http\Context as HttpContext; +use Magento\Store\Api\StoreCookieManagerInterface; /** * Process the "Store" header entry @@ -28,27 +29,36 @@ class StoreProcessor implements HttpHeaderProcessorInterface */ private $httpContext; + /** + * @var StoreCookieManagerInterface + */ + private $storeCookieManager; + /** * @param StoreManagerInterface $storeManager * @param HttpContext $httpContext */ public function __construct( StoreManagerInterface $storeManager, - HttpContext $httpContext + HttpContext $httpContext, + StoreCookieManagerInterface $storeCookieManager ) { $this->storeManager = $storeManager; $this->httpContext = $httpContext; + $this->storeCookieManager = $storeCookieManager; } /** * Handle the value of the store and set the scope * - * @inheritDoc + * @see \Magento\Store\App\Action\Plugin\Context::beforeDispatch + * + * @inheritdoc * @throws GraphQlInputException */ public function processHeaderValue(string $headerValue, HttpRequestInterface $request) : void { - if ($headerValue) { + if (!empty($headerValue)) { $storeCode = ltrim(rtrim($headerValue)); $stores = $this->storeManager->getStores(false, true); if (isset($stores[$storeCode])) { @@ -59,6 +69,11 @@ public function processHeaderValue(string $headerValue, HttpRequestInterface $re new \Magento\Framework\Phrase('Store code %1 does not exist', [$storeCode]) ); } + } elseif (!$this->isAlreadySet()) { + $storeCode = $this->storeCookieManager->getStoreCodeFromCookie() + ?: $this->storeManager->getDefaultStoreView()->getCode(); + $this->storeManager->setCurrentStore($storeCode); + $this->updateContext($storeCode); } } @@ -76,4 +91,16 @@ private function updateContext(string $storeCode) : void $this->storeManager->getDefaultStoreView()->getCode() ); } + + /** + * Check if there is a need to find the current store. + * + * @return bool + */ + private function isAlreadySet(): bool + { + $storeKey = StoreManagerInterface::CONTEXT_STORE; + + return $this->httpContext->getValue($storeKey) !== null; + } } diff --git a/app/code/Magento/StoreGraphQl/composer.json b/app/code/Magento/StoreGraphQl/composer.json index d53ba9fbb0023..aa36a4891343d 100644 --- a/app/code/Magento/StoreGraphQl/composer.json +++ b/app/code/Magento/StoreGraphQl/composer.json @@ -5,9 +5,7 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/framework": "*", - "magento/module-store": "*" - }, - "suggest": { + "magento/module-store": "*", "magento/module-graph-ql": "*" }, "license": [ diff --git a/app/code/Magento/StoreGraphQl/etc/graphql/di.xml b/app/code/Magento/StoreGraphQl/etc/graphql/di.xml new file mode 100644 index 0000000000000..973abc50a8aac --- /dev/null +++ b/app/code/Magento/StoreGraphQl/etc/graphql/di.xml @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\GraphQl\Controller\HttpRequestProcessor"> + <arguments> + <argument name="graphQlHeaders" xsi:type="array"> + <item name="Store" xsi:type="object">Magento\StoreGraphQl\Controller\HttpHeaderProcessor\StoreProcessor</item> + </argument> + </arguments> + </type> +</config> diff --git a/app/code/Magento/StoreGraphQl/etc/module.xml b/app/code/Magento/StoreGraphQl/etc/module.xml index f53379ac3bbf2..bbec6a85a1a13 100644 --- a/app/code/Magento/StoreGraphQl/etc/module.xml +++ b/app/code/Magento/StoreGraphQl/etc/module.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Magento_StoreGraphQl"> <sequence> + <module name="Magento_Store"/> <module name="Magento_GraphQl"/> </sequence> </module> From 0d94b0f51feddde21c683932f01c76c00c8ab2ef Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 4 Apr 2019 16:53:08 -0500 Subject: [PATCH 163/585] Issue-230: adding varnish - refactoring tags plugin and cache query class --- .../Controller/GraphQl/Plugin.php | 30 +++++++++++-------- .../{CacheInfo.php => CacheableQuery.php} | 22 ++++++++++---- .../GraphQlCache/Query/Resolver/Plugin.php | 20 ++++++------- 3 files changed, 43 insertions(+), 29 deletions(-) rename app/code/Magento/GraphQlCache/Model/{CacheInfo.php => CacheableQuery.php} (65%) diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php index d1b14f96ae449..b5e4155a33823 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -10,7 +10,7 @@ use Magento\Framework\App\FrontControllerInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\ResponseInterface; -use Magento\GraphQlCache\Model\CacheInfo; +use Magento\GraphQlCache\Model\CacheableQuery; use Magento\Framework\App\Response\Http as HttpResponse; use Magento\Framework\Controller\ResultInterface; use Magento\PageCache\Model\Config; @@ -22,7 +22,7 @@ class Plugin { /** - * @var CacheInfo + * @var CacheableQuery */ private $cacheInfo; @@ -42,13 +42,13 @@ class Plugin private $requestProcessor; /** - * @param CacheInfo $cacheInfo + * @param CacheableQuery $cacheInfo * @param Config $config * @param HttpResponse $response * @param HttpRequestProcessor $requestProcessor */ public function __construct( - CacheInfo $cacheInfo, + CacheableQuery $cacheInfo, Config $config, HttpResponse $response, HttpRequestProcessor $requestProcessor @@ -92,14 +92,20 @@ public function afterDispatch( $response, RequestInterface $request ) { - $cacheTags = $this->cacheInfo->getCacheTags(); - $isCacheValid = $this->cacheInfo->isCacheable(); - if (!empty($cacheTags) - && $isCacheValid - && $this->config->isEnabled() - ) { - $this->response->setPublicHeaders($this->config->getTtl()); - $this->response->setHeader('X-Magento-Tags', implode(',', $cacheTags), true); + $sendNoCacheHeaders = false; + if ($this->config->isEnabled() && $request->isGet()) { + if ($this->cacheInfo->shouldPopulateCacheHeadersWithTags()) { + $this->response->setPublicHeaders($this->config->getTtl()); + $this->response->setHeader('X-Magento-Tags', implode(',', $this->cacheInfo->getCacheTags()), true); + } else { + $sendNoCacheHeaders = true; + } + } else { + $sendNoCacheHeaders = true; + } + + if ($sendNoCacheHeaders) { + $this->response->setNoCacheHeaders(); } return $response; diff --git a/app/code/Magento/GraphQlCache/Model/CacheInfo.php b/app/code/Magento/GraphQlCache/Model/CacheableQuery.php similarity index 65% rename from app/code/Magento/GraphQlCache/Model/CacheInfo.php rename to app/code/Magento/GraphQlCache/Model/CacheableQuery.php index 57c46f6c2139d..3a7600b58f66d 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheInfo.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQuery.php @@ -7,12 +7,10 @@ namespace Magento\GraphQlCache\Model; -use Magento\Eav\Model\Attribute\Data\Boolean; - /** - * CacheInfo object is a registry for collecting cache related info and tags of all entities. + * CacheableQuery object is a registry for collecting cache related info and tags of all entities. */ -class CacheInfo +class CacheableQuery { /** * @var string[] @@ -46,7 +44,7 @@ public function addCacheTags(array $cacheTags): void } /** - * Returns if its valid to cache the response + * Return if its valid to cache the response * * @return bool */ @@ -56,7 +54,7 @@ public function isCacheable(): bool } /** - * Sets cache validity + * Set cache validity * * @param bool $cacheable */ @@ -64,4 +62,16 @@ public function setCacheValidity(bool $cacheable): void { $this->cacheable = $cacheable; } + + /** + * Check if query is cacheable and we have a list of tags to populate + * + * @return bool + */ + public function shouldPopulateCacheHeadersWithTags() : bool + { + $cacheTags = $this->getCacheTags(); + $isQueryCaheable = $this->isCacheable(); + return !empty($cacheTags) && $isQueryCaheable; + } } diff --git a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php b/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php index 2ff9c8a10b18f..029e29df3af23 100644 --- a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php +++ b/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php @@ -11,7 +11,7 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\GraphQl\Model\Query\Resolver\Context; -use Magento\GraphQlCache\Model\CacheInfo; +use Magento\GraphQlCache\Model\CacheableQuery; use Magento\Framework\App\RequestInterface; /** @@ -22,9 +22,9 @@ class Plugin { /** - * @var CacheInfo + * @var CacheableQuery */ - private $cacheInfo; + private $cacheableQuery; /** * @var Request @@ -32,14 +32,12 @@ class Plugin private $request; /** - * Constructor - * - * @param CacheInfo $cacheInfo + * @param CacheableQuery $cacheableQuery * @param RequestInterface $request */ - public function __construct(CacheInfo $cacheInfo, RequestInterface $request) + public function __construct(CacheableQuery $cacheableQuery, RequestInterface $request) { - $this->cacheInfo = $cacheInfo; + $this->cacheableQuery = $cacheableQuery; $this->request = $request; } @@ -74,7 +72,7 @@ public function afterResolve( foreach ($resolvedItemsIds as $itemId) { $cacheTags[] = $cacheTag . '_' . $itemId; } - $this->cacheInfo->addCacheTags($cacheTags); + $this->cacheableQuery->addCacheTags($cacheTags); } $this->setCacheValidity($cacheable); return $resolvedValue; @@ -117,7 +115,7 @@ private function extractResolvedItemsIds($resolvedValue) */ private function setCacheValidity(bool $isValid): void { - $cacheValidity = $this->cacheInfo->isCacheable() && $isValid; - $this->cacheInfo->setCacheValidity($cacheValidity); + $cacheValidity = $this->cacheableQuery->isCacheable() && $isValid; + $this->cacheableQuery->setCacheValidity($cacheValidity); } } From d75f99a54c927cbdbdd7ee31c72d9aca0eadc4d7 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 4 Apr 2019 17:28:55 -0500 Subject: [PATCH 164/585] Issue-230: adding varnish - removing header processor - adding dependency for store in graphql directory module --- app/code/Magento/DirectoryGraphQl/composer.json | 1 + app/code/Magento/GraphQl/Controller/GraphQl.php | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/DirectoryGraphQl/composer.json b/app/code/Magento/DirectoryGraphQl/composer.json index 0a81102a92767..ca1790c949d45 100644 --- a/app/code/Magento/DirectoryGraphQl/composer.json +++ b/app/code/Magento/DirectoryGraphQl/composer.json @@ -5,6 +5,7 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/module-directory": "*", + "magento/module-store": "*", "magento/framework": "*" }, "suggest": { diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index 6dfddf31c5e7b..4620e5369f9be 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -104,7 +104,6 @@ public function dispatch(RequestInterface $request) try { /** @var HttpRequest $request */ if ($this->isHttpVerbValid($request)) { - $this->requestProcessor->processHeaders($request); $data = $this->getDataFromRequest($request); $query = isset($data['query']) ? $data['query'] : ''; $variables = isset($data['variables']) ? $data['variables'] : null; From 559431eba2f6276543eb05a76676b9cfb29a930c Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 4 Apr 2019 18:34:15 -0500 Subject: [PATCH 165/585] Issue-230: adding varnish - adding currency validator --- .../HttpHeaderProcessor/CurrencyProcessor.php | 11 ++-- .../HttpHeaderProcessor/CurrencyValidator.php | 63 +++++++++++++++++++ .../DirectoryGraphQl/etc/graphql/di.xml | 3 + .../HttpHeaderProcessor/StoreProcessor.php | 12 +--- 4 files changed, 72 insertions(+), 17 deletions(-) create mode 100644 app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php index b6bae362175af..972cb0b37648e 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php @@ -7,11 +7,11 @@ namespace Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor; -use Magento\Framework\App\HttpRequestInterface; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\GraphQl\Controller\HttpHeaderProcessorInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\Framework\App\Http\Context as HttpContext; +use Magento\Framework\Session\SessionManagerInterface; /** * Process the "Currency" header entry @@ -29,18 +29,19 @@ class CurrencyProcessor implements HttpHeaderProcessorInterface private $httpContext; /** - * @var \Magento\Framework\Session\SessionManagerInterface + * @var SessionManagerInterface */ private $session; /** * @param StoreManagerInterface $storeManager * @param HttpContext $httpContext + * @param SessionManagerInterface $session */ public function __construct( StoreManagerInterface $storeManager, HttpContext $httpContext, - \Magento\Framework\Session\SessionManagerInterface $session + SessionManagerInterface $session ) { $this->storeManager = $storeManager; $this->httpContext = $httpContext; @@ -65,10 +66,6 @@ public function processHeaderValue(string $headerValue) : void $headerCurrency = strtoupper(ltrim(rtrim($headerValue))); if (in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes())) { $currentStore->setCurrentCurrencyCode($headerCurrency); - } else { - throw new GraphQlInputException( - new \Magento\Framework\Phrase('Currency not allowed for store %1', [$currentStore->getStoreId()]) - ); } } else { if ($this->session->getCurrencyCode()) { diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php new file mode 100644 index 0000000000000..6d28d712fdf9e --- /dev/null +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor; + +use Magento\Framework\App\HttpRequestInterface; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\GraphQl\Controller\HttpRequestValidatorInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\App\Http\Context as HttpContext; + +/** + * Validate the "Currency" header entry + */ +class CurrencyValidator implements HttpRequestValidatorInterface +{ + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var HttpContext + */ + private $httpContext; + + /** + * @param StoreManagerInterface $storeManager + * @param HttpContext $httpContext + */ + public function __construct( + StoreManagerInterface $storeManager, + HttpContext $httpContext + ) { + $this->storeManager = $storeManager; + $this->httpContext = $httpContext; + } + + /** + * Validate the header 'Content-Currency' value. + * + * @param HttpRequestInterface $request + * @return void + */ + public function validate(HttpRequestInterface $request): void + { + /** @var \Magento\Store\Model\Store $currentStore */ + $currentStore = $this->storeManager->getStore(); + $headerValue = $request->getHeader('Content-Currency'); + if (!empty($headerValue)) { + $headerCurrency = strtoupper(ltrim(rtrim($headerValue))); + if (!in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes())) { + throw new GraphQlInputException( + new \Magento\Framework\Phrase('Currency not allowed for store %1', [$currentStore->getStoreId()]) + ); + } + } + } +} diff --git a/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml b/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml index 515ffef4892cb..e9791654251ca 100644 --- a/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml @@ -11,6 +11,9 @@ <argument name="graphQlHeaders" xsi:type="array"> <item name="Content-Currency" xsi:type="object">Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor\CurrencyProcessor</item> </argument> + <argument name="requestValidators" xsi:type="array"> + <item name="currencyValidator" xsi:type="object">Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor\CurrencyValidator</item> + </argument> </arguments> </type> </config> diff --git a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php index 54ac3d4ae3bff..227665cbdd28f 100644 --- a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php +++ b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php @@ -7,7 +7,6 @@ namespace Magento\StoreGraphQl\Controller\HttpHeaderProcessor; -use Magento\Framework\App\HttpRequestInterface; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\GraphQl\Controller\HttpHeaderProcessorInterface; use Magento\Store\Model\StoreManagerInterface; @@ -62,15 +61,8 @@ public function processHeaderValue(string $headerValue) : void { if (!empty($headerValue)) { $storeCode = ltrim(rtrim($headerValue)); - $stores = $this->storeManager->getStores(false, true); - if (isset($stores[$storeCode])) { - $this->storeManager->setCurrentStore($storeCode); - $this->updateContext($storeCode); - } elseif (strtolower($storeCode) !== 'default') { - throw new GraphQlInputException( - new \Magento\Framework\Phrase('Store code %1 does not exist', [$storeCode]) - ); - } + $this->storeManager->setCurrentStore($storeCode); + $this->updateContext($storeCode); } elseif (!$this->isAlreadySet()) { $storeCode = $this->storeCookieManager->getStoreCodeFromCookie() ?: $this->storeManager->getDefaultStoreView()->getCode(); From 934ce24c54a5764d007a920ac47278e417e730f8 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 4 Apr 2019 19:17:16 -0500 Subject: [PATCH 166/585] Issue-230: adding varnish - fixing validators vs processors --- .../HttpHeaderProcessor/CurrencyProcessor.php | 38 +++++----- .../HttpHeaderProcessor/CurrencyValidator.php | 25 ++++--- .../HttpHeaderProcessor/StoreValidator.php | 73 +++++++++++++++++++ .../Magento/StoreGraphQl/etc/graphql/di.xml | 3 + 4 files changed, 113 insertions(+), 26 deletions(-) create mode 100644 app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php index 972cb0b37648e..8daa7750ddd36 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php @@ -57,26 +57,30 @@ public function __construct( */ public function processHeaderValue(string $headerValue) : void { - /** @var \Magento\Store\Model\Store $defaultStore */ - $defaultStore = $this->storeManager->getWebsite()->getDefaultStore(); - /** @var \Magento\Store\Model\Store $currentStore */ - $currentStore = $this->storeManager->getStore(); + try { + /** @var \Magento\Store\Model\Store $defaultStore */ + $defaultStore = $this->storeManager->getWebsite()->getDefaultStore(); + /** @var \Magento\Store\Model\Store $currentStore */ + $currentStore = $this->storeManager->getStore(); - if (!empty($headerValue)) { - $headerCurrency = strtoupper(ltrim(rtrim($headerValue))); - if (in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes())) { - $currentStore->setCurrentCurrencyCode($headerCurrency); - } - } else { - if ($this->session->getCurrencyCode()) { - $currentStore->setCurrentCurrencyCode($this->session->getCurrencyCode()); + if (!empty($headerValue)) { + $headerCurrency = strtoupper(ltrim(rtrim($headerValue))); + if (in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes())) { + $currentStore->setCurrentCurrencyCode($headerCurrency); + } } else { - $this->httpContext->setValue( - HttpContext::CONTEXT_CURRENCY, - $defaultStore->getCurrentCurrencyCode(), - $defaultStore->getDefaultCurrencyCode() - ); + if ($this->session->getCurrencyCode()) { + $currentStore->setCurrentCurrencyCode($this->session->getCurrencyCode()); + } else { + $this->httpContext->setValue( + HttpContext::CONTEXT_CURRENCY, + $defaultStore->getCurrentCurrencyCode(), + $defaultStore->getDefaultCurrencyCode() + ); + } } + } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + //skip store not found exception as it will be handled in graphql validation } } } diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php index 6d28d712fdf9e..9203523338ca7 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php @@ -48,16 +48,23 @@ public function __construct( */ public function validate(HttpRequestInterface $request): void { - /** @var \Magento\Store\Model\Store $currentStore */ - $currentStore = $this->storeManager->getStore(); - $headerValue = $request->getHeader('Content-Currency'); - if (!empty($headerValue)) { - $headerCurrency = strtoupper(ltrim(rtrim($headerValue))); - if (!in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes())) { - throw new GraphQlInputException( - new \Magento\Framework\Phrase('Currency not allowed for store %1', [$currentStore->getStoreId()]) - ); + try { + $headerValue = $request->getHeader('Content-Currency'); + if (!empty($headerValue)) { + $headerCurrency = strtoupper(ltrim(rtrim($headerValue))); + /** @var \Magento\Store\Model\Store $currentStore */ + $currentStore = $this->storeManager->getStore(); + if (!in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes())) { + throw new GraphQlInputException( + __('Currency not allowed for store %1', [$currentStore->getCode()]) + ); + } } + } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + $this->storeManager->setCurrentStore(null); + throw new GraphQlInputException( + __("The store that was requested wasn't found. Verify the store and try again.") + ); } } } diff --git a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php new file mode 100644 index 0000000000000..2572b4516f57c --- /dev/null +++ b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\StoreGraphQl\Controller\HttpHeaderProcessor; + +use Magento\Framework\App\HttpRequestInterface; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\GraphQl\Controller\HttpRequestValidatorInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\App\Http\Context as HttpContext; +use Magento\Store\Api\StoreCookieManagerInterface; + +/** + * Validate the "Store" header entry + */ +class StoreValidator implements HttpRequestValidatorInterface +{ + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var HttpContext + */ + private $httpContext; + + /** + * @var StoreCookieManagerInterface + */ + private $storeCookieManager; + + /** + * @param StoreManagerInterface $storeManager + * @param HttpContext $httpContext + */ + public function __construct( + StoreManagerInterface $storeManager, + HttpContext $httpContext, + StoreCookieManagerInterface $storeCookieManager + ) { + $this->storeManager = $storeManager; + $this->httpContext = $httpContext; + $this->storeCookieManager = $storeCookieManager; + } + + /** + * Validate the header 'Store' value. + * + * @param HttpRequestInterface $request + * @return void + */ + public function validate(HttpRequestInterface $request): void + { + $headerValue = $request->getHeader('Store'); + if (!empty($headerValue)) { + $storeCode = ltrim(rtrim($headerValue)); + $stores = $this->storeManager->getStores(false, true); + if (!isset($stores[$storeCode])) { + if (strtolower($storeCode) !== 'default') { + $this->storeManager->setCurrentStore(null); + throw new GraphQlInputException( + __("The store that was requested wasn't found. Verify the store and try again.") + ); + } + } + } + } +} diff --git a/app/code/Magento/StoreGraphQl/etc/graphql/di.xml b/app/code/Magento/StoreGraphQl/etc/graphql/di.xml index 973abc50a8aac..50f612194893f 100644 --- a/app/code/Magento/StoreGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/StoreGraphQl/etc/graphql/di.xml @@ -11,6 +11,9 @@ <argument name="graphQlHeaders" xsi:type="array"> <item name="Store" xsi:type="object">Magento\StoreGraphQl\Controller\HttpHeaderProcessor\StoreProcessor</item> </argument> + <argument name="requestValidators" xsi:type="array"> + <item name="storeValidator" xsi:type="object">Magento\StoreGraphQl\Controller\HttpHeaderProcessor\StoreValidator</item> + </argument> </arguments> </type> </config> From 630c36152191d50449ea3a59eb9490e938c466a9 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 4 Apr 2019 19:22:12 -0500 Subject: [PATCH 167/585] Issue-230: adding varnish - removing context --- .../HttpHeaderProcessor/CurrencyValidator.php | 11 +---------- .../HttpHeaderProcessor/StoreValidator.php | 19 +------------------ 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php index 9203523338ca7..1a2938c7d753a 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php @@ -11,7 +11,6 @@ use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\GraphQl\Controller\HttpRequestValidatorInterface; use Magento\Store\Model\StoreManagerInterface; -use Magento\Framework\App\Http\Context as HttpContext; /** * Validate the "Currency" header entry @@ -23,21 +22,13 @@ class CurrencyValidator implements HttpRequestValidatorInterface */ private $storeManager; - /** - * @var HttpContext - */ - private $httpContext; - /** * @param StoreManagerInterface $storeManager - * @param HttpContext $httpContext */ public function __construct( - StoreManagerInterface $storeManager, - HttpContext $httpContext + StoreManagerInterface $storeManager ) { $this->storeManager = $storeManager; - $this->httpContext = $httpContext; } /** diff --git a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php index 2572b4516f57c..b3b5f1a6abd49 100644 --- a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php +++ b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php @@ -11,8 +11,6 @@ use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\GraphQl\Controller\HttpRequestValidatorInterface; use Magento\Store\Model\StoreManagerInterface; -use Magento\Framework\App\Http\Context as HttpContext; -use Magento\Store\Api\StoreCookieManagerInterface; /** * Validate the "Store" header entry @@ -24,28 +22,13 @@ class StoreValidator implements HttpRequestValidatorInterface */ private $storeManager; - /** - * @var HttpContext - */ - private $httpContext; - - /** - * @var StoreCookieManagerInterface - */ - private $storeCookieManager; - /** * @param StoreManagerInterface $storeManager - * @param HttpContext $httpContext */ public function __construct( - StoreManagerInterface $storeManager, - HttpContext $httpContext, - StoreCookieManagerInterface $storeCookieManager + StoreManagerInterface $storeManager ) { $this->storeManager = $storeManager; - $this->httpContext = $httpContext; - $this->storeCookieManager = $storeCookieManager; } /** From 7cd48fc3b92c67d3d99257e3d302a931acd966a1 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Fri, 5 Apr 2019 10:30:36 +0530 Subject: [PATCH 168/585] Fixed Changing sample for downloadable product failure --- app/code/Magento/Downloadable/Model/SampleRepository.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Downloadable/Model/SampleRepository.php b/app/code/Magento/Downloadable/Model/SampleRepository.php index 0c7d2b96f1b53..98af48d1df993 100644 --- a/app/code/Magento/Downloadable/Model/SampleRepository.php +++ b/app/code/Magento/Downloadable/Model/SampleRepository.php @@ -308,8 +308,11 @@ protected function updateSample( $existingSample->setTitle($sample->getTitle()); } - if ($sample->getSampleType() === 'file' && $sample->getSampleFileContent() === null) { - $sample->setSampleFile($existingSample->getSampleFile()); + if ($sample->getSampleType() === 'file' + && $sample->getSampleFileContent() === null + && $sample->getSampleFile() !== null + ) { + $existingSample->setSampleFile($sample->getSampleFile()); } $this->saveSample($product, $sample, $isGlobalScopeContent); return $existingSample->getId(); From 865d7df16d374246d91d35f1bdb737828c88edc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= <bartlomiejszubert@gmail.com> Date: Thu, 4 Apr 2019 14:27:46 +0200 Subject: [PATCH 169/585] Fix #12802 - allow to override preference over \Magento\Quote\Api\Data\CartInterface and return correct object from QuoteRepository (+4 squashed commits) Squashed commits: [55b9f3ec52b] Fix #12802 - fix phpmd, mark quoteFactory as deprecated [56ca9a42468] Fix #12802 - change condition in quoteRepository [734212812a4] Fix #12802 - revert change of constructor parameters names [ba8ad543e0f] Fix #12802 - remove instanceof condition --- .../Magento/Quote/Model/QuoteRepository.php | 70 +++++++++------ .../Test/Unit/Model/QuoteRepositoryTest.php | 90 +++++++++++-------- 2 files changed, 93 insertions(+), 67 deletions(-) diff --git a/app/code/Magento/Quote/Model/QuoteRepository.php b/app/code/Magento/Quote/Model/QuoteRepository.php index 01c21bbbe50a7..fa6ab18136688 100644 --- a/app/code/Magento/Quote/Model/QuoteRepository.php +++ b/app/code/Magento/Quote/Model/QuoteRepository.php @@ -5,25 +5,28 @@ */ namespace Magento\Quote\Model; +use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; +use Magento\Framework\Api\Search\FilterGroup; +use Magento\Framework\Api\SearchCriteria\CollectionProcessor; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; +use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\App\ObjectManager; -use Magento\Framework\Api\SortOrder; +use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Api\Data\CartInterface; -use Magento\Quote\Model\Quote; -use Magento\Store\Model\StoreManagerInterface; -use Magento\Framework\Api\Search\FilterGroup; -use Magento\Quote\Model\ResourceModel\Quote\Collection as QuoteCollection; -use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; -use Magento\Framework\Exception\InputException; -use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; +use Magento\Quote\Api\Data\CartInterfaceFactory; +use Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory; use Magento\Quote\Model\QuoteRepository\SaveHandler; use Magento\Quote\Model\QuoteRepository\LoadHandler; +use Magento\Quote\Model\ResourceModel\Quote\Collection as QuoteCollection; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; +use Magento\Store\Model\StoreManagerInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class QuoteRepository implements \Magento\Quote\Api\CartRepositoryInterface +class QuoteRepository implements CartRepositoryInterface { /** * @var Quote[] @@ -37,6 +40,7 @@ class QuoteRepository implements \Magento\Quote\Api\CartRepositoryInterface /** * @var QuoteFactory + * @deprecated */ protected $quoteFactory; @@ -46,13 +50,13 @@ class QuoteRepository implements \Magento\Quote\Api\CartRepositoryInterface protected $storeManager; /** - * @var \Magento\Quote\Model\ResourceModel\Quote\Collection + * @var QuoteCollection * @deprecated 100.2.0 */ protected $quoteCollection; /** - * @var \Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory + * @var CartSearchResultsInterfaceFactory */ protected $searchResultsDataFactory; @@ -77,39 +81,47 @@ class QuoteRepository implements \Magento\Quote\Api\CartRepositoryInterface private $collectionProcessor; /** - * @var \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory + * @var QuoteCollectionFactory */ private $quoteCollectionFactory; + /** + * @var CartInterfaceFactory + */ + private $cartFactory; + /** * Constructor * * @param QuoteFactory $quoteFactory * @param StoreManagerInterface $storeManager - * @param \Magento\Quote\Model\ResourceModel\Quote\Collection $quoteCollection - * @param \Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory $searchResultsDataFactory + * @param QuoteCollection $quoteCollection + * @param CartSearchResultsInterfaceFactory $searchResultsDataFactory * @param JoinProcessorInterface $extensionAttributesJoinProcessor * @param CollectionProcessorInterface|null $collectionProcessor - * @param \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory|null $quoteCollectionFactory + * @param QuoteCollectionFactory|null $quoteCollectionFactory + * @param CartInterfaceFactory|null $cartFactory * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( QuoteFactory $quoteFactory, StoreManagerInterface $storeManager, - \Magento\Quote\Model\ResourceModel\Quote\Collection $quoteCollection, - \Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory $searchResultsDataFactory, + QuoteCollection $quoteCollection, + CartSearchResultsInterfaceFactory $searchResultsDataFactory, JoinProcessorInterface $extensionAttributesJoinProcessor, CollectionProcessorInterface $collectionProcessor = null, - \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory $quoteCollectionFactory = null + QuoteCollectionFactory $quoteCollectionFactory = null, + CartInterfaceFactory $cartFactory = null ) { $this->quoteFactory = $quoteFactory; $this->storeManager = $storeManager; $this->searchResultsDataFactory = $searchResultsDataFactory; $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; - $this->collectionProcessor = $collectionProcessor ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\Api\SearchCriteria\CollectionProcessor::class); - $this->quoteCollectionFactory = $quoteCollectionFactory ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Quote\Model\ResourceModel\Quote\CollectionFactory::class); + $this->collectionProcessor = $collectionProcessor ?: ObjectManager::getInstance() + ->get(CollectionProcessor::class); + $this->quoteCollectionFactory = $quoteCollectionFactory ?: ObjectManager::getInstance() + ->get(QuoteCollectionFactory::class); + $this->cartFactory = $cartFactory ?: ObjectManager::getInstance()->get(CartInterfaceFactory::class); } /** @@ -166,7 +178,7 @@ public function getActiveForCustomer($customerId, array $sharedStoreIds = []) /** * {@inheritdoc} */ - public function save(\Magento\Quote\Api\Data\CartInterface $quote) + public function save(CartInterface $quote) { if ($quote->getId()) { $currentQuote = $this->get($quote->getId(), [$quote->getStoreId()]); @@ -186,7 +198,7 @@ public function save(\Magento\Quote\Api\Data\CartInterface $quote) /** * {@inheritdoc} */ - public function delete(\Magento\Quote\Api\Data\CartInterface $quote) + public function delete(CartInterface $quote) { $quoteId = $quote->getId(); $customerId = $quote->getCustomerId(); @@ -203,13 +215,13 @@ public function delete(\Magento\Quote\Api\Data\CartInterface $quote) * @param int $identifier * @param int[] $sharedStoreIds * @throws NoSuchEntityException - * @return Quote + * @return CartInterface */ protected function loadQuote($loadMethod, $loadField, $identifier, array $sharedStoreIds = []) { - /** @var Quote $quote */ - $quote = $this->quoteFactory->create(); - if ($sharedStoreIds) { + /** @var CartInterface $quote */ + $quote = $this->cartFactory->create(); + if ($sharedStoreIds && method_exists($quote, 'setSharedStoreIds')) { $quote->setSharedStoreIds($sharedStoreIds); } $quote->setStoreId($this->storeManager->getStore()->getId())->$loadMethod($identifier); @@ -222,7 +234,7 @@ protected function loadQuote($loadMethod, $loadField, $identifier, array $shared /** * {@inheritdoc} */ - public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria) + public function getList(SearchCriteriaInterface $searchCriteria) { $this->quoteCollection = $this->quoteCollectionFactory->create(); /** @var \Magento\Quote\Api\Data\CartSearchResultsInterface $searchData */ diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteRepositoryTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteRepositoryTest.php index 3101c7d0677a9..095e1760df86f 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteRepositoryTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteRepositoryTest.php @@ -5,17 +5,31 @@ */ namespace Magento\Quote\Test\Unit\Model; +use Magento\Framework\Api\SearchCriteria; +use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; use Magento\Framework\Api\SortOrder; use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Api\Data\CartInterfaceFactory; +use Magento\Quote\Api\Data\CartSearchResultsInterface; +use Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\QuoteRepository; use Magento\Quote\Model\QuoteRepository\LoadHandler; use Magento\Quote\Model\QuoteRepository\SaveHandler; +use Magento\Quote\Model\ResourceModel\Quote\Collection; use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use PHPUnit\Framework\TestCase; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyMethods) */ -class QuoteRepositoryTest extends \PHPUnit\Framework\TestCase +class QuoteRepositoryTest extends TestCase { /** * @var \Magento\Quote\Api\CartRepositoryInterface @@ -23,32 +37,32 @@ class QuoteRepositoryTest extends \PHPUnit\Framework\TestCase private $model; /** - * @var \Magento\Quote\Model\QuoteFactory|\PHPUnit_Framework_MockObject_MockObject + * @var CartInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject */ - private $quoteFactoryMock; + private $cartFactoryMock; /** - * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ private $storeManagerMock; /** - * @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject + * @var Store|\PHPUnit_Framework_MockObject_MockObject */ private $storeMock; /** - * @var \Magento\Quote\Model\Quote|\PHPUnit_Framework_MockObject_MockObject + * @var Quote|\PHPUnit_Framework_MockObject_MockObject */ private $quoteMock; /** - * @var \Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject + * @var CartSearchResultsInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject */ private $searchResultsDataFactory; /** - * @var \Magento\Quote\Model\ResourceModel\Quote\Collection|\PHPUnit_Framework_MockObject_MockObject + * @var Collection|\PHPUnit_Framework_MockObject_MockObject */ private $quoteCollectionMock; @@ -78,21 +92,21 @@ class QuoteRepositoryTest extends \PHPUnit\Framework\TestCase private $objectManagerMock; /** - * @var \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + * @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject */ private $quoteCollectionFactoryMock; protected function setUp() { - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $objectManager = new ObjectManager($this); - $this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); + $this->objectManagerMock = $this->createMock(ObjectManagerInterface::class); \Magento\Framework\App\ObjectManager::setInstance($this->objectManagerMock); - $this->quoteFactoryMock = $this->createPartialMock(\Magento\Quote\Model\QuoteFactory::class, ['create']); - $this->storeManagerMock = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class); + $this->cartFactoryMock = $this->createPartialMock(CartInterfaceFactory::class, ['create']); + $this->storeManagerMock = $this->createMock(StoreManagerInterface::class); $this->quoteMock = $this->createPartialMock( - \Magento\Quote\Model\Quote::class, + Quote::class, [ 'load', 'loadByIdWithoutStore', @@ -108,35 +122,35 @@ protected function setUp() 'getData' ] ); - $this->storeMock = $this->createMock(\Magento\Store\Model\Store::class); + $this->storeMock = $this->createMock(Store::class); $this->searchResultsDataFactory = $this->createPartialMock( - \Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory::class, + CartSearchResultsInterfaceFactory::class, ['create'] ); $this->quoteCollectionMock = - $this->createMock(\Magento\Quote\Model\ResourceModel\Quote\Collection::class); + $this->createMock(Collection::class); $this->extensionAttributesJoinProcessorMock = $this->createMock( - \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface::class + JoinProcessorInterface::class ); $this->collectionProcessor = $this->createMock( - \Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface::class + CollectionProcessorInterface::class ); $this->quoteCollectionFactoryMock = $this->createPartialMock( - \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory::class, + CollectionFactory::class, ['create'] ); $this->model = $objectManager->getObject( - \Magento\Quote\Model\QuoteRepository::class, + QuoteRepository::class, [ - 'quoteFactory' => $this->quoteFactoryMock, 'storeManager' => $this->storeManagerMock, 'searchResultsDataFactory' => $this->searchResultsDataFactory, 'quoteCollection' => $this->quoteCollectionMock, 'extensionAttributesJoinProcessor' => $this->extensionAttributesJoinProcessorMock, 'collectionProcessor' => $this->collectionProcessor, - 'quoteCollectionFactory' => $this->quoteCollectionFactoryMock + 'quoteCollectionFactory' => $this->quoteCollectionFactoryMock, + 'cartFactory' => $this->cartFactoryMock ] ); @@ -161,7 +175,7 @@ public function testGetWithExceptionById() { $cartId = 14; - $this->quoteFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); + $this->cartFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($this->storeMock); $this->storeMock->expects($this->once())->method('getId')->willReturn(1); $this->quoteMock->expects($this->never())->method('setSharedStoreIds'); @@ -178,7 +192,7 @@ public function testGet() { $cartId = 15; - $this->quoteFactoryMock->expects(static::once()) + $this->cartFactoryMock->expects(static::once()) ->method('create') ->willReturn($this->quoteMock); $this->storeManagerMock->expects(static::once()) @@ -211,7 +225,7 @@ public function testGetForCustomerAfterGet() $cartId = 15; $customerId = 23; - $this->quoteFactoryMock->expects(static::exactly(2)) + $this->cartFactoryMock->expects(static::exactly(2)) ->method('create') ->willReturn($this->quoteMock); $this->storeManagerMock->expects(static::exactly(2)) @@ -249,7 +263,7 @@ public function testGetWithSharedStoreIds() $cartId = 16; $sharedStoreIds = [1, 2]; - $this->quoteFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); + $this->cartFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($this->storeMock); $this->storeMock->expects($this->once())->method('getId')->willReturn(1); $this->quoteMock->expects($this->once()) @@ -275,7 +289,7 @@ public function testGetForCustomer() $cartId = 17; $customerId = 23; - $this->quoteFactoryMock->expects(static::once()) + $this->cartFactoryMock->expects(static::once()) ->method('create') ->willReturn($this->quoteMock); $this->storeManagerMock->expects(static::once()) @@ -310,7 +324,7 @@ public function testGetActiveWithExceptionById() { $cartId = 14; - $this->quoteFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); + $this->cartFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($this->storeMock); $this->storeMock->expects($this->once())->method('getId')->willReturn(1); $this->quoteMock->expects($this->never())->method('setSharedStoreIds'); @@ -332,7 +346,7 @@ public function testGetActiveWithExceptionByIsActive() { $cartId = 15; - $this->quoteFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); + $this->cartFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($this->storeMock); $this->storeMock->expects($this->once())->method('getId')->willReturn(1); $this->quoteMock->expects($this->never())->method('setSharedStoreIds'); @@ -355,7 +369,7 @@ public function testGetActive() { $cartId = 15; - $this->quoteFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); + $this->cartFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($this->storeMock); $this->storeMock->expects($this->once())->method('getId')->willReturn(1); $this->quoteMock->expects($this->never())->method('setSharedStoreIds'); @@ -379,7 +393,7 @@ public function testGetActiveWithSharedStoreIds() $cartId = 16; $sharedStoreIds = [1, 2]; - $this->quoteFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); + $this->cartFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($this->storeMock); $this->storeMock->expects($this->once())->method('getId')->willReturn(1); $this->quoteMock->expects($this->once()) @@ -406,7 +420,7 @@ public function testGetActiveForCustomer() $cartId = 17; $customerId = 23; - $this->quoteFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); + $this->cartFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($this->storeMock); $this->storeMock->expects($this->once())->method('getId')->willReturn(1); $this->quoteMock->expects($this->never())->method('setSharedStoreIds'); @@ -430,14 +444,14 @@ public function testSave() { $cartId = 100; $quoteMock = $this->createPartialMock( - \Magento\Quote\Model\Quote::class, + Quote::class, ['getId', 'getCustomerId', 'getStoreId', 'hasData', 'setData'] ); $quoteMock->expects($this->exactly(3))->method('getId')->willReturn($cartId); $quoteMock->expects($this->once())->method('getCustomerId')->willReturn(2); $quoteMock->expects($this->once())->method('getStoreId')->willReturn(5); - $this->quoteFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); + $this->cartFactoryMock->expects($this->once())->method('create')->willReturn($this->quoteMock); $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($this->storeMock); $this->storeMock->expects($this->once())->method('getId')->willReturn(1); $this->quoteMock->expects($this->once())->method('getId')->willReturn($cartId); @@ -481,8 +495,8 @@ public function testGetList() ->method('load') ->with($cartMock); - $searchResult = $this->createMock(\Magento\Quote\Api\Data\CartSearchResultsInterface::class); - $searchCriteriaMock = $this->createMock(\Magento\Framework\Api\SearchCriteria::class); + $searchResult = $this->createMock(CartSearchResultsInterface::class); + $searchCriteriaMock = $this->createMock(SearchCriteria::class); $this->searchResultsDataFactory ->expects($this->once()) ->method('create') @@ -495,7 +509,7 @@ public function testGetList() $this->extensionAttributesJoinProcessorMock->expects($this->once()) ->method('process') ->with( - $this->isInstanceOf(\Magento\Quote\Model\ResourceModel\Quote\Collection::class) + $this->isInstanceOf(Collection::class) ); $this->quoteCollectionMock->expects($this->atLeastOnce())->method('getItems')->willReturn([$cartMock]); $searchResult->expects($this->once())->method('setTotalCount')->with($pageSize); From 2a343dd8e60d7cc9ba8fa037dd8dbd2f51ab6d46 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 5 Apr 2019 13:43:20 +0300 Subject: [PATCH 170/585] Fix static and integration tests. --- app/code/Magento/Sales/Model/Order/Payment.php | 1 + app/code/Magento/Sales/Model/RefundOrder.php | 1 + app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php | 1 + app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php | 1 + .../testsuite/Magento/Sales/Service/V1/RefundOrderTest.php | 1 + .../Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php | 5 +++-- .../Sales/_files/order_with_invoice_and_custom_status.php | 1 + .../_files/order_with_invoice_and_custom_status_rollback.php | 1 + 8 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php index dcf6d86b44cae..5d1d3f0d040a7 100644 --- a/app/code/Magento/Sales/Model/Order/Payment.php +++ b/app/code/Magento/Sales/Model/Order/Payment.php @@ -684,6 +684,7 @@ public function refund($creditmemo) $gateway->refund($this, $baseAmountToRefund); $creditmemo->setTransactionId($this->getLastTransId()); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Magento\Framework\Exception\LocalizedException $e) { if (!$captureTxn) { throw new \Magento\Framework\Exception\LocalizedException( diff --git a/app/code/Magento/Sales/Model/RefundOrder.php b/app/code/Magento/Sales/Model/RefundOrder.php index 97daab0615736..07555cba1b7f7 100644 --- a/app/code/Magento/Sales/Model/RefundOrder.php +++ b/app/code/Magento/Sales/Model/RefundOrder.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model; use Magento\Framework\App\ResourceConnection; diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php index 7798fdd2ce285..9d0f10a30e6ef 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order; use Magento\Framework\Model\Context; diff --git a/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php index 5962b11311e7d..1ffeaa053cc2e 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model; use Magento\Framework\App\ResourceConnection; diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php index 37fa36f707ad4..92942d7acc6f2 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Service\V1; use Magento\Sales\Model\Order; diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php index 0a85fe5fbd380..f589a0f5a1c74 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php @@ -10,15 +10,16 @@ use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Sales\Api\Data\OrderItemInterface; use Magento\Sales\Model\Order; -use Magento\TestFramework\TestCase\AbstractBackendController; use PHPUnit\Framework\Constraint\StringContains; /** * Provide tests for CreditMemo save controller. * + * @magentoDbIsolation enabled * @magentoAppArea adminhtml + * @magentoDataFixture Magento/Sales/_files/invoice.php */ -class SaveTest extends AbstractBackendController +class SaveTest extends AbstractCreditmemoControllerTest { /** * @var string diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php index 0ee9e95a56b49..46d3fb547cd09 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php @@ -8,6 +8,7 @@ use Magento\Sales\Model\Order\Status; use Magento\TestFramework\Helper\Bootstrap; +// phpcs:ignore Magento2.Security.IncludeFile require 'invoice.php'; $orderStatus = Bootstrap::getObjectManager()->create(Status::class); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php index af31c7b4f24a4..274cb3c74395d 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php @@ -8,6 +8,7 @@ use Magento\Sales\Model\Order\Status; use Magento\TestFramework\Helper\Bootstrap; +// phpcs:ignore Magento2.Security.IncludeFile require 'default_rollback.php'; /** @var Status $orderStatus */ From 63a497e04c95a9e18df75c0f7f846758d346555e Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Fri, 5 Apr 2019 14:52:16 +0300 Subject: [PATCH 171/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Fixed api-functional tests; --- .../testsuite/Magento/Ups/_files/enable_ups_shipping_method.php | 1 + .../Magento/Ups/_files/enable_ups_shipping_method_rollback.php | 1 + 2 files changed, 2 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php b/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php index 5c6c60866fafb..09e6c265a9d05 100644 --- a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php +++ b/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php @@ -15,6 +15,7 @@ $configWriter = $objectManager->get(WriterInterface::class); $configWriter->save('carriers/ups/active', 1); +$configWriter->save('carriers/ups/type', "UPS"); $scopeConfig = $objectManager->get(ScopeConfigInterface::class); $scopeConfig->clean(); diff --git a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php b/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php index 6d7894879f97b..e4226d2d1e457 100644 --- a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php @@ -14,3 +14,4 @@ $configWriter = $objectManager->create(WriterInterface::class); $configWriter->delete('carriers/ups/active'); +$configWriter->delete('carriers/ups/type'); From 48b0ab873183966d3f797df97d64cf7fccc1bd5d Mon Sep 17 00:00:00 2001 From: Yuriy <Vechirko.Yuriy@gmail.com> Date: Fri, 5 Apr 2019 16:20:10 +0300 Subject: [PATCH 172/585] #21737 Duplicating product with translated url keys over multiple storeviews causes non-unique url keys to be generated --- .../Magento/Catalog/Model/Product/Copier.php | 83 +++++++++++++++---- 1 file changed, 68 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Copier.php b/app/code/Magento/Catalog/Model/Product/Copier.php index 53fa11df04b35..2cd9304af7890 100644 --- a/app/code/Magento/Catalog/Model/Product/Copier.php +++ b/app/code/Magento/Catalog/Model/Product/Copier.php @@ -74,22 +74,9 @@ public function copy(Product $product) $duplicate->setUpdatedAt(null); $duplicate->setId(null); $duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID); - $this->copyConstructor->build($product, $duplicate); - $isDuplicateSaved = false; - do { - $urlKey = $duplicate->getUrlKey(); - $urlKey = preg_match('/(.*)-(\d+)$/', $urlKey, $matches) - ? $matches[1] . '-' . ($matches[2] + 1) - : $urlKey . '-1'; - $duplicate->setUrlKey($urlKey); - $duplicate->setData('url_path', null); - try { - $duplicate->save(); - $isDuplicateSaved = true; - } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { - } - } while (!$isDuplicateSaved); + $this->setDefaultUrl($product, $duplicate); + $this->setStoresUrl($product, $duplicate); $this->getOptionRepository()->duplicate($product, $duplicate); $product->getResource()->duplicate( $product->getData($metadata->getLinkField()), @@ -98,6 +85,72 @@ public function copy(Product $product) return $duplicate; } + /** + * Set default URL. + * + * @param Product $product + * @param Product $duplicate + * @return void + */ + private function setDefaultUrl(Product $product, Product $duplicate) : void + { + $duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID); + $resource = $product->getResource(); + $attribute = $resource->getAttribute('url_key'); + $productId = $product->getId(); + $urlKey = $resource->getAttributeRawValue($productId, 'url_key', \Magento\Store\Model\Store::DEFAULT_STORE_ID); + do { + $urlKey = $this->modifyUrl($urlKey); + $duplicate->setUrlKey($urlKey); + } while (!$attribute->getEntity()->checkAttributeUniqueValue($attribute, $duplicate)); + $duplicate->setData('url_path', null); + $duplicate->save(); + } + + /** + * Set URL for each store. + * + * @param Product $product + * @param Product $duplicate + * @return void + */ + private function setStoresUrl(Product $product, Product $duplicate) : void + { + $storeIds = $duplicate->getStoreIds(); + $resource = $product->getResource(); + $productId = $product->getId(); + $duplicate->setData('save_rewrites_history', false); + foreach ($storeIds as $storeId) { + $isDuplicateSaved = false; + $duplicate->setStoreId($storeId); + $urlKey = $resource->getAttributeRawValue($productId, 'url_key', $storeId); + do { + $urlKey = $this->modifyUrl($urlKey); + $duplicate->setUrlKey($urlKey); + $duplicate->setData('url_path', null); + try { + $duplicate->save(); + $isDuplicateSaved = true; + } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { + } + } while (!$isDuplicateSaved); + } + $duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID); + } + + /** + * Modify URL key. + * + * @param string $urlKey + * @return string + */ + private function modifyUrl(string $urlKey) : string + { + return preg_match('/(.*)-(\d+)$/', $urlKey, $matches) + ? $matches[1] . '-' . ($matches[2] + 1) + : $urlKey . '-1'; + } + /** * Returns product option repository. * From 3777ff79e68cd3583f41f393c76576825e274db9 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Fri, 5 Apr 2019 10:55:55 -0500 Subject: [PATCH 173/585] MC-14063: Apply catalog rule for configurable product with assigned simple products - Fixed selector that changed in mainline --- .../Test/Mftf/Section/StorefrontProductInfoMainSection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index d0cbcf5bc1654..0853d22eda7b9 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -15,7 +15,7 @@ <element name="productAttributeOptions1" type="select" selector="#product-options-wrapper div[tabindex='0'] option"/> <element name="productAttributeOptionsSelectButton" type="select" selector="#product-options-wrapper .super-attribute-select"/> <element name="productAttributeOptionsError" type="text" selector="//div[@class='mage-error']"/> - <element name="selectCustomOptionByName" type="radio" selector="//*[@class='options-list nested']//span[text()='{{value}}']/../../input" parameterized="true"/> + <element name="selectCustomOptionByName" type="radio" selector="//*[@class='options-list nested']//span[contains(text(), '{{value}}')]/../../input" parameterized="true"/> <!-- Parameter is the order number of the attribute on the page (1 is the newest) --> <element name="nthAttributeOnPage" type="block" selector="tr:nth-of-type({{numElement}}) .data" parameterized="true"/> <element name="stockIndication" type="block" selector=".stock" /> From 0733e7f995527ca95ea1dca26cbfb00aa2307d21 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Fri, 5 Apr 2019 11:31:52 -0500 Subject: [PATCH 174/585] Issue-230: adding varnish - fixing static errors --- .../HttpHeaderProcessor/CurrencyProcessor.php | 13 ++++++++++--- .../HttpHeaderProcessor/CurrencyValidator.php | 1 + app/code/Magento/GraphQl/Controller/GraphQl.php | 2 +- .../Controller/HttpRequestValidatorInterface.php | 3 ++- .../GraphQlCache/Controller/GraphQl/Plugin.php | 4 ++-- .../Model/App/CacheIdentifierPlugin.php | 7 ++----- .../HttpHeaderProcessor/StoreProcessor.php | 5 ++--- .../HttpHeaderProcessor/StoreValidator.php | 1 + .../GraphQlReader/Reader/InputObjectType.php | 5 +++-- .../GraphQlReader/Reader/ObjectType.php | 1 - 10 files changed, 24 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php index 8daa7750ddd36..383955772d1bd 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php @@ -7,11 +7,11 @@ namespace Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor; -use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\GraphQl\Controller\HttpHeaderProcessorInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\Framework\App\Http\Context as HttpContext; use Magento\Framework\Session\SessionManagerInterface; +use Psr\Log\LoggerInterface; /** * Process the "Currency" header entry @@ -33,6 +33,11 @@ class CurrencyProcessor implements HttpHeaderProcessorInterface */ private $session; + /** + * @var LoggerInterface + */ + private $logger; + /** * @param StoreManagerInterface $storeManager * @param HttpContext $httpContext @@ -41,11 +46,13 @@ class CurrencyProcessor implements HttpHeaderProcessorInterface public function __construct( StoreManagerInterface $storeManager, HttpContext $httpContext, - SessionManagerInterface $session + SessionManagerInterface $session, + LoggerInterface $logger ) { $this->storeManager = $storeManager; $this->httpContext = $httpContext; $this->session = $session; + $this->logger = $logger; } /** @@ -53,7 +60,6 @@ public function __construct( * * @param string $headerValue * @return void - * @throws GraphQlInputException */ public function processHeaderValue(string $headerValue) : void { @@ -81,6 +87,7 @@ public function processHeaderValue(string $headerValue) : void } } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { //skip store not found exception as it will be handled in graphql validation + $this->logger->warning($e->getMessage()); } } } diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php index 1a2938c7d753a..0d4a6708ba438 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php @@ -36,6 +36,7 @@ public function __construct( * * @param HttpRequestInterface $request * @return void + * @throws GraphQlInputException */ public function validate(HttpRequestInterface $request): void { diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index ab7fa3648d5d0..4fccec6c046ef 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -82,8 +82,8 @@ public function __construct( QueryProcessor $queryProcessor, ExceptionFormatter $graphQlError, ContextInterface $resolverContext, - QueryFields $queryFields, HttpRequestProcessor $requestProcessor, + QueryFields $queryFields, JsonFactory $jsonFactory ) { $this->schemaGenerator = $schemaGenerator; diff --git a/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php b/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php index c0873b0caff89..23e19195393f3 100644 --- a/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php +++ b/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php @@ -8,7 +8,7 @@ namespace Magento\GraphQl\Controller; use Magento\Framework\App\HttpRequestInterface; - +use Magento\Framework\GraphQl\Exception\GraphQlInputException; /** * Use this interface to implement a validator for a Graphql HTTP requests */ @@ -19,6 +19,7 @@ interface HttpRequestValidatorInterface * * @param HttpRequestInterface $request * @return void + * @throws GraphQlInputException */ public function validate(HttpRequestInterface $request) : void; } diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php index b5e4155a33823..8e849904a0adc 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php @@ -82,9 +82,9 @@ public function beforeDispatch( * depending if it comes from builtin cache or the dispatch. * * @param FrontControllerInterface $subject - * @param ResponseInterface | ResultInterface $response + * @param ResponseInterface|ResultInterface $response * @param RequestInterface $request - * @return ResponseInterface | ResultInterface + * @return ResponseInterface|ResultInterface * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function afterDispatch( diff --git a/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php b/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php index 9b70f4305fc76..a0fa5c1f9de99 100644 --- a/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php +++ b/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php @@ -6,11 +6,8 @@ namespace Magento\GraphQlCache\Model\App; -use Magento\Framework\Serialize\Serializer\Json; - /** - * Class CachePlugin - * Should add unique identifier for graphql query + * Handles unique identifier for graphql query */ class CacheIdentifierPlugin { @@ -53,7 +50,7 @@ public function __construct( } /** - * Adds a unique key identifier for graphql specific query and variables that skips X-Magento-Vary cookie + * Add/Override a unique key identifier for graphql specific query and variables that skips X-Magento-Vary cookie * * @param \Magento\Framework\App\PageCache\Identifier $identifier * @param string $result diff --git a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php index 227665cbdd28f..70d4730c2a63b 100644 --- a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php +++ b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php @@ -7,7 +7,6 @@ namespace Magento\StoreGraphQl\Controller\HttpHeaderProcessor; -use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\GraphQl\Controller\HttpHeaderProcessorInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\Framework\App\Http\Context as HttpContext; @@ -36,6 +35,7 @@ class StoreProcessor implements HttpHeaderProcessorInterface /** * @param StoreManagerInterface $storeManager * @param HttpContext $httpContext + * @param StoreCookieManagerInterface $storeCookieManager */ public function __construct( StoreManagerInterface $storeManager, @@ -54,7 +54,6 @@ public function __construct( * * @param string $headerValue * @return void - * @throws GraphQlInputException * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function processHeaderValue(string $headerValue) : void @@ -74,7 +73,7 @@ public function processHeaderValue(string $headerValue) : void /** * Update context accordingly to the store code found. * - * @param string $store + * @param string $storeCode * @return void */ private function updateContext(string $storeCode) : void diff --git a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php index b3b5f1a6abd49..437ff2c5dacc5 100644 --- a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php +++ b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php @@ -36,6 +36,7 @@ public function __construct( * * @param HttpRequestInterface $request * @return void + * @throws GraphQlInputException */ public function validate(HttpRequestInterface $request): void { diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php index e8c4f2721f65e..262ae33fb0a4c 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php @@ -12,7 +12,6 @@ use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\DocReader; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheTagReader; - /** * Composite configuration reader to handle the input object type meta */ @@ -50,7 +49,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array { @@ -80,6 +79,8 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array } /** + * Read the input's meta data + * * @param \GraphQL\Type\Definition\InputObjectField $fieldMeta * @return array */ diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php index 5d38d1444e4fd..97dc5a3d1f510 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php @@ -13,7 +13,6 @@ use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\ImplementsReader; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheTagReader; - /** * Composite configuration reader to handle the object type meta */ From 282f58469d822019a951eb920596d7a757f5db7e Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Fri, 5 Apr 2019 11:34:14 -0500 Subject: [PATCH 175/585] 230: Implement cache tag generation for GraphQL queries - Removed bad code from debugging --- .../Framework/GraphQl/Config/Element/FieldFactory.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php b/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php index 000fcc298708e..60191b69be47f 100644 --- a/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php +++ b/lib/internal/Magento/Framework/GraphQl/Config/Element/FieldFactory.php @@ -52,13 +52,6 @@ public function createFromConfigData( $fieldData['itemType'] = str_replace('[]', '', $fieldData['type']); } - if (isset($fieldData['description'])) { - if ($fieldData['description'] == "The list of products assigned to the category") { - $fieldType = $fieldData['type']; - } - } - - return $this->objectManager->create( Field::class, [ From 10274e3cb1cc2a68e126f164be256a25a2dc2b4e Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Fri, 5 Apr 2019 11:46:57 -0500 Subject: [PATCH 176/585] Issue-230: adding varnish - fixing static errors --- app/code/Magento/GraphQlCache/README.md | 4 ++++ app/code/Magento/GraphQlCache/composer.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/GraphQlCache/README.md diff --git a/app/code/Magento/GraphQlCache/README.md b/app/code/Magento/GraphQlCache/README.md new file mode 100644 index 0000000000000..98ccf26d038a8 --- /dev/null +++ b/app/code/Magento/GraphQlCache/README.md @@ -0,0 +1,4 @@ +# GraphQl Cache + +**GraphQl Cache** provides the caching ability for a graphql query. +This enabled Magento's builtin cache and varnish by leveraging FPC (Full page cache) that's used for front end. diff --git a/app/code/Magento/GraphQlCache/composer.json b/app/code/Magento/GraphQlCache/composer.json index 54e6573cb61c0..2633b4ea9b353 100644 --- a/app/code/Magento/GraphQlCache/composer.json +++ b/app/code/Magento/GraphQlCache/composer.json @@ -4,7 +4,7 @@ "type": "magento2-module", "require": { "php": "~7.1.3||~7.2.0", - "magento/module-graph-ql": "*" + "magento/module-graph-ql": "*", "magento/module-page-cache": "*" }, "license": [ From 59db1306b3f2ba08750909285278e66996721b5e Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Fri, 5 Apr 2019 16:41:41 -0500 Subject: [PATCH 177/585] 230: Implement cache tag generation for GraphQL queries - Fixed X-Magento-Tags not displaying in Developer mode --- .../Magento/Framework/App/PageCache/Kernel.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/App/PageCache/Kernel.php b/lib/internal/Magento/Framework/App/PageCache/Kernel.php index 13e18ed28fd67..2fb5b832e346e 100644 --- a/lib/internal/Magento/Framework/App/PageCache/Kernel.php +++ b/lib/internal/Magento/Framework/App/PageCache/Kernel.php @@ -5,6 +5,8 @@ */ namespace Magento\Framework\App\PageCache; +use Magento\Framework\App\State as AppState; + /** * Builtin cache processor */ @@ -52,6 +54,11 @@ class Kernel */ private $httpFactory; + /** + * @var AppState + */ + private $state; + /** * @param Cache $cache * @param Identifier $identifier @@ -60,6 +67,7 @@ class Kernel * @param \Magento\Framework\App\Http\ContextFactory|null $contextFactory * @param \Magento\Framework\App\Response\HttpFactory|null $httpFactory * @param \Magento\Framework\Serialize\SerializerInterface|null $serializer + * @param AppState $state */ public function __construct( \Magento\Framework\App\PageCache\Cache $cache, @@ -68,11 +76,13 @@ public function __construct( \Magento\Framework\App\Http\Context $context = null, \Magento\Framework\App\Http\ContextFactory $contextFactory = null, \Magento\Framework\App\Response\HttpFactory $httpFactory = null, - \Magento\Framework\Serialize\SerializerInterface $serializer = null + \Magento\Framework\Serialize\SerializerInterface $serializer = null, + AppState $state ) { $this->cache = $cache; $this->identifier = $identifier; $this->request = $request; + $this->state = $state; if ($context) { $this->context = $context; @@ -144,7 +154,9 @@ public function process(\Magento\Framework\App\Response\Http $response) $tags = $tagsHeader ? explode(',', $tagsHeader->getFieldValue()) : []; $response->clearHeader('Set-Cookie'); - $response->clearHeader('X-Magento-Tags'); + if ($this->state->getMode() != AppState::MODE_DEVELOPER) { + $response->clearHeader('X-Magento-Tags'); + } if (!headers_sent()) { header_remove('Set-Cookie'); } From 9675984b0487996de1521e2ba70d35ad7f77a788 Mon Sep 17 00:00:00 2001 From: WEXO team <support@wexo.dk> Date: Mon, 8 Apr 2019 10:40:30 +0600 Subject: [PATCH 178/585] fatalErrorHandler returns 500 only on fatal errors fatalogErrorHandler should return 500 only on fatal errors - otherwise, even a simple deprecation warning on the page triggers internal server error, which is invalid. --- pub/health_check.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pub/health_check.php b/pub/health_check.php index c9a4965876bb7..06c79baa2fd81 100644 --- a/pub/health_check.php +++ b/pub/health_check.php @@ -70,7 +70,7 @@ function fatalErrorHandler() { $error = error_get_last(); - if ($error !== null) { + if ($error !== null && $error['type'] === E_ERROR) { http_response_code(500); } } From 594badbb07888ed4156493a0c4354c71c3100365 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Mon, 8 Apr 2019 10:23:47 +0530 Subject: [PATCH 179/585] Fixed wrong url redirect when edit product review from product view page --- app/code/Magento/Review/Block/Adminhtml/Edit/Form.php | 3 ++- app/code/Magento/Review/Controller/Adminhtml/Product/Save.php | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php b/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php index 8a8395de72b62..8ca6d695113b9 100644 --- a/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php +++ b/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php @@ -84,7 +84,8 @@ protected function _prepareForm() 'review/*/save', [ 'id' => $this->getRequest()->getParam('id'), - 'ret' => $this->_coreRegistry->registry('ret') + 'ret' => $this->_coreRegistry->registry('ret'), + 'productId' => $this->getRequest()->getParam('productId') ] ), 'method' => 'post', diff --git a/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php index 6217729f53e50..9c85ae7db22d9 100644 --- a/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php +++ b/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php @@ -73,6 +73,10 @@ public function execute() } else { $resultRedirect->setPath('*/*/'); } + $productId = $this->getRequest()->getParam('productId'); + if ($productId) { + $resultRedirect->setPath("catalog/product/edit/id/$productId"); + } return $resultRedirect; } $resultRedirect->setPath('review/*/'); From 8256077236f6999df755b7fb71cb1ccbd53f2174 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Mon, 8 Apr 2019 10:58:12 +0530 Subject: [PATCH 180/585] Correct spelling --- .../adminhtml/Magento/backend/web/css/source/forms/_fields.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less index 5698afdaac7ae..66c9086c15aa7 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less @@ -81,7 +81,7 @@ min-width: 0; padding: 0; - // Filedset section + // Fieldset section .fieldset-wrapper { &.admin__fieldset-section { > .fieldset-wrapper-title { From 09b35a252f282283100a721ead25b9634e412f6e Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Mon, 8 Apr 2019 11:02:11 +0530 Subject: [PATCH 181/585] Correct spelling --- .../Magento/Catalog/Model/Product/Gallery/CreateHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php index 42b9639d2717b..d6416a024c6df 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php @@ -206,7 +206,7 @@ public function execute($product, $arguments = []) } /** - * Returns media gallery atribute instance + * Returns media gallery attribute instance * * @return \Magento\Catalog\Api\Data\ProductAttributeInterface * @since 101.0.0 From 4e6e1a15ccb773f2ce023e6a01ed6c46f6e30360 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Mon, 8 Apr 2019 09:40:21 +0300 Subject: [PATCH 182/585] MC-13339: Adding new options with images and prices to Configurable Product --- .../Cms/Test/Mftf/Data/CmsPageData.xml | 2 + .../AdminConfigurableProductActionGroup.xml | 10 ++ ...reateApiConfigurableProductActionGroup.xml | 2 +- .../StorefrontProductActionGroup.xml | 14 +- .../AdminProductFormConfigurationsSection.xml | 2 + ...agesAndPricesToConfigurableProductTest.xml | 124 ++++++++++++++++++ 6 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml diff --git a/app/code/Magento/Cms/Test/Mftf/Data/CmsPageData.xml b/app/code/Magento/Cms/Test/Mftf/Data/CmsPageData.xml index 2ec2eccba2344..2f8efac37cecf 100644 --- a/app/code/Magento/Cms/Test/Mftf/Data/CmsPageData.xml +++ b/app/code/Magento/Cms/Test/Mftf/Data/CmsPageData.xml @@ -50,6 +50,7 @@ <data key="file_type">Upload File</data> <data key="shareable">Yes</data> <data key="file">magento-again.jpg</data> + <data key="fileName">magento-again</data> <data key="value">magento-again.jpg</data> <data key="content">Image content. Yeah.</data> <data key="height">1000</data> @@ -71,6 +72,7 @@ <data key="file_type">Upload File</data> <data key="shareable">Yes</data> <data key="value">magento3.jpg</data> + <data key="file">magento3.jpg</data> <data key="fileName">magento3</data> <data key="extension">jpg</data> <data key="content">Image content. Yeah.</data> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml index 43dae2d70d416..069838231d775 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml @@ -276,4 +276,14 @@ <seeInField userInput="{{ApiConfigurableProduct.sku}}" selector="{{AdminProductFormSection.productSku}}" stepKey="seeSkuRequired"/> <dontSeeInField userInput="{{ApiConfigurableProduct.price}}" selector="{{AdminProductFormSection.productPrice}}" stepKey="dontSeePriceRequired"/> </actionGroup> + + <!--Click in Next Step and see Title--> + <actionGroup name="AdminConfigurableWizardMoveToNextStepActionGroup"> + <arguments> + <argument name="title" type="string"/> + </arguments> + <click selector="{{ConfigurableProductSection.nextButton}}" stepKey="clickNextButton"/> + <waitForPageLoad stepKey="waitForNextStepLoaded"/> + <see userInput="{{title}}" selector="{{AdminProductFormConfigurationsSection.stepsWizardTitle}}" stepKey="seeStepTitle"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml index c0a9f03906030..5feaab40a7695 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminCreateApiConfigurableProductActionGroup"> <arguments> - <argument name="productName" defaultValue="ApiConfigurableProductWithOutCategory" type="string"/> + <argument name="productName" defaultValue="{{ApiConfigurableProductWithOutCategory.name}}" type="string"/> </arguments> <!-- Create the configurable product based on the data in the /data folder --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontProductActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontProductActionGroup.xml index 51bb041b66089..d7f85dc9e08a2 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontProductActionGroup.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontProductActionGroup.xml @@ -66,6 +66,18 @@ <seeElement selector="{{StorefrontProductMediaSection.imageFile(image.filename)}}" stepKey="seeFirstImage"/> </actionGroup> + <!-- Assert option image and price in storefront product page --> + <actionGroup name="AssertOptionImageAndPriceInStorefrontProductActionGroup"> + <arguments> + <argument name="label" type="string"/> + <argument name="image" type="string"/> + <argument name="price" type="string"/> + </arguments> + <selectOption userInput="{{label}}" selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" stepKey="selectOption"/> + <seeElement selector="{{StorefrontProductMediaSection.imageFile(image)}}" stepKey="seeImage"/> + <see userInput="{{price}}" selector="{{StorefrontProductInfoMainSection.price}}" stepKey="seeProductPrice"/> + </actionGroup> + <!-- Assert configurable product with special price in storefront product page --> <actionGroup name="assertConfigurableProductWithSpecialPriceOnStorefrontProductPage"> <arguments> @@ -78,4 +90,4 @@ <see userInput="Regular Price" selector="{{StorefrontProductInfoMainSection.specialProductText}}" stepKey="seeText"/> <see userInput="{{price}}" selector="{{StorefrontProductInfoMainSection.oldProductPrice}}" stepKey="seeOldProductPrice"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml index d1b16cb8f5ce3..f6828a3b86312 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml @@ -36,6 +36,8 @@ <element name="variationsSkuInputByRow" selector="[data-index='configurable-matrix'] table > tbody > tr:nth-of-type({{row}}) input[name*='sku']" type="input" parameterized="true"/> <element name="variationsSkuInputErrorByRow" selector="[data-index='configurable-matrix'] table > tbody > tr:nth-of-type({{row}}) .admin__field-error" type="text" parameterized="true"/> <element name="variationLabel" type="text" selector="//div[@data-index='configurable-matrix']/label"/> + <element name="stepsWizardTitle" type="text" selector="div.content:not([style='display: none;']) .steps-wizard-title"/> + <element name="attributeEntityByName" type="text" selector="//div[@class='attribute-entity']//div[normalize-space(.)='{{attributeLabel}}']" parameterized="true"/> </section> <section name="AdminConfigurableProductFormSection"> <element name="productWeight" type="input" selector=".admin__control-text[name='product[weight]']"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml new file mode 100644 index 0000000000000..52443a17dfe64 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest"> + <annotations> + <features value="ConfigurableProduct"/> + <stories value="Update product"/> + <title value="Adding new options with images and prices to Configurable Product"/> + <description value="Test case verifies possibility to add new options for configurable attribute for existing configurable product."/> + <severity value="CRITICAL"/> + <testCaseId value="MC-13339"/> + <group value="configurableProduct"/> + </annotations> + + <before> + <actionGroup ref="AdminCreateApiConfigurableProductActionGroup" stepKey="createConfigurableProduct"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + + <after> + <deleteData createDataKey="createConfigProductCreateConfigurableProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigProductAttributeCreateConfigurableProduct" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createConfigChildProduct1CreateConfigurableProduct" stepKey="deleteConfigChildProduct1"/> + <deleteData createDataKey="createConfigChildProduct2CreateConfigurableProduct" stepKey="deleteConfigChildProduct2"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Open edit product page--> + <amOnPage url="{{AdminProductEditPage.url($$createConfigProductCreateConfigurableProduct.id$$)}}" stepKey="goToProductEditPage"/> + + <!--Open edit configuration wizard--> + <click selector="{{AdminProductFormConfigurationsSection.createConfigurations}}" stepKey="clickEditConfigurations"/> + <see userInput="Select Attributes" selector="{{AdminProductFormConfigurationsSection.stepsWizardTitle}}" stepKey="seeStepTitle"/> + + <!--Click Next button--> + <actionGroup ref="AdminConfigurableWizardMoveToNextStepActionGroup" stepKey="navigateToAttributeValuesStep"> + <argument name="title" value="Attribute Values"/> + </actionGroup> + <seeElement selector="{{AdminProductFormConfigurationsSection.attributeEntityByName($$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$)}}" stepKey="seeAttribute"/> + + <!--Create one color option via "Create New Value" link--> + <click selector="{{AdminCreateProductConfigurationsPanel.createNewValue}}" stepKey="clickOnCreateNewValue"/> + <fillField userInput="{{colorDefaultProductAttribute1.name}}" selector="{{AdminCreateProductConfigurationsPanel.attributeName}}" stepKey="fillFieldForNewAttribute"/> + <click selector="{{AdminCreateProductConfigurationsPanel.saveAttribute}}" stepKey="clickOnSaveNewAttribute"/> + + <!--Click Next button--> + <actionGroup ref="AdminConfigurableWizardMoveToNextStepActionGroup" stepKey="navigateToBulkStep"> + <argument name="title" value="Bulk Images, Price and Quantity"/> + </actionGroup> + + <!--Select Apply unique images by attribute to each SKU and color attribute in dropdown in Images--> + <click selector="{{AdminCreateProductConfigurationsPanel.applyUniqueImagesToEachSkus}}" stepKey="clickOnApplyUniqueImagesToEachSku"/> + <selectOption userInput="$$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$" + selector="{{AdminCreateProductConfigurationsPanel.selectImagesButton}}" stepKey="selectAttributeOption"/> + + <!-- Add images to configurable product attribute options --> + <actionGroup ref="addUniqueImageToConfigurableProductOption" stepKey="addImageToConfigurableProductOptionOne"> + <argument name="image" value="ImageUpload"/> + <argument name="frontend_label" value="$$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$"/> + <argument name="label" value="$$getConfigAttributeOption1CreateConfigurableProduct.label$$"/> + </actionGroup> + <actionGroup ref="addUniqueImageToConfigurableProductOption" stepKey="addImageToConfigurableProductOptionTwo"> + <argument name="image" value="ImageUpload_1"/> + <argument name="frontend_label" value="$$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$"/> + <argument name="label" value="$$getConfigAttributeOption2CreateConfigurableProduct.label$$"/> + </actionGroup> + <actionGroup ref="addUniqueImageToConfigurableProductOption" stepKey="addImageToConfigurableProductOptionThree"> + <argument name="image" value="ImageUpload3"/> + <argument name="frontend_label" value="$$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$"/> + <argument name="label" value="{{colorDefaultProductAttribute1.name}}"/> + </actionGroup> + + <!--Add prices to configurable product attribute options--> + <click selector="{{AdminCreateProductConfigurationsPanel.applyUniquePricesToEachSkus}}" stepKey="clickOnApplyUniquePricesByAttributeToEachSku"/> + <selectOption userInput="$$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$" + selector="{{AdminCreateProductConfigurationsPanel.selectAttribute}}" stepKey="selectAttributes"/> + <fillField userInput="10" selector="{{AdminCreateProductConfigurationsPanel.price($$getConfigAttributeOption1CreateConfigurableProduct.label$$)}}" stepKey="fillAttributePrice"/> + <fillField userInput="20" selector="{{AdminCreateProductConfigurationsPanel.price($$getConfigAttributeOption2CreateConfigurableProduct.label$$)}}" stepKey="fillAttributePrice1"/> + <fillField userInput="30" selector="{{AdminCreateProductConfigurationsPanel.price(colorDefaultProductAttribute1.name)}}" stepKey="fillAttributePrice2"/> + + <!-- Add quantity to product attribute options --> + <click selector="{{AdminCreateProductConfigurationsPanel.applySingleQuantityToEachSkus}}" stepKey="clickOnApplySingleQuantityToEachSku"/> + <fillField selector="{{AdminCreateProductConfigurationsPanel.quantity}}" userInput="100" stepKey="enterAttributeQuantity"/> + + <!--Click Next button--> + <actionGroup ref="AdminConfigurableWizardMoveToNextStepActionGroup" stepKey="navigateToSummaryStep"> + <argument name="title" value="Summary"/> + </actionGroup> + + <!--Click Generate Configure button--> + <click selector="{{ConfigurableProductSection.generateConfigure}}" stepKey="clickGenerateConfigure"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!--Go to frontend and check image and price--> + <amOnPage url="{{StorefrontProductPage.url($$createConfigProductCreateConfigurableProduct.custom_attributes[url_key]$$)}}" stepKey="goToProductPage"/> + + <actionGroup ref="AssertOptionImageAndPriceInStorefrontProductActionGroup" stepKey="assertFirstOptionImageAndPriceInStorefrontProductPage"> + <argument name="label" value="$$getConfigAttributeOption1CreateConfigurableProduct.label$$"/> + <argument name="image" value="{{ImageUpload.filename}}"/> + <argument name="price" value="10"/> + </actionGroup> + + <actionGroup ref="AssertOptionImageAndPriceInStorefrontProductActionGroup" stepKey="assertSecondOptionImageAndPriceInStorefrontProductPage"> + <argument name="label" value="$$getConfigAttributeOption2CreateConfigurableProduct.label$$"/> + <argument name="image" value="{{ImageUpload_1.filename}}"/> + <argument name="price" value="20"/> + </actionGroup> + + <actionGroup ref="AssertOptionImageAndPriceInStorefrontProductActionGroup" stepKey="assertThirdOptionImageAndPriceInStorefrontProductPage"> + <argument name="label" value="{{colorDefaultProductAttribute1.name}}"/> + <argument name="image" value="{{ImageUpload3.filename}}"/> + <argument name="price" value="30"/> + </actionGroup> + </test> +</tests> From 2f23922752aa0d1d713a5f285a52b4cf5fe46202 Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Mon, 8 Apr 2019 17:19:46 +0300 Subject: [PATCH 183/585] MAGETWO-98584: Google chart API used by Magento dashboard scheduled to be turned off --- .../Magento/Backend/Controller/Adminhtml/DashboardTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php index 89f1e5e5d53d6..07af21505f180 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php @@ -21,8 +21,6 @@ public function testAjaxBlockAction() public function testTunnelAction() { - $this->markTestSkipped('MAGETWO-98800: TunnelAction fails when Google Chart API is not available'); - $testUrl = \Magento\Backend\Block\Dashboard\Graph::API_URL . '?cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World'; $handle = curl_init(); curl_setopt($handle, CURLOPT_URL, $testUrl); From dfea9bfffde7480f855ce38ebfbc696eb686109a Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 8 Apr 2019 10:12:28 -0500 Subject: [PATCH 184/585] Issue-230: adding varnish - fixing composer --- app/code/Magento/DirectoryGraphQl/composer.json | 4 +--- app/code/Magento/GraphQlCache/composer.json | 5 +++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/DirectoryGraphQl/composer.json b/app/code/Magento/DirectoryGraphQl/composer.json index ca1790c949d45..d3c783e6c7bfe 100644 --- a/app/code/Magento/DirectoryGraphQl/composer.json +++ b/app/code/Magento/DirectoryGraphQl/composer.json @@ -6,11 +6,9 @@ "php": "~7.1.3||~7.2.0", "magento/module-directory": "*", "magento/module-store": "*", + "magento/module-graph-ql": "*", "magento/framework": "*" }, - "suggest": { - "magento/module-graph-ql": "*" - }, "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GraphQlCache/composer.json b/app/code/Magento/GraphQlCache/composer.json index 2633b4ea9b353..436ae95da40f5 100644 --- a/app/code/Magento/GraphQlCache/composer.json +++ b/app/code/Magento/GraphQlCache/composer.json @@ -4,8 +4,9 @@ "type": "magento2-module", "require": { "php": "~7.1.3||~7.2.0", - "magento/module-graph-ql": "*", - "magento/module-page-cache": "*" + "magento/framework": "*", + "magento/module-page-cache": "*", + "magento/module-graph-ql": "*" }, "license": [ "OSL-3.0", From 5746022728fb62959cfa4d956765ec0e56850e27 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Mon, 8 Apr 2019 10:15:42 -0500 Subject: [PATCH 185/585] MC-4439: Convert UpdateSearchTermEntityTest to MFTF --- .../AdminCatalogSearchTermNewSection.xml | 6 +- .../StorefrontUpdateSearchTermEntityTest.xml | 72 +++++++++++++++++++ .../AdminEditSearchTermActionGroup.xml | 24 +++++++ .../Search/Test/Mftf/Data/SearchTermData.xml | 8 +++ .../TestCase/UpdateSearchTermEntityTest.xml | 1 + 5 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontUpdateSearchTermEntityTest.xml create mode 100644 app/code/Magento/Search/Test/Mftf/ActionGroup/AdminEditSearchTermActionGroup.xml diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Section/AdminCatalogSearchTermNewSection.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Section/AdminCatalogSearchTermNewSection.xml index a7d577a7508c0..a07e2a9b8a547 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Section/AdminCatalogSearchTermNewSection.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Section/AdminCatalogSearchTermNewSection.xml @@ -9,8 +9,10 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminCatalogSearchTermNewSection"> - <element name="searchQuery" type="text" selector="//div[@class='admin__field-control control']/input[@id='query_text']"/> - <element name="store" type="text" selector="//select[@id='store_id']"/> + <element name="searchQuery" type="text" selector="#query_text"/> + <element name="store" type="text" selector="#store_id"/> + <element name="numberOfResults" type="button" selector="#num_results"/> + <element name="numberOfUses" type="button" selector="#popularity"/> <element name="redirectUrl" type="text" selector="//div[@class='admin__field-control control']/input[@id='redirect']"/> <element name="displayInSuggestedTerm" type="select" selector="//select[@name='display_in_terms']"/> <element name="saveSearchButton" type="button" selector="//button[@id='save']/span[@class='ui-button-text']" timeout="30"/> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontUpdateSearchTermEntityTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontUpdateSearchTermEntityTest.xml new file mode 100644 index 0000000000000..3ebb09f3c9c26 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontUpdateSearchTermEntityTest.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontUpdateSearchTermEntityTest"> + <annotations> + <stories value="Storefront Search"/> + <title value="Update Storefront Search Results"/> + <description value="You should see the updated Search Term on the Storefront via the Admin."/> + <testCaseId value="MC-13987"/> + <severity value="CRITICAL"/> + <group value="search"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createCategory1"/> + <createData entity="SimpleProduct" stepKey="createProduct1"> + <requiredEntity createDataKey="createCategory1"/> + </createData> + + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage1"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logoutOfAdmin1"/> + + <deleteData createDataKey="createProduct1" stepKey="deleteSimpleProduct1"/> + <deleteData createDataKey="createCategory1" stepKey="deleteCategory1"/> + </after> + + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName1"> + <argument name="phrase" value="$$createProduct1.name$$"/> + </actionGroup> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> + + <amOnPage url="{{AdminCatalogSearchTermIndexPage.url}}" stepKey="openAdminCatalogSearchTermIndexPage1"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + + <actionGroup ref="searchTermFilterBySearchQuery" stepKey="filterByFirstSearchQuery1"> + <argument name="searchQuery" value="$$createProduct1.name$$"/> + </actionGroup> + + <click selector="{{AdminGridRow.editByValue($$createProduct1.name$$)}}" stepKey="clickOnSearchResult1"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + + <actionGroup ref="AdminFillAllSearchTermFieldsActionGroup" stepKey="searchForSearchTerm1"> + <argument name="searchTerm" value="UpdatedSearchTermData1"/> + </actionGroup> + + <amOnPage url="{{AdminCatalogSearchTermIndexPage.url}}" stepKey="openAdminCatalogSearchTermIndexPage2"/> + <waitForPageLoad stepKey="waitForPageLoad3"/> + + <actionGroup ref="searchTermFilterBySearchQuery" stepKey="filterByFirstSearchQuery2"> + <argument name="searchQuery" value="{{UpdatedSearchTermData1.query_text}}"/> + </actionGroup> + + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage2"/> + <waitForPageLoad stepKey="waitForPageLoad4"/> + + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName2"> + <argument name="phrase" value="{{UpdatedSearchTermData1.query_text}}"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Search/Test/Mftf/ActionGroup/AdminEditSearchTermActionGroup.xml b/app/code/Magento/Search/Test/Mftf/ActionGroup/AdminEditSearchTermActionGroup.xml new file mode 100644 index 0000000000000..de330bb24a2e6 --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/ActionGroup/AdminEditSearchTermActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminFillAllSearchTermFieldsActionGroup"> + <arguments> + <argument name="searchTerm" type="entity"/> + </arguments> + + <fillField selector="{{AdminCatalogSearchTermNewSection.searchQuery}}" userInput="{{searchTerm.query_text}}" stepKey="fillSearchQuery1"/> + <selectOption selector="{{AdminCatalogSearchTermNewSection.store}}" userInput="{{searchTerm.store_id}}" stepKey="selectStore1"/> + <fillField selector="{{AdminCatalogSearchTermNewSection.numberOfResults}}" userInput="{{searchTerm.number_of_results}}" stepKey="fillNumberOfResults1"/> + <fillField selector="{{AdminCatalogSearchTermNewSection.numberOfUses}}" userInput="{{searchTerm.number_of_uses}}" stepKey="fillNumberOfUses1"/> + <selectOption selector="{{AdminCatalogSearchTermNewSection.displayInSuggestedTerm}}" userInput="{{searchTerm.display_in_suggested_term}}" stepKey="selectDisplayInSuggestedTerms1"/> + + <click selector="{{AdminConfigSection.saveButton}}" stepKey="clickOnSaveButton1"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Search/Test/Mftf/Data/SearchTermData.xml b/app/code/Magento/Search/Test/Mftf/Data/SearchTermData.xml index 1518adad01347..8263ff996318e 100644 --- a/app/code/Magento/Search/Test/Mftf/Data/SearchTermData.xml +++ b/app/code/Magento/Search/Test/Mftf/Data/SearchTermData.xml @@ -14,4 +14,12 @@ <data key="redirect" unique="suffix">http://example.com/</data> <data key="display_in_terms">0</data> </entity> + <entity name="UpdatedSearchTermData1" type="searchTerm"> + <data key="query_text" unique="suffix">UpdatedSearchTerm</data> + <data key="store_id">Default Store View</data> + <data key="number_of_results">1</data> + <data key="number_of_uses">20</data> + <data key="redirect_url">http://example.com</data> + <data key="display_in_suggested_term">No</data> + </entity> </entities> diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/UpdateSearchTermEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/UpdateSearchTermEntityTest.xml index 922973dbf316a..2ce4bbaa8a6d2 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/UpdateSearchTermEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/UpdateSearchTermEntityTest.xml @@ -14,6 +14,7 @@ <data name="searchTerm/data/popularity" xsi:type="string">20</data> <data name="searchTerm/data/redirect" xsi:type="string">http://example.com/</data> <data name="searchTerm/data/display_in_terms" xsi:type="string">No</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertSearchTermSuccessSaveMessage" /> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertSearchTermForm" /> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertSearchTermInGrid" /> From 02a65d02b25acb73e243cac8abf03cc55cb68335 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Mon, 8 Apr 2019 10:27:17 -0500 Subject: [PATCH 186/585] MAGETWO-93628: Shopping cart is emptied after reset password procedure --- app/code/Magento/Customer/Model/AccountManagement.php | 5 +---- .../Customer/Test/Unit/Model/AccountManagementTest.php | 9 +++------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index d86286bc2fcb9..0440eb161e9e0 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -1066,10 +1066,7 @@ public function validate(CustomerInterface $customer) $result = $this->getEavValidator()->isValid($customerModel); if ($result === false && is_array($this->getEavValidator()->getMessages())) { return $validationResults->setIsValid(false)->setMessages( - call_user_func_array( - 'array_merge', - $this->getEavValidator()->getMessages() - ) + array_merge(...$this->getEavValidator()->getMessages()) ); } return $validationResults->setIsValid(true)->setMessages([]); diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index aa901e8a2e978..24a96a929a067 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1238,8 +1238,7 @@ public function testInitiatePasswordResetEmailReminder() $storeId = 1; - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); + $hash = hash('sha256', microtime() . random_int(PHP_INT_MIN, PHP_INT_MAX)); $this->emailNotificationMock->expects($this->once()) ->method('passwordReminder') @@ -1263,8 +1262,7 @@ public function testInitiatePasswordResetEmailReset() $templateIdentifier = 'Template Identifier'; $sender = 'Sender'; - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); + $hash = hash('sha256', microtime() . random_int(PHP_INT_MIN, PHP_INT_MAX)); $this->emailNotificationMock->expects($this->once()) ->method('passwordResetConfirmation') @@ -1288,8 +1286,7 @@ public function testInitiatePasswordResetNoTemplate() $templateIdentifier = 'Template Identifier'; $sender = 'Sender'; - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); + $hash = hash('sha256', microtime() . random_int(PHP_INT_MIN, PHP_INT_MAX)); $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash); From fda9e3e5392a781f3fc2cc1e4a1f43ac57d7a174 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 8 Apr 2019 11:49:04 -0500 Subject: [PATCH 187/585] Issue-230: adding varnish - fixing static --- .../CurrencyValidator.php | 2 +- .../Magento/DirectoryGraphQl/etc/graphql/di.xml | 2 +- .../App/PageCache/Identifier.php} | 7 ++++--- .../Plugin/Query/Resolver.php} | 13 ++++++------- app/code/Magento/GraphQlCache/README.md | 4 ++-- app/code/Magento/GraphQlCache/etc/graphql/di.xml | 4 ++-- .../HttpHeaderProcessor/StoreProcessor.php | 1 - .../StoreValidator.php | 2 +- app/code/Magento/StoreGraphQl/etc/graphql/di.xml | 2 +- .../Magento/Framework/App/PageCache/Kernel.php | 13 ++++++++++--- .../Framework/GraphQl/Config/Element/Field.php | 6 +++--- .../GraphQlReader/MetaReader/FieldMetaReader.php | 15 ++++++++++----- .../GraphQlReader/Reader/InputObjectType.php | 13 +++++++++---- .../GraphQlReader/Reader/InterfaceType.php | 13 +++++++++---- .../GraphQlReader/Reader/ObjectType.php | 12 +++++++++--- 15 files changed, 68 insertions(+), 41 deletions(-) rename app/code/Magento/DirectoryGraphQl/Controller/{HttpHeaderProcessor => HttpRequestValidator}/CurrencyValidator.php (96%) rename app/code/Magento/GraphQlCache/Model/{App/CacheIdentifierPlugin.php => Plugin/App/PageCache/Identifier.php} (92%) rename app/code/Magento/GraphQlCache/{Query/Resolver/Plugin.php => Model/Plugin/Query/Resolver.php} (90%) rename app/code/Magento/StoreGraphQl/Controller/{HttpHeaderProcessor => HttpRequestValidator}/StoreValidator.php (96%) diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php similarity index 96% rename from app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php rename to app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php index 0d4a6708ba438..7ecff5d1f3f66 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyValidator.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor; +namespace Magento\DirectoryGraphQl\Controller\HttpRequestValidator; use Magento\Framework\App\HttpRequestInterface; use Magento\Framework\GraphQl\Exception\GraphQlInputException; diff --git a/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml b/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml index e9791654251ca..63f501551f535 100644 --- a/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/DirectoryGraphQl/etc/graphql/di.xml @@ -12,7 +12,7 @@ <item name="Content-Currency" xsi:type="object">Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor\CurrencyProcessor</item> </argument> <argument name="requestValidators" xsi:type="array"> - <item name="currencyValidator" xsi:type="object">Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor\CurrencyValidator</item> + <item name="currencyValidator" xsi:type="object">Magento\DirectoryGraphQl\Controller\HttpRequestValidator\CurrencyValidator</item> </argument> </arguments> </type> diff --git a/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php b/app/code/Magento/GraphQlCache/Model/Plugin/App/PageCache/Identifier.php similarity index 92% rename from app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php rename to app/code/Magento/GraphQlCache/Model/Plugin/App/PageCache/Identifier.php index a0fa5c1f9de99..e02a51d2c1ca1 100644 --- a/app/code/Magento/GraphQlCache/Model/App/CacheIdentifierPlugin.php +++ b/app/code/Magento/GraphQlCache/Model/Plugin/App/PageCache/Identifier.php @@ -3,13 +3,14 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); -namespace Magento\GraphQlCache\Model\App; +namespace Magento\GraphQlCache\Model\Plugin\App\PageCache; /** * Handles unique identifier for graphql query */ -class CacheIdentifierPlugin +class Identifier { /** * @var \Magento\Framework\App\Request\Http @@ -57,7 +58,7 @@ public function __construct( * @return string * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function afterGetValue(\Magento\Framework\App\PageCache\Identifier $identifier, string $result) + public function afterGetValue(\Magento\Framework\App\PageCache\Identifier $identifier, string $result) : string { if ($this->config->isEnabled()) { $data = [ diff --git a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php similarity index 90% rename from app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php rename to app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php index 029e29df3af23..f3cccdb0995d2 100644 --- a/app/code/Magento/GraphQlCache/Query/Resolver/Plugin.php +++ b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\GraphQlCache\Query\Resolver; +namespace Magento\GraphQlCache\Model\Plugin\Query; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; @@ -15,11 +15,9 @@ use Magento\Framework\App\RequestInterface; /** - * Class Plugin - * - * @package Magento\GraphQlCache\Query\Resolver + * Plugin to handle cache validation that can be done after each resolver */ -class Plugin +class Resolver { /** * @var CacheableQuery @@ -42,7 +40,7 @@ public function __construct(CacheableQuery $cacheableQuery, RequestInterface $re } /** - * @inheritdoc + * Set cache validity to the cacheableQuery after resolving any resolver in a query * * @param ResolverInterface $subject * @param Object $resolvedValue @@ -52,6 +50,7 @@ public function __construct(CacheableQuery $cacheableQuery, RequestInterface $re * @param array|null $value * @param array|null $args * @return mixed + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function afterResolve( ResolverInterface $subject, @@ -84,7 +83,7 @@ public function afterResolve( * @param Object $resolvedValue * @return array */ - private function extractResolvedItemsIds($resolvedValue) + private function extractResolvedItemsIds($resolvedValue) : array { if (isset($resolvedValue['ids']) && is_array($resolvedValue['ids'])) { return $resolvedValue['ids']; diff --git a/app/code/Magento/GraphQlCache/README.md b/app/code/Magento/GraphQlCache/README.md index 98ccf26d038a8..fd2f19f957c5e 100644 --- a/app/code/Magento/GraphQlCache/README.md +++ b/app/code/Magento/GraphQlCache/README.md @@ -1,4 +1,4 @@ # GraphQl Cache -**GraphQl Cache** provides the caching ability for a graphql query. -This enabled Magento's builtin cache and varnish by leveraging FPC (Full page cache) that's used for front end. +**GraphQL Cache** provides the ability to cache GraphQL queries. +This module allows Magento's built-in cache or Varnish as the application for serving the Full Page Cache to the front end. diff --git a/app/code/Magento/GraphQlCache/etc/graphql/di.xml b/app/code/Magento/GraphQlCache/etc/graphql/di.xml index 5c13dbb02e066..8a5b6476c7afc 100644 --- a/app/code/Magento/GraphQlCache/etc/graphql/di.xml +++ b/app/code/Magento/GraphQlCache/etc/graphql/di.xml @@ -12,11 +12,11 @@ <plugin name="front-controller-varnish-cache" type="Magento\PageCache\Model\App\FrontController\VarnishPlugin"/> </type> <type name="Magento\Framework\GraphQl\Query\ResolverInterface"> - <plugin name="cache" type="Magento\GraphQlCache\Query\Resolver\Plugin"/> + <plugin name="cache" type="Magento\GraphQlCache\Model\Plugin\Query\Resolver"/> </type> <type name="Magento\Framework\App\PageCache\Identifier"> <plugin name="core-app-area-design-exception-plugin" - type="Magento\GraphQlCache\Model\App\CacheIdentifierPlugin" sortOrder="1"/> + type="Magento\GraphQlCache\Model\Plugin\App\PageCache\Identifier" sortOrder="1"/> </type> <type name="Magento\Framework\Controller\ResultInterface"> <plugin name="result-builtin-cache" type="Magento\PageCache\Model\Controller\Result\BuiltinPlugin"/> diff --git a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php index 70d4730c2a63b..7999a96917cde 100644 --- a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php +++ b/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php @@ -54,7 +54,6 @@ public function __construct( * * @param string $headerValue * @return void - * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function processHeaderValue(string $headerValue) : void { diff --git a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php b/app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php similarity index 96% rename from app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php rename to app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php index 437ff2c5dacc5..afc84c061df44 100644 --- a/app/code/Magento/StoreGraphQl/Controller/HttpHeaderProcessor/StoreValidator.php +++ b/app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\StoreGraphQl\Controller\HttpHeaderProcessor; +namespace Magento\StoreGraphQl\Controller\HttpRequestValidator; use Magento\Framework\App\HttpRequestInterface; use Magento\Framework\GraphQl\Exception\GraphQlInputException; diff --git a/app/code/Magento/StoreGraphQl/etc/graphql/di.xml b/app/code/Magento/StoreGraphQl/etc/graphql/di.xml index 50f612194893f..c2191164287f1 100644 --- a/app/code/Magento/StoreGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/StoreGraphQl/etc/graphql/di.xml @@ -12,7 +12,7 @@ <item name="Store" xsi:type="object">Magento\StoreGraphQl\Controller\HttpHeaderProcessor\StoreProcessor</item> </argument> <argument name="requestValidators" xsi:type="array"> - <item name="storeValidator" xsi:type="object">Magento\StoreGraphQl\Controller\HttpHeaderProcessor\StoreValidator</item> + <item name="storeValidator" xsi:type="object">Magento\StoreGraphQl\Controller\HttpRequestValidator\StoreValidator</item> </argument> </arguments> </type> diff --git a/lib/internal/Magento/Framework/App/PageCache/Kernel.php b/lib/internal/Magento/Framework/App/PageCache/Kernel.php index 2fb5b832e346e..813762c646d4c 100644 --- a/lib/internal/Magento/Framework/App/PageCache/Kernel.php +++ b/lib/internal/Magento/Framework/App/PageCache/Kernel.php @@ -67,7 +67,7 @@ class Kernel * @param \Magento\Framework\App\Http\ContextFactory|null $contextFactory * @param \Magento\Framework\App\Response\HttpFactory|null $httpFactory * @param \Magento\Framework\Serialize\SerializerInterface|null $serializer - * @param AppState $state + * @param AppState|null $state */ public function __construct( \Magento\Framework\App\PageCache\Cache $cache, @@ -77,12 +77,11 @@ public function __construct( \Magento\Framework\App\Http\ContextFactory $contextFactory = null, \Magento\Framework\App\Response\HttpFactory $httpFactory = null, \Magento\Framework\Serialize\SerializerInterface $serializer = null, - AppState $state + AppState $state = null ) { $this->cache = $cache; $this->identifier = $identifier; $this->request = $request; - $this->state = $state; if ($context) { $this->context = $context; @@ -112,6 +111,14 @@ public function __construct( \Magento\Framework\Serialize\SerializerInterface::class ); } + + if ($state) { + $this->state = $state; + } else { + $this->state = \Magento\Framework\App\ObjectManager::getInstance()->get( + AppState::class + ); + } } /** diff --git a/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php b/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php index dc59e490a0203..0fc51e4ecd069 100644 --- a/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php +++ b/lib/internal/Magento/Framework/GraphQl/Config/Element/Field.php @@ -61,8 +61,8 @@ class Field implements OutputFieldInterface * @param string $itemType * @param string $resolver * @param string $description - * @param array $cache * @param array $arguments + * @param array $cache */ public function __construct( string $name, @@ -72,8 +72,8 @@ public function __construct( string $itemType = '', string $resolver = '', string $description = '', - array $cache = [], - array $arguments = [] + array $arguments = [], + array $cache = [] ) { $this->name = $name; $this->type = $isList ? $itemType : $type; diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php index 97f169054a071..c20a3875e71fb 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php @@ -28,19 +28,24 @@ class FieldMetaReader private $cacheTagReader; /** - * FieldMetaReader constructor. - * @param \Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\TypeMetaWrapperReader $typeMetaReader + * @param TypeMetaWrapperReader $typeMetaReader * @param DocReader $docReader - * @param CacheTagReader $cacheTagReader + * @param CacheTagReader|null $cacheTagReader */ public function __construct( TypeMetaWrapperReader $typeMetaReader, DocReader $docReader, - CacheTagReader $cacheTagReader + CacheTagReader $cacheTagReader = null ) { $this->typeMetaReader = $typeMetaReader; $this->docReader = $docReader; - $this->cacheTagReader = $cacheTagReader; + if ($cacheTagReader) { + $this->cacheTagReader = $cacheTagReader; + } else { + $this->cacheTagReader = \Magento\Framework\App\ObjectManager::getInstance()->get( + CacheTagReader::class + ); + } } /** diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php index 262ae33fb0a4c..92ac22607b981 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php @@ -33,19 +33,24 @@ class InputObjectType implements TypeMetaReaderInterface private $cacheTagReader; /** - * InputObjectType constructor. * @param TypeMetaWrapperReader $typeMetaReader * @param DocReader $docReader - * @param CacheTagReader $cacheTagReader + * @param CacheTagReader|null $cacheTagReader */ public function __construct( TypeMetaWrapperReader $typeMetaReader, DocReader $docReader, - CacheTagReader $cacheTagReader + CacheTagReader $cacheTagReader = null ) { $this->typeMetaReader = $typeMetaReader; $this->docReader = $docReader; - $this->cacheTagReader = $cacheTagReader; + if ($cacheTagReader) { + $this->cacheTagReader = $cacheTagReader; + } else { + $this->cacheTagReader = \Magento\Framework\App\ObjectManager::getInstance()->get( + CacheTagReader::class + ); + } } /** diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php index 2020f42dcaefe..bd21e6361d4c4 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php @@ -33,19 +33,24 @@ class InterfaceType implements TypeMetaReaderInterface private $cacheTagReader; /** - * InterfaceType constructor. * @param FieldMetaReader $fieldMetaReader * @param DocReader $docReader - * @param CacheTagReader $cacheTagReader + * @param CacheTagReader|null $cacheTagReader */ public function __construct( FieldMetaReader $fieldMetaReader, DocReader $docReader, - CacheTagReader $cacheTagReader + CacheTagReader $cacheTagReader = null ) { $this->fieldMetaReader = $fieldMetaReader; $this->docReader = $docReader; - $this->cacheTagReader = $cacheTagReader; + if ($cacheTagReader) { + $this->cacheTagReader = $cacheTagReader; + } else { + $this->cacheTagReader = \Magento\Framework\App\ObjectManager::getInstance()->get( + CacheTagReader::class + ); + } } /** diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php index 97dc5a3d1f510..361eb30423a98 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php @@ -43,18 +43,24 @@ class ObjectType implements TypeMetaReaderInterface * @param FieldMetaReader $fieldMetaReader * @param DocReader $docReader * @param ImplementsReader $implementsAnnotation - * @param CacheTagReader $cacheTagReader + * @param CacheTagReader|null $cacheTagReader */ public function __construct( FieldMetaReader $fieldMetaReader, DocReader $docReader, ImplementsReader $implementsAnnotation, - CacheTagReader $cacheTagReader + CacheTagReader $cacheTagReader = null ) { $this->fieldMetaReader = $fieldMetaReader; $this->docReader = $docReader; $this->implementsAnnotation = $implementsAnnotation; - $this->cacheTagReader = $cacheTagReader; + if ($cacheTagReader) { + $this->cacheTagReader = $cacheTagReader; + } else { + $this->cacheTagReader = \Magento\Framework\App\ObjectManager::getInstance()->get( + CacheTagReader::class + ); + } } /** From 1c98b32f62a4f2433adb4b01d144fcfc9e12ebf7 Mon Sep 17 00:00:00 2001 From: "Leandro F. L" <lfluvisotto@gmail.com> Date: Mon, 8 Apr 2019 13:53:10 -0300 Subject: [PATCH 188/585] Fix > Exception #0 (BadMethodCallException): Missing required argument of Magento\Msrp\Pricing\MsrpPriceCalculator. --- app/code/Magento/Msrp/Pricing/MsrpPriceCalculator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Msrp/Pricing/MsrpPriceCalculator.php b/app/code/Magento/Msrp/Pricing/MsrpPriceCalculator.php index 3d1e5ef0b8e6c..af5a29eb288ea 100644 --- a/app/code/Magento/Msrp/Pricing/MsrpPriceCalculator.php +++ b/app/code/Magento/Msrp/Pricing/MsrpPriceCalculator.php @@ -23,7 +23,7 @@ class MsrpPriceCalculator implements MsrpPriceCalculatorInterface /** * @param array $msrpPriceCalculators */ - public function __construct(array $msrpPriceCalculators) + public function __construct(array $msrpPriceCalculators = []) { $this->msrpPriceCalculators = $this->getMsrpPriceCalculators($msrpPriceCalculators); } From 4e17e459726226e60f099e88bf1d96c13017ebb2 Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Mon, 8 Apr 2019 12:10:03 -0500 Subject: [PATCH 189/585] MC-4789: Convert CreateSalesRuleEntityPartOneTest to MFTF --- .../Catalog/Test/Mftf/Data/ProductData.xml | 15 ++- .../Section/StorefrontMiniCartSection.xml | 3 + ...CartPriceRuleActionsSectionActionGroup.xml | 32 +++++ ...tPriceRuleConditionsSectionActionGroup.xml | 60 +++++++++ ...eCartPriceRuleLabelsSectionActionGroup.xml | 18 +++ ...PriceRuleSuccessSaveMessageActionGroup.xml | 14 ++ ...sertStorefrontMiniCartItemsActionGroup.xml | 24 ++++ .../StorefrontAddToTheCartActionGroup.xml | 16 +++ .../StorefrontClickOnMiniCartActionGroup.xml | 16 +++ .../Test/Mftf/Data/SalesRuleData.xml | 90 ++++++++++++- .../AdminCartPriceRulesFormSection.xml | 15 ++- ...eConditionAndFreeShippingIsAppliedTest.xml | 113 ++++++++++++++++ ...AndVerifyRuleConditionIsNotAppliedTest.xml | 111 ++++++++++++++++ ...talAndVerifyRuleConditionIsAppliedTest.xml | 118 +++++++++++++++++ ...oryAndVerifyRuleConditionIsAppliedTest.xml | 124 ++++++++++++++++++ ...ghtAndVerifyRuleConditionIsAppliedTest.xml | 112 ++++++++++++++++ 16 files changed, 878 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCartPriceRuleSuccessSaveMessageActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 1aca63b28c95d..f7a980e1604e1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -982,4 +982,17 @@ <data key="tax_class_id">2</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> </entity> -</entities> + <entity name="defaultSimpleProductWeight200" type="product"> + <data key="name" unique="suffix">Testp</data> + <data key="sku" unique="suffix">testsku</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="price">560.00</data> + <data key="urlKey" unique="suffix">testurl-</data> + <data key="status">1</data> + <data key="quantity">25</data> + <data key="weight">200</data> + <requiredEntity type="product_extension_attribute">EavStock100</requiredEntity> + </entity> +</entities> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml index 38c88bf4f80bb..fec06f226d45e 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml @@ -33,5 +33,8 @@ <element name="subtotal" type="text" selector="//tr[@class='totals sub']//td[@class='amount']/span"/> <element name="emptyCart" type="text" selector=".counter.qty.empty"/> <element name="minicartContent" type="block" selector="#minicart-content-wrapper"/> + <element name="productQuantity" type="input" selector="//*[@id='mini-cart']//a[contains(text(),'{{productName}}')]/../..//div[@class='details-qty qty']//input[@data-item-qty='{{qty}}']" parameterized="true"/> + <element name="productImage" type="text" selector="//ol[@id='mini-cart']//img[@class='product-image-photo']"/> + <element name="productSubTotal" type="text" selector="//div[@class='subtotal']//span/span[@class='price']"/> </section> </sections> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml new file mode 100644 index 0000000000000..a2bc44ccceef0 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup"> + <arguments> + <argument name="ruleName" type="entity"/> + </arguments> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.actionsHeader}}" visible="true" stepKey="clickToExpandActions"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{ruleName.simple_action}}" stepKey="selectActionType"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{ruleName.discount_amount}}" stepKey="fillDiscountAmount"/> + <fillField selector="{{AdminCartPriceRulesFormSection.maximumQtyDiscount}}" userInput="{{ruleName.maximumQtyDiscount}}" stepKey="fillMaximumQtyDiscount"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountStep}}" userInput="{{ruleName.discount_step}}" stepKey="fillDiscountStep"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleActionsSectionShippingAmountActionGroup"> + <click selector="{{AdminCartPriceRulesFormSection.applyToShippingAmount}}" stepKey="clickApplyToShipping"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleActionsSectionSubsequentRulesActionGroup"> + <click selector="{{AdminCartPriceRulesFormSection.discardSubsequentRules}}" stepKey="clickApplyToShipping"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup"> + <arguments> + <argument name="ruleName" type="string"/> + </arguments> + <selectOption selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{ruleName}}" stepKey="selectForMatchingItemsOnly"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml new file mode 100644 index 0000000000000..4d53b56c41789 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCartPriceRuleConditionsSectionSubtotalActionGroup"> + <arguments> + <argument name="ruleName" type="entity"/> + <argument name="condition1" type="string"/> + </arguments> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewCondition"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition1}}" stepKey="selectCondition1"/> + <waitForPageLoad stepKey="waitForConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{ruleName.subtotal}}" stepKey="fillSubtotalParameter"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleConditionsSectionShippingCountryActionGroup"> + <arguments> + <argument name="ruleName" type="entity"/> + <argument name="condition2" type="string"/> + </arguments> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewConditionButton"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition2}}" stepKey="selectCondition2"/> + <waitForPageLoad stepKey="waitForSecondConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickTheEllipsis"/> + <click selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" stepKey="clickSelectCountryDropdown"/> + <waitForPageLoad stepKey="waitForDropdownLoad"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" userInput="{{ruleName.shippingCountry}}" stepKey="fillShippingCountryParameter"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleConditionsSectionShippingPostcodeActionGroup"> + <arguments> + <argument name="ruleName" type="entity"/> + <argument name="condition3" type="string"/> + </arguments> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickOnNewCondition"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition3}}" stepKey="selectCondition3"/> + <waitForPageLoad stepKey="waitForThirdConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickOnEllipsis"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--3')}}" userInput="{{ruleName.shippingPostcode}}" stepKey="fillShippingPostcodeParameter"/> + </actionGroup> + <actionGroup name="AdminCreateCartPriceRuleConditionsSectionTotalItemQuantityActionGroup"> + <arguments> + <argument name="ruleName" type="entity"/> + <argument name="condition4" type="string"/> + </arguments> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickOnNewCondition"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition4}}" stepKey="selectCondition4"/> + <waitForPageLoad stepKey="waitForThirdConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickOnEllipsis"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{ruleName.totalItemQuantity}}" stepKey="fillTotalItemQuantity"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml new file mode 100644 index 0000000000000..623b6dd5f3153 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCartPriceRuleLabelsSectionActionGroup"> + <arguments> + <argument name="ruleName"/> + </arguments> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.labelsHeader}}" visible="true" stepKey="clickToExpandLabels"/> + <fillField selector="{{AdminCartPriceRulesFormSection.defaultRuleLabelAllStoreViews}}" userInput="{{ruleName.defaultRuleLabelAllStoreViews}}" stepKey="fillDefaultRuleLabelAllStoreViews"/> + <fillField selector="{{AdminCartPriceRulesFormSection.defaultStoreView}}" userInput="{{ruleName.defaultStoreView}}" stepKey="fillDefaultStoreView"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCartPriceRuleSuccessSaveMessageActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCartPriceRuleSuccessSaveMessageActionGroup.xml new file mode 100644 index 0000000000000..7c76d61cb5b2a --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCartPriceRuleSuccessSaveMessageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCartPriceRuleSuccessSaveMessageActionGroup"> + <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> + <see selector="{{AdminCartPriceRulesFormSection.successMessage}}" userInput="You saved the rule." stepKey="seeAssertSuccessSaveMessage"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml new file mode 100644 index 0000000000000..b569f8f5e013e --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertStorefrontMiniCartItemsActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontMiniCartItemsActionGroup"> + <arguments> + <argument name="productName" type="string"/> + <argument name="productPrice" type="string"/> + <argument name="cartSubtotal" type="string"/> + <argument name="qty" type="string"/> + </arguments> + <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{productName}}" stepKey="seeProductNameInMiniCart"/> + <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{productPrice}}" stepKey="seeProductPriceInMiniCart"/> + <seeElement selector="{{StorefrontMinicartSection.goToCheckout}}" stepKey="seeCheckOutButtonInMiniCart"/> + <seeElement selector="{{StorefrontMinicartSection.productQuantity(productName, qty)}}" stepKey="seeProductQuantity1"/> + <seeElement selector="{{StorefrontMinicartSection.productImage}}" stepKey="seeProductImage"/> + <see selector="{{StorefrontMinicartSection.productSubTotal}}" userInput="{{cartSubtotal}}" stepKey="seeSubTotal"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml new file mode 100644 index 0000000000000..416dbde6748b1 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontAddToTheCartActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAddToTheCartActionGroup"> + <waitForPageLoad stepKey="waitForPageLoad"/> + <scrollTo selector="{{StorefrontProductActionSection.addToCart}}" stepKey="scrollToAddToCartButton"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml new file mode 100644 index 0000000000000..8c31f89d52ca0 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontClickOnMiniCartActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontClickOnMiniCartActionGroup"> + <scrollToTopOfPage stepKey="scrollToTheTopOfThePage"/> + <waitForElementVisible selector="{{StorefrontMinicartSection.showCart}}" stepKey="waitForElementToBeVisible"/> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="clickOnMiniCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml index 8f6e63534b0ca..4e951ca5b6afe 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml @@ -193,4 +193,92 @@ <entity name="SalesRuleNoCouponWithFixedDiscount" extends="ApiCartRule"> <data key="simple_action">by_fixed</data> </entity> -</entities> + + <entity name="CartPriceRuleConditionAndFreeShippingApplied"> + <data key="name" unique="suffix">Cart Price Rule For RuleCondition And FreeShipping</data> + <data key="description">Description for Cart Price Rule</data> + <data key="is_active">Yes</data> + <data key="websites">Main Website</data> + <data key="customerGroups">NOT LOGGED IN</data> + <data key="coupon_type">No Coupon</data> + <data key="simple_action">Percent of product price discount</data> + <data key="discount_amount">50</data> + <data key="maximumQtyDiscount">0</data> + <data key="discount_step">0</data> + <data key="apply_to_shipping">0</data> + <data key="simple_free_shipping">For matching items only</data> + <data key="defaultRuleLabelAllStoreViews">Free Shipping in conditions</data> + <data key="defaultStoreView">Free Shipping in conditions</data> + </entity> + + <entity name="CartPriceRuleConditionAppliedForSubtotal"> + <data key="name" unique="suffix">Cart Price Rule For Rule Condition</data> + <data key="description">Description for Cart Price Rule</data> + <data key="is_active">Yes</data> + <data key="websites">Main Website</data> + <data key="customerGroups">NOT LOGGED IN</data> + <data key="coupon_type">No Coupon</data> + <data key="subtotal">560</data> + <data key="simple_action">Percent of product price discount</data> + <data key="discount_amount">50</data> + <data key="maximumQtyDiscount">0</data> + <data key="discount_step">0</data> + <data key="apply_to_shipping">0</data> + <data key="simple_free_shipping">No</data> + <data key="defaultRuleLabelAllStoreViews">Free Shipping in Rule conditions</data> + <data key="defaultStoreView">Free Shipping in Rule conditions</data> + </entity> + + <entity name="CartPriceRuleConditionNotApplied"> + <data key="name" unique="suffix">Cart Price Rule Condition Not Applied</data> + <data key="description">Description for Cart Price Rule</data> + <data key="is_active">Yes</data> + <data key="websites">Main Website</data> + <data key="customerGroups">NOT LOGGED IN</data> + <data key="coupon_type">No Coupon</data> + <data key="totalItemQuantity">3</data> + <data key="simple_action">Percent of product price discount</data> + <data key="discount_amount">50</data> + <data key="maximumQtyDiscount">0</data> + <data key="discount_step">0</data> + <data key="apply_to_shipping">0</data> + <data key="simple_free_shipping">No</data> + <data key="defaultRuleLabelAllStoreViews">Total Items Quantity-Not Applied test</data> + <data key="defaultStoreView">Total Items Quantity-Not Applied test</data> + </entity> + + <entity name="CartPriceRuleConditionAppliedForWeight"> + <data key="name" unique="suffix">Cart Price Rule With Weight Condition Applied</data> + <data key="description">Description for Cart Price Rule</data> + <data key="is_active">Yes</data> + <data key="websites">Main Website</data> + <data key="customerGroups">NOT LOGGED IN</data> + <data key="coupon_type">No Coupon</data> + <data key="totalWeight">200</data> + <data key="simple_action">Percent of product price discount</data> + <data key="discount_amount">50</data> + <data key="maximumQtyDiscount">0</data> + <data key="discount_step">0</data> + <data key="apply_to_shipping">0</data> + <data key="simple_free_shipping">No</data> + <data key="defaultRuleLabelAllStoreViews">Total Weight is 200</data> + <data key="defaultStoreView">Total Weight is 200</data> + </entity> + + <entity name="CartPriceRuleConditionAppliedForCategory"> + <data key="name" unique="suffix">Cart Price Rule With Category Condition Applied</data> + <data key="description">Description for Cart Price Rule</data> + <data key="is_active">Yes</data> + <data key="websites">Main Website</data> + <data key="customerGroups">NOT LOGGED IN</data> + <data key="coupon_type">No Coupon</data> + <data key="simple_action">Percent of product price discount</data> + <data key="discount_amount">50</data> + <data key="maximumQtyDiscount">0</data> + <data key="discount_step">0</data> + <data key="apply_to_shipping">0</data> + <data key="simple_free_shipping">No</data> + <data key="defaultRuleLabelAllStoreViews">Product attribute combination - Category</data> + <data key="defaultStoreView">Product attribute combination - Category</data> + </entity> +</entities> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml index c8da82407457d..9f74eba562259 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml @@ -16,6 +16,7 @@ <!-- Rule Information (the main form on the page) --> <element name="ruleInformationHeader" type="button" selector="div[data-index='rule_information']" timeout="30"/> <element name="ruleName" type="input" selector="input[name='name']"/> + <element name="description" type="textarea" selector="//div[@class='admin__field-control']/textarea[@name='description']"/> <element name="websites" type="multiselect" selector="select[name='website_ids']"/> <element name="customerGroups" type="multiselect" selector="select[name='customer_group_ids']"/> <element name="coupon" type="select" selector="select[name='coupon_type']"/> @@ -39,6 +40,12 @@ <element name="ruleParameterInput" type="input" selector="rule[conditions][{{arg}}][value]" parameterized="true"/> <element name="openChooser" type="button" selector="//label[@for='conditions__{{arg}}__value']" parameterized="true"/> <element name="categoryCheckbox" type="checkbox" selector="//span[contains(text(), '{{arg}}')]/parent::a/preceding-sibling::input[@type='checkbox']" parameterized="true"/> + <element name="newCondition" type="button" selector=".rule-param.rule-param-new-child" timeout="30"/> + <element name="conditionSelect" type="select" selector="select[name='rule[conditions][1][new_child]']"/> + <element name="targetEllipsis" type="input" selector="//ul[contains(@id, 'conditions')]//a[.='...']"/> + <element name="ruleFieldByIndex" type="input" selector="[id='conditions__{{index}}__value']" parameterized="true"/> + <element name="addNewCondition" type="button" selector="//ul[@id = 'conditions__{{nestedIndex}}__children']/li/span[contains(@class, 'rule-param-new-child')]" parameterized="true" timeout="30"/> + <element name="conditionSelectDropdown" type="select" selector="select[name='rule[conditions][{{nestedIndex}}][new_child]']" parameterized="true"/> <!-- Actions sub-form --> <element name="actionsTab" type="text" selector="//div[@data-index='actions']//span[contains(.,'Actions')][1]"/> @@ -58,10 +65,16 @@ <element name="applyDiscountToShipping" type="checkbox" selector="input[name='apply_to_shipping']"/> <element name="applyDiscountToShippingLabel" type="checkbox" selector="input[name='apply_to_shipping']+label"/> <element name="discountAmount" type="input" selector="input[name='discount_amount']"/> + <element name="maximumQtyDiscount" type="input" selector="input[name='discount_qty']"/> <element name="discountStep" type="input" selector="input[name='discount_step']"/> <element name="addRewardPoints" type="input" selector="input[name='extension_attributes[reward_points_delta]']"/> <element name="freeShipping" type="select" selector="//select[@name='simple_free_shipping']"/> + <!-- Labels sub-form --> + <element name="labelsHeader" type="button" selector="div[data-index='labels']" timeout="30"/> + <element name="defaultRuleLabelAllStoreViews" type="input" selector="input[name='store_labels[0]']"/> + <element name="defaultStoreView" type="input" selector="input[name='store_labels[1]']"/> + <!-- Manage Coupon Codes sub-form --> <element name="manageCouponCodesHeader" type="button" selector="div[data-index='manage_coupon_codes']" timeout="30"/> <element name="successMessage" type="text" selector="div.message.message-success.success"/> @@ -69,4 +82,4 @@ <element name="generateCouponsButton" type="button" selector="#coupons_generate_button" timeout="30"/> <element name="generatedCouponByIndex" type="text" selector="#couponCodesGrid_table > tbody > tr:nth-child({{var}}) > td.col-code" parameterized="true"/> </section> -</sections> +</sections> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml new file mode 100644 index 0000000000000..5ed2e423288d9 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest"> + <annotations> + <stories value="Create Sales Rule"/> + <title value="Create Cart Price Rule And Verify Rule Condition And Free Shipping Is Applied"/> + <description value="Test log in to Cart Price Rules and Create Cart Price Rule And Verify Rule Condition And Free Shipping Is Applied"/> + <testCaseId value="MC-15604"/> + <severity value="CRITICAL"/> + <group value="SalesRule"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="defaultSimpleProduct" stepKey="initialSimpleProduct"/> + </before> + <after> + <deleteData stepKey="deleteProduct" createDataKey="initialSimpleProduct"/> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCreatedCartPriceRule"> + <argument name="ruleName" value="{{CartPriceRuleConditionAndFreeShippingApplied.name}}"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create cart price rule as per data and verify AssertCartPriceRuleSuccessSaveMessage--> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForPriceList"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.name}}" stepKey="fillRuleName"/> + <fillField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.description}}" stepKey="fillDescription"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.websites}}" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" parameterArray="[{{CartPriceRuleConditionAndFreeShippingApplied.customerGroups}}]" stepKey="selectCustomerGroup"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.coupon_type}}" stepKey="selectCouponType"/> + <scrollTo selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="scrollToActionsHeader"/> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> + <argument name="ruleName" value="CartPriceRuleConditionAndFreeShippingApplied"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> + <argument name="ruleName" value="{{CartPriceRuleConditionAndFreeShippingApplied.simple_free_shipping}}"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> + <argument name="ruleName" value="CartPriceRuleConditionAndFreeShippingApplied"/> + </actionGroup> + <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="seeAssertCartPriceRuleSuccessSaveMessage"/> + + <!--Search created cart price rule in grid--> + <actionGroup ref="AdminFilterCartPriceRuleActionGroup" stepKey="searchCreatedCartPriceRuleInGrid"> + <argument name="ruleName" value="CartPriceRuleConditionAndFreeShippingApplied.name"/> + </actionGroup> + + <!--Go to cart price rule form page and verify AssertCartPriceRuleForm--> + <waitForPageLoad stepKey="waitForAdminCartPriceRuleEditPageLoad"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.name}}" stepKey="seeRuleName"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.description}}" stepKey="seeDescription"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.websites}}" stepKey="seeWebsites"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.customerGroups}}" stepKey="seeCustomerGroup"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.coupon_type}}" stepKey="seeCouponType"/> + <scrollTo selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickActionsHeader"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.actionsHeader}}" visible="true" stepKey="clickExpandActions"/> + <see selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.simple_action}}" stepKey="seeActionApplyType"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.discount_amount}}" stepKey="seeDiscountAmount"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.simple_free_shipping}}" stepKey="seeFreeShipping"/> + <scrollTo selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="clickLabelsHeader"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.labelsHeader}}" visible="true" stepKey="clickToExpandLabels"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.defaultRuleLabelAllStoreViews}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.defaultRuleLabelAllStoreViews}}" stepKey="seeDefaultRuleLabelAllStoreViews"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.defaultStoreView}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.defaultStoreView}}" stepKey="seeDefaultStoreView"/> + + <!--Go to storefront page and verify created product--> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$initialSimpleProduct$$"/> + </actionGroup> + <!--Click on Add To Cart button--> + <actionGroup ref="StorefrontAddToTheCartActionGroup" stepKey="clickOnAddToCartButton"/> + <!--Click on mini cart--> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> + + <!--Open mini cart and verify Shopping cart subtotal equals to grand total--> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="verifyCartSubtotalEqualsGrandTotal"> + <argument name="productName" value="$$initialSimpleProduct.name$$"/> + <argument name="productPrice" value="$560.00"/> + <argument name="cartSubtotal" value="$560.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!--Click on view and edit cart link--> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="goToShoppingCartFromMinicart"/> + <waitForPageLoad stepKey="waitForViewAndEditCartToOpen"/> + <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" visible="true" stepKey="clickEstimateShippingAndTaxToOpen"/> + <waitForPageLoad stepKey="waitForEstimateShippingAndTaxToOpen"/> + <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="{{US_Address_CA.country_id}}" stepKey="selectUnitedStatesCountry"/> + <waitForPageLoad stepKey="waitToSelectCountry"/> + <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{US_Address_CA.state}}" stepKey="selectCaliforniaRegion"/> + <waitForPageLoad stepKey="waitToSelectState"/> + <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{US_Address_CA.postcode}}" stepKey="inputPostCode"/> + <!--After selecting country, province and postcode, verify AssertCartPriceRuleConditionIsApplied and AssertCartPriceRuleFreeShippingIsApplied--> + <actionGroup ref="StorefrontCheckCartActionGroup" stepKey="cartAssert"> + <argument name="subtotal" value="$560.00"/> + <argument name="shipping" value="$0.00"/> + <argument name="shippingMethod" value="Flat Rate - Fixed"/> + <argument name="total" value="$280.00"/> + </actionGroup> + <see selector="{{CheckoutCartSummarySection.shipping}}" userInput="$0.00" stepKey="seeAssertFreeShippingConditionApplied"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$280.00" stepKey="seeAssertDiscountAmountAppliedForMatchingItemsConditionIsTrue"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml new file mode 100644 index 0000000000000..38ca57e5da5dd --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest"> + <annotations> + <stories value="Create Sales Rule"/> + <title value="Create Cart Price Rule And Verify Rule Condition Is Not Applied"/> + <description value="Test log in to Cart Price Rules and Create Cart Price Rule And Verify Rule Condition Is Not Applied"/> + <testCaseId value="MC-15606"/> + <severity value="CRITICAL"/> + <group value="SalesRule"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="defaultSimpleProduct" stepKey="initialSimpleProduct"/> + </before> + <after> + <deleteData stepKey="deleteProduct" createDataKey="initialSimpleProduct"/> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCreatedCartPriceRule"> + <argument name="ruleName" value="{{CartPriceRuleConditionNotApplied.name}}"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create cart price rule as per data and verify AssertCartPriceRuleSuccessSaveMessage--> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForPriceList"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CartPriceRuleConditionNotApplied.name}}" stepKey="fillRuleName"/> + <fillField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{CartPriceRuleConditionNotApplied.description}}" stepKey="fillDescription"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionNotApplied.websites}}" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" parameterArray="[{{CartPriceRuleConditionNotApplied.customerGroups}}]" stepKey="selectCustomerGroup"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionNotApplied.coupon_type}}" stepKey="selectCouponType"/> + <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToConditionsHeader"/> + <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionTotalItemQuantityActionGroup" stepKey="createActiveCartPriceRuleConditionsTotalItemQuantitySection"> + <argument name="ruleName" value="CartPriceRuleConditionNotApplied"/> + <argument name="condition4" value="Total Items Quantity"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> + <argument name="ruleName" value="CartPriceRuleConditionNotApplied"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> + <argument name="ruleName" value="{{CartPriceRuleConditionNotApplied.simple_free_shipping}}"/> + </actionGroup> + <scrollTo selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="scrollToLabelsHeader"/> + <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> + <argument name="ruleName" value="CartPriceRuleConditionNotApplied"/> + </actionGroup> + <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="seeAssertCartPriceRuleSuccessSaveMessage"/> + + <!--Search created cart price rule in grid--> + <actionGroup ref="AdminFilterCartPriceRuleActionGroup" stepKey="searchCreatedCartPriceRuleInGrid"> + <argument name="ruleName" value="CartPriceRuleConditionNotApplied.name"/> + </actionGroup> + + <!--Go to cart price rule form page and verify AssertCartPriceRuleForm--> + <waitForPageLoad stepKey="waitForAdminCartPriceRuleEditPageLoad"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CartPriceRuleConditionNotApplied.name}}" stepKey="seeRuleName"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{CartPriceRuleConditionNotApplied.description}}" stepKey="seeDescription"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionNotApplied.websites}}" stepKey="seeWebsites"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="{{CartPriceRuleConditionNotApplied.customerGroups}}" stepKey="seeCustomerGroup"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionNotApplied.coupon_type}}" stepKey="seeCouponType"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{CartPriceRuleConditionNotApplied.totalItemQuantity}}" stepKey="seeTotalItemQuantity"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.actionsHeader}}" visible="true" stepKey="clickExpandActions"/> + <see selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{CartPriceRuleConditionNotApplied.simple_action}}" stepKey="seeActionApplyType"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{CartPriceRuleConditionNotApplied.discount_amount}}" stepKey="seeDiscountAmount"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{CartPriceRuleConditionNotApplied.simple_free_shipping}}" stepKey="seeFreeShipping"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.labelsHeader}}" visible="true" stepKey="clickToExpandLabels"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.defaultRuleLabelAllStoreViews}}" userInput="{{CartPriceRuleConditionNotApplied.defaultRuleLabelAllStoreViews}}" stepKey="seeDefaultRuleLabelAllStoreViews"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.defaultStoreView}}" userInput="{{CartPriceRuleConditionNotApplied.defaultStoreView}}" stepKey="seeDefaultStoreView"/> + + <!--Go to storefront page and verify created product--> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$initialSimpleProduct$$"/> + </actionGroup> + <fillField selector="{{StorefrontProductInfoMainSection.qty}}" userInput="2" stepKey="fillProductQuantity"/> + <!--Click on Add To Cart button--> + <actionGroup ref="StorefrontAddToTheCartActionGroup" stepKey="clickOnAddToCartButton"/> + <!--Click on mini cart--> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> + + <!--Open mini cart and verify Shopping cart subtotal equals to grand total--> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="verifyCartSubtotalEqualsGrandTotal"> + <argument name="productName" value="$$initialSimpleProduct.name$$"/> + <argument name="productPrice" value="$560.00"/> + <argument name="cartSubtotal" value="$1,120.00" /> + <argument name="qty" value="2"/> + </actionGroup> + + <!--Click on view and edit cart link--> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="goToShoppingCartFromMinicart"/> + <waitForPageLoad stepKey="waitForViewAndEditCartToOpen"/> + <!--Verify AssertCartPriceRuleConditionIsNotApplied(Shopping cart subtotal equals to grand total - price rule has not been applied)--> + <actionGroup ref="StorefrontCheckCartActionGroup" stepKey="cartAssert"> + <argument name="subtotal" value="$1,120.00"/> + <argument name="shipping" value="$10.00"/> + <argument name="shippingMethod" value="Flat Rate - Fixed"/> + <argument name="total" value="$1,130.00"/> + </actionGroup> + <dontSee selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeAssertDiscountAmountForRuleConditionNotApplied"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml new file mode 100644 index 0000000000000..22b03287c8952 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest"> + <annotations> + <stories value="Create Sales Rule"/> + <title value="Create Cart Price Rule For Matching Subtotal And Verify Rule Condition Is Applied"/> + <description value="Test log in to Cart Price Rules and Create Cart Price Rule For Matching Subtotal And Verify Rule Condition Is Applied"/> + <testCaseId value="MC-15605"/> + <severity value="CRITICAL"/> + <group value="SalesRule"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="defaultSimpleProduct" stepKey="initialSimpleProduct"/> + </before> + <after> + <deleteData stepKey="deleteProduct" createDataKey="initialSimpleProduct"/> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCreatedCartPriceRule"> + <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForSubtotal.name}}"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create cart price rule as per data and verify AssertCartPriceRuleSuccessSaveMessage--> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForPriceList"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.name}}" stepKey="fillRuleName"/> + <fillField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.description}}" stepKey="fillDescription"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.websites}}" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" parameterArray="[{{CartPriceRuleConditionAppliedForSubtotal.customerGroups}}]" stepKey="selectCustomerGroup"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.coupon_type}}" stepKey="selectCouponType"/> + <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToConditionsHeader"/> + <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionSubtotalActionGroup" stepKey="createActiveCartPriceRuleConditionsSubtotalSection"> + <argument name="ruleName" value="CartPriceRuleConditionAppliedForSubtotal"/> + <argument name="condition1" value="Subtotal"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> + <argument name="ruleName" value="CartPriceRuleConditionAppliedForSubtotal"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> + <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForSubtotal.simple_free_shipping}}"/> + </actionGroup> + <scrollTo selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="scrollToLabelsHeader"/> + <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> + <argument name="ruleName" value="CartPriceRuleConditionAppliedForSubtotal"/> + </actionGroup> + <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="seeAssertCartPriceRuleSuccessSaveMessage"/> + + <!--Search created cart price rule in grid--> + <actionGroup ref="AdminFilterCartPriceRuleActionGroup" stepKey="searchCreatedCartPriceRuleInGrid"> + <argument name="ruleName" value="CartPriceRuleConditionAppliedForSubtotal.name"/> + </actionGroup> + + <!--Go to cart price rule form page and verify AssertCartPriceRuleForm--> + <waitForPageLoad stepKey="waitForAdminCartPriceRuleEditPageLoad"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.name}}" stepKey="seeRuleName"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.description}}" stepKey="seeDescription"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.websites}}" stepKey="seeWebsites"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.customerGroups}}" stepKey="seeCustomerGroup"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.coupon_type}}" stepKey="seeCouponType"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.subtotal}}" stepKey="seeSubtotalParameter"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.actionsHeader}}" visible="true" stepKey="clickExpandActions"/> + <see selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.simple_action}}" stepKey="seeActionApplyType"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.discount_amount}}" stepKey="seeDiscountAmount"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.simple_free_shipping}}" stepKey="seeFreeShipping"/> + <scrollTo selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="scrollToTheLabelsHeader"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.labelsHeader}}" visible="true" stepKey="clickToExpandLabels"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.defaultRuleLabelAllStoreViews}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.defaultRuleLabelAllStoreViews}}" stepKey="seeDefaultRuleLabelAllStoreViews"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.defaultStoreView}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.defaultStoreView}}" stepKey="seeDefaultStoreView"/> + + <!--Go to storefront page and verify created product--> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$initialSimpleProduct$$"/> + </actionGroup> + <!--Click on Add To Cart button--> + <actionGroup ref="StorefrontAddToTheCartActionGroup" stepKey="clickOnAddToCartButton"/> + <!--Click on mini cart--> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> + + <!--Open mini cart and verify Shopping cart subtotal equals to grand total--> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="verifyCartSubtotalEqualsGrandTotal"> + <argument name="productName" value="$$initialSimpleProduct.name$$"/> + <argument name="productPrice" value="$560.00"/> + <argument name="cartSubtotal" value="$560.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!--Click on view and edit cart link--> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="goToShoppingCartFromMinicart"/> + <waitForPageLoad stepKey="waitForViewAndEditCartToOpen"/> + <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" visible="true" stepKey="clickEstimateShippingAndTaxToOpen"/> + <waitForPageLoad stepKey="waitForEstimateShippingAndTaxToOpen"/> + <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="{{US_Address_CA.country_id}}" stepKey="selectUnitedStatesCountry"/> + <waitForPageLoad stepKey="waitToSelectCountry"/> + <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{US_Address_CA.state}}" stepKey="selectCaliforniaRegion"/> + <waitForPageLoad stepKey="waitToSelectState"/> + <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{US_Address_CA.postcode}}" stepKey="inputPostCode"/> + <!--After selecting country, province and postcode, verify AssertCartPriceRuleConditionIsApplied if Subtotal condition is True--> + <actionGroup ref="StorefrontCheckCartActionGroup" stepKey="cartAssert"> + <argument name="subtotal" value="$560.00"/> + <argument name="shipping" value="$5.00"/> + <argument name="shippingMethod" value="Flat Rate - Fixed"/> + <argument name="total" value="$285.00"/> + </actionGroup> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$280.00" stepKey="seeAssertDiscountAmountAppliedForSubtotalConditionIsTrue"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml new file mode 100644 index 0000000000000..87f963a78d718 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest"> + <annotations> + <stories value="Create Sales Rule"/> + <title value="Create Cart Price Rule With Matching Category And Verify Rule Condition Is Applied"/> + <description value="Test log in to Cart Price Rules and Create Cart Price Rule With Matching Category And Verify Rule Condition Is Applied"/> + <testCaseId value="MC-15608"/> + <severity value="CRITICAL"/> + <group value="SalesRule"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <actionGroup ref="FillAdminSimpleProductForm" stepKey="fillProductFieldsInAdmin"> + <argument name="category" value="$$createCategory$$"/> + <argument name="simpleProduct" value="_defaultProduct"/> + </actionGroup> + </before> + <after> + <deleteData createDataKey="createCategory" stepKey="deletePreReqCategory"/> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteSimpleProduct"> + <argument name="product" value="_defaultProduct"/> + </actionGroup> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCreatedCartPriceRule"> + <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForCategory.name}}"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create cart price rule as per data and verify AssertCartPriceRuleSuccessSaveMessage--> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForPriceList"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CartPriceRuleConditionAppliedForCategory.name}}" stepKey="fillRuleName"/> + <fillField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{CartPriceRuleConditionAppliedForCategory.description}}" stepKey="fillDescription"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAppliedForCategory.websites}}" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" parameterArray="[{{CartPriceRuleConditionAppliedForCategory.customerGroups}}]" stepKey="selectCustomerGroup"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAppliedForCategory.coupon_type}}" stepKey="selectCouponType"/> + <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToConditionsHeader"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <click selector="{{AdminCartPriceRulesFormSection.addNewCondition('1')}}" stepKey="clickOnAddNewCondition"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelectDropdown('1')}}" userInput="Product attribute combination" stepKey="selectProductAttributeCombination"/> + <waitForPageLoad stepKey="waitForConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.addNewCondition('1--1')}}" stepKey="clickOnTheAddNewCondition"/> + <waitForPageLoad stepKey="waitForToggleLoad"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelectDropdown('1--1')}}" userInput="Category" stepKey="selectCategory"/> + <waitForElementVisible selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="a"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickOnEllipsis"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1--1')}}" userInput="$$createCategory.id$$" stepKey="fillTotalItemQuantity"/> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> + <argument name="ruleName" value="CartPriceRuleConditionAppliedForCategory"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> + <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForCategory.simple_free_shipping}}"/> + </actionGroup> + <scrollTo selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="scrollToLabelsHeader"/> + <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> + <argument name="ruleName" value="CartPriceRuleConditionAppliedForCategory"/> + </actionGroup> + <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="seeAssertCartPriceRuleSuccessSaveMessage"/> + + <!--Search created cart price rule in grid--> + <actionGroup ref="AdminFilterCartPriceRuleActionGroup" stepKey="searchCreatedCartPriceRuleInGrid"> + <argument name="ruleName" value="CartPriceRuleConditionAppliedForCategory.name"/> + </actionGroup> + + <!--Go to cart price rule form page and verify AssertCartPriceRuleForm--> + <waitForPageLoad stepKey="waitForAdminCartPriceRuleEditPageLoad"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CartPriceRuleConditionAppliedForCategory.name}}" stepKey="seeRuleName"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{CartPriceRuleConditionAppliedForCategory.description}}" stepKey="seeDescription"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAppliedForCategory.websites}}" stepKey="seeWebsites"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="{{CartPriceRuleConditionAppliedForCategory.customerGroups}}" stepKey="seeCustomerGroup"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAppliedForCategory.coupon_type}}" stepKey="seeCouponType"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditionHeader"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1--1')}}" userInput="$$createCategory.id$$" stepKey="seeCategoryParameter"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.actionsHeader}}" visible="true" stepKey="clickExpandActions"/> + <see selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{CartPriceRuleConditionAppliedForCategory.simple_action}}" stepKey="seeActionApplyType"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{CartPriceRuleConditionAppliedForCategory.discount_amount}}" stepKey="seeDiscountAmount"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{CartPriceRuleConditionAppliedForCategory.simple_free_shipping}}" stepKey="seeFreeShipping"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.labelsHeader}}" visible="true" stepKey="clickToExpandLabels"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.defaultRuleLabelAllStoreViews}}" userInput="{{CartPriceRuleConditionAppliedForCategory.defaultRuleLabelAllStoreViews}}" stepKey="seeDefaultRuleLabelAllStoreViews"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.defaultStoreView}}" userInput="{{CartPriceRuleConditionAppliedForCategory.defaultStoreView}}" stepKey="seeDefaultStoreView"/> + + <!--Go to storefront page and verify created product--> + <amOnPage url="{{StorefrontProductPage.url(_defaultProduct.urlKey)}}" stepKey="onCategoryPage"/> + <waitForPageLoad stepKey="waitForCategoryPageLoad"/> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="openProductPageAndVerifyProduct"> + <argument name="productName" value="_defaultProduct.name"/> + </actionGroup> + + <!--Click on mini cart--> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> + + <!--Open mini cart and verify Shopping cart subtotal equals to grand total--> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="verifyCartSubtotalEqualsGrandTotal"> + <argument name="productName" value="{{_defaultProduct.name}}"/> + <argument name="productPrice" value="$123.00"/> + <argument name="cartSubtotal" value="$123.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!--Click on view and edit cart link--> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="goToShoppingCartFromMinicart"/> + <waitForPageLoad stepKey="waitForViewAndEditToOpen"/> + <!--Verify AssertCartPriceRuleConditionIsApplied if condition category id is matching--> + <actionGroup ref="StorefrontCheckCartActionGroup" stepKey="cartAssert"> + <argument name="subtotal" value="$123.00"/> + <argument name="shipping" value="$5.00"/> + <argument name="shippingMethod" value="Flat Rate - Fixed"/> + <argument name="total" value="$66.50"/> + </actionGroup> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$61.50" stepKey="seeAssertDiscountAmountAppliedForMatchingCategory"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml new file mode 100644 index 0000000000000..bc0277e07cddf --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest"> + <annotations> + <stories value="Create Sales Rule"/> + <title value="Create Cart Price Rule With Matching Total Weight And Verify Rule Condition Is Applied"/> + <description value="Test log in to Cart Price Rules and Create Cart Price Rule With Matching Total Weight And Verify Rule Condition Is Applied"/> + <testCaseId value="MC-15609"/> + <severity value="CRITICAL"/> + <group value="SalesRule"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="defaultSimpleProductWeight200" stepKey="initialSimpleProduct"/> + </before> + <after> + <deleteData stepKey="deleteProduct" createDataKey="initialSimpleProduct"/> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCreatedCartPriceRule"> + <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForWeight.name}}"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create cart price rule as per data and verify AssertCartPriceRuleSuccessSaveMessage--> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForPriceList"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CartPriceRuleConditionAppliedForWeight.name}}" stepKey="fillRuleName"/> + <fillField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{CartPriceRuleConditionAppliedForWeight.description}}" stepKey="fillDescription"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAppliedForWeight.websites}}" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" parameterArray="[{{CartPriceRuleConditionAppliedForWeight.customerGroups}}]" stepKey="selectCustomerGroup"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAppliedForWeight.coupon_type}}" stepKey="selectCouponType"/> + <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToConditionsHeader"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickOnNewCondition"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="Total Weight" stepKey="selectTotalWeight"/> + <waitForPageLoad stepKey="waitForThirdConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickOnEllipsis"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{CartPriceRuleConditionAppliedForWeight.totalWeight}}" stepKey="fillTotalItemQuantity"/> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> + <argument name="ruleName" value="CartPriceRuleConditionAppliedForWeight"/> + </actionGroup> + <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> + <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForWeight.simple_free_shipping}}"/> + </actionGroup> + <scrollTo selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="scrollToLabelsHeader"/> + <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> + <argument name="ruleName" value="CartPriceRuleConditionAppliedForWeight"/> + </actionGroup> + <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="seeAssertCartPriceRuleSuccessSaveMessage"/> + + <!--Search created cart price rule in grid--> + <actionGroup ref="AdminFilterCartPriceRuleActionGroup" stepKey="searchCreatedCartPriceRuleInGrid"> + <argument name="ruleName" value="CartPriceRuleConditionAppliedForWeight.name"/> + </actionGroup> + + <!--Go to cart price rule form page and verify AssertCartPriceRuleForm--> + <waitForPageLoad stepKey="waitForAdminCartPriceRuleEditPageLoad"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CartPriceRuleConditionAppliedForWeight.name}}" stepKey="seeRuleName"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.description}}" userInput="{{CartPriceRuleConditionAppliedForWeight.description}}" stepKey="seeDescription"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAppliedForWeight.websites}}" stepKey="seeWebsites"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="{{CartPriceRuleConditionAppliedForWeight.customerGroups}}" stepKey="seeCustomerGroup"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAppliedForWeight.coupon_type}}" stepKey="seeCouponType"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditionHeader"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{CartPriceRuleConditionAppliedForWeight.totalWeight}}" stepKey="seeTotalWeightParameter"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.actionsHeader}}" visible="true" stepKey="clickExpandActions"/> + <see selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{CartPriceRuleConditionAppliedForWeight.simple_action}}" stepKey="seeActionApplyType"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{CartPriceRuleConditionAppliedForWeight.discount_amount}}" stepKey="seeDiscountAmount"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{CartPriceRuleConditionAppliedForWeight.simple_free_shipping}}" stepKey="seeFreeShipping"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.labelsHeader}}" visible="true" stepKey="clickToExpandLabels"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.defaultRuleLabelAllStoreViews}}" userInput="{{CartPriceRuleConditionAppliedForWeight.defaultRuleLabelAllStoreViews}}" stepKey="seeDefaultRuleLabelAllStoreViews"/> + <seeInField selector="{{AdminCartPriceRulesFormSection.defaultStoreView}}" userInput="{{CartPriceRuleConditionAppliedForWeight.defaultStoreView}}" stepKey="seeDefaultStoreView"/> + + <!--Go to storefront page and verify created product--> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$initialSimpleProduct$$"/> + </actionGroup> + <!--Click on Add To Cart button--> + <actionGroup ref="StorefrontAddToTheCartActionGroup" stepKey="clickOnAddToCartButton"/> + <!--Click on mini cart--> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> + + <!--Open mini cart and verify Shopping cart subtotal equals to grand total--> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="verifyCartSubtotalEqualsGrandTotal"> + <argument name="productName" value="$$initialSimpleProduct.name$$"/> + <argument name="productPrice" value="$560.00"/> + <argument name="cartSubtotal" value="$560.00" /> + <argument name="qty" value="1"/> + </actionGroup> + + <!--Click on view and edit cart link--> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="goToShoppingCartFromMinicart"/> + <waitForPageLoad stepKey="waitForViewAndEditCartToOpen"/> + <!--Verify AssertCartPriceRuleConditionIsApplied if condition Total Weight equals 200 is true--> + <actionGroup ref="StorefrontCheckCartActionGroup" stepKey="cartAssert"> + <argument name="subtotal" value="$560.00"/> + <argument name="shipping" value="$5.00"/> + <argument name="shippingMethod" value="Flat Rate - Fixed"/> + <argument name="total" value="$285.00"/> + </actionGroup> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$280.00" stepKey="seeAssertDiscountAmountAppliedForWeightConditionIsTrue"/> + </test> +</tests> \ No newline at end of file From c2d1f8fa571b1133c09a3b6344f44b2c364efecc Mon Sep 17 00:00:00 2001 From: "Leandro F. L" <lfluvisotto@gmail.com> Date: Mon, 8 Apr 2019 14:41:02 -0300 Subject: [PATCH 190/585] Remove all marketing get params on Varnish to minimize the cache objects (added facebook parameter) --- app/code/Magento/PageCache/etc/varnish4.vcl | 4 ++-- app/code/Magento/PageCache/etc/varnish5.vcl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/PageCache/etc/varnish4.vcl b/app/code/Magento/PageCache/etc/varnish4.vcl index c73c4e39170e6..198b2f6796e69 100644 --- a/app/code/Magento/PageCache/etc/varnish4.vcl +++ b/app/code/Magento/PageCache/etc/varnish4.vcl @@ -92,8 +92,8 @@ sub vcl_recv { } # Remove all marketing get parameters to minimize the cache objects - if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|mc_[a-z]+|utm_[a-z]+)=") { - set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); + if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=") { + set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); set req.url = regsub(req.url, "[?|&]+$", ""); } diff --git a/app/code/Magento/PageCache/etc/varnish5.vcl b/app/code/Magento/PageCache/etc/varnish5.vcl index ea586858eff75..eac724ea7d0a5 100644 --- a/app/code/Magento/PageCache/etc/varnish5.vcl +++ b/app/code/Magento/PageCache/etc/varnish5.vcl @@ -93,8 +93,8 @@ sub vcl_recv { } # Remove all marketing get parameters to minimize the cache objects - if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|mc_[a-z]+|utm_[a-z]+)=") { - set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); + if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=") { + set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); set req.url = regsub(req.url, "[?|&]+$", ""); } From 3f1e3392a0227a03cfa86e7babd58b11dfbec3f8 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 8 Apr 2019 14:38:25 -0500 Subject: [PATCH 191/585] MC-4430: Convert ApplyCatalogPriceRulesTest to MFTF Fixed as per review comments --- ...ntSelectCustomOptionDropDownAndAssertPricesActionGroup.xml | 2 +- .../Test/Mftf/Section/StorefrontProductPageSection.xml | 2 +- .../ActionGroup/CatalogSelectCustomerGroupActionGroup.xml | 4 ++-- .../ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml | 4 ++-- ...pplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml | 2 +- .../ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup.xml index 13bbc3c1ac4f8..39793cb8f68de 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontSelectCustomOptionDropDownAndAssertPricesActionGroup" extends="AssertStorefrontProductPricesActionGroup"> <arguments> <argument name="customOption" type="string"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml index c82e26a0e5968..78818dd37a5d4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml @@ -24,6 +24,6 @@ <element name="orderTotal" type="input" selector=".grand.totals .amount .price"/> <element name="customOptionDropDown" type="select" selector="//*[@id='product-options-wrapper']//select[contains(@class, 'product-custom-option admin__control-select')]"/> <element name="qtyInputWithProduct" type="input" selector="//tr//strong[contains(.,'{{productName}}')]/../../td[@class='col qty']//input" parameterized="true"/> - <element name="customOptionRadio" type="input" selector="//span[@text='{{customOption}}']/../../input" parameterized="true"/> + <element name="customOptionRadio" type="input" selector="//span[contains(text(),'{{customOption}}')]/../../input" parameterized="true"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogSelectCustomerGroupActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogSelectCustomerGroupActionGroup.xml index 64cadc5be232e..da961abac304b 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogSelectCustomerGroupActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogSelectCustomerGroupActionGroup.xml @@ -10,8 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="CatalogSelectCustomerGroupActionGroup"> <arguments> - <argument name="customer" defaultValue="NOT LOGGED IN" type="entity"/> + <argument name="customerGroupName" defaultValue="NOT LOGGED IN" type="string"/> </arguments> - <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="{{customer}}" stepKey="selectCustomerGroup"/> + <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="{{customerGroupName}}" stepKey="selectCustomerGroup"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml index a4e2e1acf62c2..7b7953c1d9b06 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml @@ -27,8 +27,8 @@ <!-- Create Simple Product --> <createData entity="_defaultProduct" stepKey="createProduct1"> - <requiredEntity createDataKey="createCategory"/> - <field key="price">56.78</field> + <requiredEntity createDataKey="createCategory"/> + <field key="price">56.78</field> </createData> <!-- Update all products to have custom options --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml index 0aea543942976..e4af21cac6723 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml @@ -68,7 +68,7 @@ <!-- Select custom customer group --> <actionGroup ref="CatalogSelectCustomerGroupActionGroup" stepKey="selectCustomCustomerGroup"> - <argument name="customer" value="$customerGroup.code$"/> + <argument name="customerGroupName" value="$customerGroup.code$"/> </actionGroup> <!-- Save and apply the new catalog price rule --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml index 1f611ffd716aa..5b7e722c92a02 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml @@ -67,7 +67,7 @@ </after> <!-- 1. Begin creating a new catalog price rule --> <actionGroup ref="newCatalogPriceRuleByUIWithConditionIsCategory" stepKey="newCatalogPriceRuleByUIWithConditionIsCategory"> - <argument name ="categoryId" value="$createCategory.id$"/> + <argument name ="categoryId" value="$createCategory.id$"/> </actionGroup> <!-- Select not logged in customer group --> @@ -105,7 +105,7 @@ <argument name="productNumber" value="2"/> </actionGroup> - <!-- Check product 1 price on store front category page --> + <!-- Check product 2 price on store front category page --> <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct2Price"> <argument name="productInfo" value="$51.10"/> <argument name="productNumber" value="2"/> From 1575b4ac59dd14d43f0a03133b96bac471600c32 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Mon, 8 Apr 2019 15:24:12 -0500 Subject: [PATCH 192/585] GraphQL-514: Test coverage for tag cache generation - added test framework changes and api-functional tests for coverage --- .../TestFramework/TestCase/GraphQl/Client.php | 22 ++++++ .../TestCase/GraphQlAbstract.php | 23 ++++++ .../TestCase/HttpClient/CurlClient.php | 12 +++ .../GraphQl/PageCache/CacheTagTest.php | 77 +++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php index 5eea3be840ae5..5945124936c60 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php @@ -113,6 +113,28 @@ private function processResponse(string $response) return $responseArray['data']; } + /** + * Process the header information from response + * + * @param string $query + * @param array $variables + * @param string $operationName + * @param array $headers + * @return mixed + */ + public function getQueryResponseHeaders(string $query, array $variables = [], string $operationName = '', array $headers = []) + { + $url = $this->getEndpointUrl(); + $requestArray = [ + 'query' => $query, + 'variables' => empty($variables) ? $variables : null, + 'operationName' => empty($operationName) ? $operationName : null + ]; + + $responseHeader = $this->curlClient->getHttpHeaders($url, $requestArray, $headers); + return $responseHeader; + } + /** * Process errors * diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php index 8abd97b4b744d..810ebcbb098fd 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php @@ -77,6 +77,29 @@ public function graphQlMutation( ); } + /** + * Perform GraphQL query via GET and returns only the response headers + * + * @param string $query + * @param array $variables + * @param string $operationName + * @param array $headers + * @return mixed + */ + public function graphQlQueryForHttpHeaders( + string $query, + array $variables = [], + string $operationName = '', + array $headers = [] + ) { + return $response = $this->getGraphQlClient()->getQueryResponseHeaders( + $query, + $variables, + $operationName, + $this->composeHeaders($headers) + ); + } + /** * Compose headers * diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php index 787f207ef33e9..24f622da7055a 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php @@ -32,6 +32,18 @@ public function get($url, $data = [], $headers = []) return $resp["body"]; } + public function getHttpHeaders($url, $data = [], $headers = []) + { + if (!empty($data)) { + $url .= '?' . http_build_query($data); + } + + $curlOpts = []; + $curlOpts[CURLOPT_CUSTOMREQUEST] = \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET; + $resp = $this->invokeApi($url, $curlOpts, $headers); + return $resp["header"]; + } + /** * Perform HTTP DELETE request * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php new file mode 100644 index 0000000000000..0c9f489f91e3c --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\PageCache; + + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product; +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\App\State; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +class CacheTagTest extends GraphQlAbstract +{ + /** + * @var \Magento\Framework\App\State + */ + protected $state; + + /** + * Tests various use cases for built-in cache for graphql query + * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_url_key.php + */ + public function testCacheTagsAndCacheDebugHeaderFromResponse() + { + $productSku='simple2'; + $query + = <<<QUERY + { + products(filter: {sku: {eq: "{$productSku}"}}) + { + items { + id + name + sku + } + } + } +QUERY; + + /** cache-debug should be a MISS when product is queried for first time */ + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); + preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); + $this->assertEquals('MISS', rtrim($matchesMiss[1],"\r")); + + /** cache-debug should be a HIT for the second round */ + $responseHitHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); + preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHitHeaders, $matchesHit); + $this->assertEquals('HIT', rtrim($matchesHit[1],"\r")); + + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + /** @var Product $product */ + $product =$productRepository->get($productSku,false,null, true); + /** update the price attribute for the product in test */ + $product->setPrice(15); + $product->save(); + /** cache-debug header value should be a MISS after product attribute update */ + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); + preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); + $this->assertEquals('MISS', rtrim($matchesMiss[1],"\r")); + + /** checks if cache tags for products are correctly displayed in the response header */ + preg_match('/X-Magento-Tags: (.*?)\n/', $responseMissHeaders, $headerCacheTags); + $actualCacheTags = explode(',', rtrim($headerCacheTags[1],"\r")); + $expectedCacheTags=['cat_p','cat_p_' . $product->getId(),'FPC']; + foreach(array_keys($actualCacheTags) as $key){ + $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key] + ); + } + } +} From 32f2813ab8dca3d6d79e460392c1b24cbda0d89c Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Mon, 8 Apr 2019 21:48:00 +0100 Subject: [PATCH 193/585] magento/magento2#18541: Fixed static tests --- .../Test/Unit/Layout/Argument/Interpreter/ObjectTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php index 180888bcc1d3e..6e3ba94de507d 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php @@ -3,10 +3,15 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Framework\View\Test\Unit\Layout\Argument\Interpreter; use Magento\Framework\View\Layout\Argument\Interpreter\DataObject; +/** + * Tests layout argument interpreter data object. + */ class ObjectTest extends \PHPUnit\Framework\TestCase { const EXPECTED_CLASS = \Magento\Framework\View\Test\Unit\Layout\Argument\Interpreter\ObjectTest::class; From 8c4a6770308c7e78c889162a0048fd8afe5f05a0 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Mon, 8 Apr 2019 16:46:29 -0500 Subject: [PATCH 194/585] MC-4571: Convert CreateCustomerSegmentEntityWithCustomerConditionsPartOneTest to MFTF --- .../StorefrontCheckCartDiscountAndSummaryActionGroup.xml | 2 -- ...uteConditionWithSegmentForCartPriceRuleActionGroup.xml} | 7 ++++--- 2 files changed, 4 insertions(+), 5 deletions(-) rename app/code/Magento/SalesRule/Test/Mftf/ActionGroup/{SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup.xml => SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml} (93%) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml index b8a989ba2cf35..115fbc4993e58 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml @@ -11,11 +11,9 @@ <!-- Open the Minicart and check Summary --> <actionGroup name="StorefrontCheckCartDiscountAndSummaryActionGroup"> <arguments> - <argument name="product" type="entity"/> <argument name="total" type="string"/> <argument name="discount" type="string"/> </arguments> - <waitForPageLoad stepKey="waitForSummary"/> <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-${{discount}}" stepKey="assertDiscount"/> <see selector="{{CheckoutCartSummarySection.total}}" userInput="${{total}}" stepKey="assertTotal"/> </actionGroup> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml similarity index 93% rename from app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup.xml rename to app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml index 855da5228d493..1ae6b7a3e92f4 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml @@ -6,8 +6,9 @@ */ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"><!--Set condition for Customer Segment--> - <actionGroup name="SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!--Set condition for Customer Segment--> + <actionGroup name="SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup"> <arguments> <argument name="attributeName" type="string"/> <argument name="value" type="entity"/> @@ -35,7 +36,7 @@ <click selector="{{AdminMainActionsSection.saveAndContinue}}" stepKey="clickSaveButton"/> <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> </actionGroup> - <actionGroup name="SetCartAttributeConditionWhenMatchForCartPriceRuleActionGroup" extends="SetCartAttributeConditionWIthSegmentForCartPriceRuleActionGroup"> + <actionGroup name="SetCartAttributeConditionWhenMatchForCartPriceRuleActionGroup" extends="SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup"> <arguments> <argument name="operatorType" type="string" defaultValue="matches"/> </arguments> From 6e08072015973a368221c34c08c172aee77aeaa9 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 8 Apr 2019 16:47:12 -0500 Subject: [PATCH 195/585] Issue-230: adding varnish - fixing static plus composer --- .../Controller/HttpHeaderProcessor/CurrencyProcessor.php | 1 + .../Controller/{GraphQl/Plugin.php => Plugin/GraphQl.php} | 4 ++-- app/code/Magento/GraphQlCache/etc/graphql/di.xml | 2 +- composer.json | 1 + composer.lock | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) rename app/code/Magento/GraphQlCache/Controller/{GraphQl/Plugin.php => Plugin/GraphQl.php} (97%) diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php index 383955772d1bd..7aa5f032ad4d1 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php @@ -42,6 +42,7 @@ class CurrencyProcessor implements HttpHeaderProcessorInterface * @param StoreManagerInterface $storeManager * @param HttpContext $httpContext * @param SessionManagerInterface $session + * @param LoggerInterface $logger */ public function __construct( StoreManagerInterface $storeManager, diff --git a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php b/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php similarity index 97% rename from app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php rename to app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php index 8e849904a0adc..1979ef1e0d0c8 100644 --- a/app/code/Magento/GraphQlCache/Controller/GraphQl/Plugin.php +++ b/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\GraphQlCache\Controller\GraphQl; +namespace Magento\GraphQlCache\Controller\Plugin; use Magento\Framework\App\FrontControllerInterface; use Magento\Framework\App\RequestInterface; @@ -19,7 +19,7 @@ /** * Class Plugin */ -class Plugin +class GraphQl { /** * @var CacheableQuery diff --git a/app/code/Magento/GraphQlCache/etc/graphql/di.xml b/app/code/Magento/GraphQlCache/etc/graphql/di.xml index 8a5b6476c7afc..6636ebacf9e5c 100644 --- a/app/code/Magento/GraphQlCache/etc/graphql/di.xml +++ b/app/code/Magento/GraphQlCache/etc/graphql/di.xml @@ -7,7 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Framework\App\FrontControllerInterface"> - <plugin name="cache" type="Magento\GraphQlCache\Controller\GraphQl\Plugin"/> + <plugin name="graphql-dispatch-plugin" type="Magento\GraphQlCache\Controller\Plugin\GraphQl"/> <plugin name="front-controller-builtin-cache" type="Magento\PageCache\Model\App\FrontController\BuiltinPlugin"/> <plugin name="front-controller-varnish-cache" type="Magento\PageCache\Model\App\FrontController\VarnishPlugin"/> </type> diff --git a/composer.json b/composer.json index 525f3a21d9577..cff2d676038d7 100644 --- a/composer.json +++ b/composer.json @@ -159,6 +159,7 @@ "magento/module-google-analytics": "*", "magento/module-google-optimizer": "*", "magento/module-graph-ql": "*", + "magento/module-graph-ql-cache": "*", "magento/module-catalog-graph-ql": "*", "magento/module-catalog-url-rewrite-graph-ql": "*", "magento/module-configurable-product-graph-ql": "*", diff --git a/composer.lock b/composer.lock index 06ab71ee75970..5d9f7fbdf695c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c43d19692d25afef14dd42eb893eb4ca", + "content-hash": "597fe6a47b695221292482fead498d83", "packages": [ { "name": "braintree/braintree_php", From d62d2784d1a121e590c2224f2e3010dc2feca25c Mon Sep 17 00:00:00 2001 From: niravkrish <nirav.patel@krishtechnolabs.com> Date: Tue, 9 Apr 2019 12:10:12 +0530 Subject: [PATCH 196/585] Fixed - Admin Order Create Full tax summary calculation missing --- .../adminhtml/templates/order/create/totals/tax.phtml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml index 92139896273da..643146f7bb5cb 100755 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml @@ -33,7 +33,6 @@ $taxAmount = $block->getTotal()->getValue(); <?php $percent = $info['percent']; ?> <?php $amount = $info['amount']; ?> <?php $rates = $info['rates']; ?> - <?php $isFirst = 1; ?> <?php foreach ($rates as $rate): ?> <tr class="summary-details-<?= /* @escapeNotVerified */ $taxIter ?> summary-details<?php if ($isTop): echo ' summary-details-first'; endif; ?>" style="display:none;"> @@ -44,13 +43,10 @@ $taxAmount = $block->getTotal()->getValue(); <?php endif; ?> <br /> </td> - <?php if ($isFirst): ?> - <td style="<?= /* @escapeNotVerified */ $block->getTotal()->getStyle() ?>" class="admin__total-amount" rowspan="<?= count($rates) ?>"> - <?= /* @escapeNotVerified */ $block->formatPrice($amount) ?> - </td> - <?php endif; ?> + <td style="<?= /* @escapeNotVerified */ $block->getTotal()->getStyle() ?>" class="admin__total-amount"> + <?= /* @escapeNotVerified */ $block->formatPrice(($amount*(float)$rate['percent'])/$percent) ?> + </td> </tr> - <?php $isFirst = 0; ?> <?php $isTop = 0; ?> <?php endforeach; ?> <?php endforeach; ?> From 83cb9a054fe9908c9e22682b1d62353336363568 Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Tue, 9 Apr 2019 11:03:55 +0300 Subject: [PATCH 197/585] MAGETWO-98584: Google chart API used by Magento dashboard scheduled to be turned off --- .../Magento/Backend/Block/Dashboard/Graph.php | 79 +++++++++++-------- .../Controller/Adminhtml/DashboardTest.php | 8 ++ 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/app/code/Magento/Backend/Block/Dashboard/Graph.php b/app/code/Magento/Backend/Block/Dashboard/Graph.php index 71a6cf4e938f2..56e7ab6186ada 100644 --- a/app/code/Magento/Backend/Block/Dashboard/Graph.php +++ b/app/code/Magento/Backend/Block/Dashboard/Graph.php @@ -320,7 +320,8 @@ public function getChartUrl($directUrl = true) foreach ($this->getAllSeries() as $index => $serie) { $thisdataarray = $serie; - for ($j = 0; $j < sizeof($thisdataarray); $j++) { + $count = count($thisdataarray); + for ($j = 0; $j < $count; $j++) { $currentvalue = $thisdataarray[$j]; if (is_numeric($currentvalue)) { $ylocation = $yorigin + $currentvalue; @@ -341,45 +342,13 @@ public function getChartUrl($directUrl = true) $valueBuffer = []; - if (sizeof($this->_axisLabels) > 0) { + if (count($this->_axisLabels) > 0) { $params['chxt'] = implode(',', array_keys($this->_axisLabels)); $indexid = 0; foreach ($this->_axisLabels as $idx => $labels) { if ($idx == 'x') { - /** - * Format date - */ - foreach ($this->_axisLabels[$idx] as $_index => $_label) { - if ($_label != '') { - $period = new \DateTime($_label, new \DateTimeZone($timezoneLocal)); - switch ($this->getDataHelper()->getParam('period')) { - case '24h': - $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime( - $period->setTime($period->format('H'), 0, 0), - \IntlDateFormatter::NONE, - \IntlDateFormatter::SHORT - ); - break; - case '7d': - case '1m': - $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime( - $period, - \IntlDateFormatter::SHORT, - \IntlDateFormatter::NONE - ); - break; - case '1y': - case '2y': - $this->_axisLabels[$idx][$_index] = date('m/Y', strtotime($_label)); - break; - } - } else { - $this->_axisLabels[$idx][$_index] = ''; - } - } - + $this->formatAxisLabelDate($idx, $timezoneLocal); $tmpstring = implode('|', $this->_axisLabels[$idx]); - $valueBuffer[] = $indexid . ":|" . $tmpstring; } elseif ($idx == 'y') { $valueBuffer[] = $indexid . ":|" . implode('|', $yLabels); @@ -407,6 +376,46 @@ public function getChartUrl($directUrl = true) } } + /** + * Format dates for axis labels + * + * @param string $idx + * @param string $timezoneLocal + * + * @return void + */ + private function formatAxisLabelDate($idx, $timezoneLocal) + { + foreach ($this->_axisLabels[$idx] as $_index => $_label) { + if ($_label != '') { + $period = new \DateTime($_label, new \DateTimeZone($timezoneLocal)); + switch ($this->getDataHelper()->getParam('period')) { + case '24h': + $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime( + $period->setTime($period->format('H'), 0, 0), + \IntlDateFormatter::NONE, + \IntlDateFormatter::SHORT + ); + break; + case '7d': + case '1m': + $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime( + $period, + \IntlDateFormatter::SHORT, + \IntlDateFormatter::NONE + ); + break; + case '1y': + case '2y': + $this->_axisLabels[$idx][$_index] = date('m/Y', strtotime($_label)); + break; + } + } else { + $this->_axisLabels[$idx][$_index] = ''; + } + } + } + /** * Get rows data * diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php index 07af21505f180..8b96dbd09b543 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php @@ -19,8 +19,15 @@ public function testAjaxBlockAction() $this->assertContains('dashboard-diagram', $actual); } + /** + * Tests tunnelAction + * + * @throws \Exception + * @return void + */ public function testTunnelAction() { + // phpcs:disable Magento2.Functions.DiscouragedFunction $testUrl = \Magento\Backend\Block\Dashboard\Graph::API_URL . '?cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World'; $handle = curl_init(); curl_setopt($handle, CURLOPT_URL, $testUrl); @@ -34,6 +41,7 @@ public function testTunnelAction() curl_close($handle); throw $e; } + // phpcs:enable $gaData = [ 'cht' => 'lc', From 0de457220574931d82e11be83b4f565f38ab06cb Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 2 Apr 2019 16:26:53 +0300 Subject: [PATCH 198/585] magento/magento2#21869: Static test fix. --- .../Magento/Eav/Model/Entity/Collection/AbstractCollection.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 05c6d989fa130..b191f14bb7e60 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -264,7 +264,7 @@ public function setEntity($entity) $this->_entity = $this->_eavEntityFactory->create()->setType($entity); } else { throw new LocalizedException( - __('The "%1" entity supplied is invalid. Verify the entity and try again.', print_r($entity, 1)) + __('The entity supplied to collection is invalid. Verify the entity and try again.') ); } return $this; @@ -1165,7 +1165,6 @@ public function _loadEntities($printQuery = false, $logQuery = false) * @param bool $printQuery * @param bool $logQuery * @return $this - * @throws LocalizedException * @throws \Exception * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) From c0f2c2ad58ab0607a668a8e34f984f0b3f73dcc0 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Tue, 9 Apr 2019 11:15:54 +0300 Subject: [PATCH 199/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Added strict type declaration; --- app/code/Magento/Ups/Model/Carrier.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 9cb1fe615aa42..14b71e5f75db3 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Ups\Model; From 13d1f426de8c64c2059f00a50e02185eed5e0188 Mon Sep 17 00:00:00 2001 From: Davit_Zakharyan <davit_zakharyan@epam.com> Date: Tue, 9 Apr 2019 12:44:11 +0400 Subject: [PATCH 200/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Updated automated test script. --- .../Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml b/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml index 9a168f0bd6197..51db704a7abc7 100644 --- a/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml +++ b/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml @@ -31,7 +31,7 @@ <createData entity="ShippingMethodsUpsTypeSetDefault" stepKey="setShippingMethodsUpsTypeToDefault"/> <!-- Navigate to Stores -> Configuration -> Sales -> Shipping Methods Page --> <comment userInput="Navigate to Stores -> Configuration -> Sales -> Shipping Methods Page" stepKey="goToAdminShippingMethodsPage"/> - <amonPage url="{{AdminShippingMethodsConfigPage.url}}" stepKey="navigateToAdminShippingMethodsPage"/> + <amOnPage url="{{AdminShippingMethodsConfigPage.url}}" stepKey="navigateToAdminShippingMethodsPage"/> <waitForPageLoad stepKey="waitPageToLoad"/> <!-- Expand 'UPS' tab --> <comment userInput="Expand UPS tab" stepKey="expandUpsTab"/> From d061c5461a316a44b6cc9b7a48c35aaff98b9719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Me=CC=81ndez=20Calzada?= <gonzalo.mendez@interactiv4.com> Date: Tue, 9 Apr 2019 11:17:42 +0200 Subject: [PATCH 201/585] drop optional unused parameter --- .../Eav/Model/Entity/Attribute/Source/AbstractSource.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php index 0e547e0887c30..b291b7b28d5b7 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php @@ -171,14 +171,11 @@ public function toOptionArray() * Multibyte support strcasecmp function version * @param string $str1 * @param string $str2 - * @param null|string $encoding * @return int|\\lt */ - private function mbStrcasecmp($str1, $str2, $encoding = null) + private function mbStrcasecmp($str1, $str2) { - if (null === $encoding) { - $encoding = mb_internal_encoding(); - } + $encoding = mb_internal_encoding(); return strcmp( mb_strtoupper($str1, $encoding), mb_strtoupper($str2, $encoding) From 07a1570b147ac2cca6bb97e748571304a5ab7b96 Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Tue, 9 Apr 2019 12:42:34 +0300 Subject: [PATCH 202/585] MAGETWO-98584: Google chart API used by Magento dashboard scheduled to be turned off --- app/code/Magento/Backend/Block/Dashboard/Graph.php | 2 ++ .../testsuite/Magento/Backend/Block/Dashboard/GraphTest.php | 2 ++ .../Magento/Backend/Controller/Adminhtml/DashboardTest.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/app/code/Magento/Backend/Block/Dashboard/Graph.php b/app/code/Magento/Backend/Block/Dashboard/Graph.php index 56e7ab6186ada..f57b03fdbfa0b 100644 --- a/app/code/Magento/Backend/Block/Dashboard/Graph.php +++ b/app/code/Magento/Backend/Block/Dashboard/Graph.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Backend\Block\Dashboard; /** diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php b/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php index 215fd85d33167..497deb2c99110 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Backend\Block\Dashboard; /** diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php index 8b96dbd09b543..0eb98379b4571 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Backend\Controller\Adminhtml; /** From 4aa6b278e7273066bfceab39dce3f79b4a7085d1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Tue, 9 Apr 2019 14:36:37 +0300 Subject: [PATCH 203/585] MC-13479: Persistent Data for Guest Customer with physical quote --- ...tCartEstimateShippingAndTaxActionGroup.xml | 20 +++++ ...tCartShippingMethodSelectedActionGroup.xml | 19 ++++ ...EstimateShippingInformationActionGroup.xml | 20 +++++ ...ckoutShippingMethodSelectedActionGroup.xml | 18 ++++ ...rontAssertGuestShippingInfoActionGroup.xml | 28 ++++++ ...ShippingMethodPresentInCartActionGroup.xml | 18 ++++ ...tCartEstimateShippingAndTaxActionGroup.xml | 25 ++++++ ...efrontFillGuestShippingInfoActionGroup.xml | 25 ++++++ .../Test/Mftf/Data/EstimateAndTaxData.xml | 16 ++++ .../Section/CheckoutCartSummarySection.xml | 3 + .../CheckoutShippingGuestInfoSection.xml | 4 + .../CheckoutShippingMethodsSection.xml | 1 + ...aForGuestCustomerWithPhysicalQuoteTest.xml | 90 +++++++++++++++++++ .../Test/Mftf/Data/NewCustomerData.xml | 26 ++++++ 14 files changed, 313 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartEstimateShippingAndTaxActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartShippingMethodSelectedActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutEstimateShippingInformationActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutShippingMethodSelectedActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertGuestShippingInfoActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingMethodPresentInCartActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCartEstimateShippingAndTaxActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillGuestShippingInfoActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Data/EstimateAndTaxData.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontPersistentDataForGuestCustomerWithPhysicalQuoteTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartEstimateShippingAndTaxActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartEstimateShippingAndTaxActionGroup.xml new file mode 100644 index 0000000000000..0d6f34098c048 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartEstimateShippingAndTaxActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Assert Estimate Shipping and Tax Data in Cart --> + <actionGroup name="StorefrontAssertCartEstimateShippingAndTaxActionGroup"> + <arguments> + <argument name="customerData" defaultValue="Simple_US_CA_Customer_For_Shipment"/> + </arguments> + <seeInField selector="{{CheckoutCartSummarySection.country}}" userInput="{{customerData.country}}" stepKey="assertCountryFieldInCartEstimateShippingAndTaxSection"/> + <seeInField selector="{{CheckoutCartSummarySection.stateProvinceInput}}" userInput="{{customerData.region}}" stepKey="assertStateProvinceInCartEstimateShippingAndTaxSection"/> + <seeInField selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{customerData.postcode}}" stepKey="assertZipPostalCodeInCartEstimateShippingAndTaxSection"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartShippingMethodSelectedActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartShippingMethodSelectedActionGroup.xml new file mode 100644 index 0000000000000..4061f97821cd0 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartShippingMethodSelectedActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Assert Shipping Method Is Checked on Cart --> + <actionGroup name="StorefrontAssertCartShippingMethodSelectedActionGroup"> + <arguments> + <argument name="carrierCode" type="string"/> + <argument name="methodCode" type="string"/> + </arguments> + <seeCheckboxIsChecked selector="{{CheckoutCartSummarySection.shippingMethodElementId(carrierCode, methodCode)}}" stepKey="assertShippingMethodIsChecked"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutEstimateShippingInformationActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutEstimateShippingInformationActionGroup.xml new file mode 100644 index 0000000000000..82d7e12105b8c --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutEstimateShippingInformationActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Assert Estimate Shipping and Tax Data on Checkout --> + <actionGroup name="StorefrontAssertCheckoutEstimateShippingInformationActionGroup"> + <arguments> + <argument name="customerData" defaultValue="Simple_US_CA_Customer_For_Shipment"/> + </arguments> + <seeInField selector="{{CheckoutShippingGuestInfoSection.country}}" userInput="{{customerData.country}}" stepKey="assertCountryField"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.region}}" userInput="{{customerData.region}}" stepKey="assertStateProvinceField"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.postcode}}" userInput="{{customerData.postcode}}" stepKey="assertZipPostalCodeField"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutShippingMethodSelectedActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutShippingMethodSelectedActionGroup.xml new file mode 100644 index 0000000000000..33f2852f1f0ad --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutShippingMethodSelectedActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Assert Shipping Method by Name Is Checked on Checkout --> + <actionGroup name="StorefrontAssertCheckoutShippingMethodSelectedActionGroup"> + <arguments> + <argument name="shippingMethod"/> + </arguments> + <seeCheckboxIsChecked selector="{{CheckoutShippingMethodsSection.checkShippingMethodByName('shippingMethod')}}" stepKey="assertShippingMethodByNameIsChecked"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertGuestShippingInfoActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertGuestShippingInfoActionGroup.xml new file mode 100644 index 0000000000000..02c362bf34058 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertGuestShippingInfoActionGroup.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Assert guest shipping info on checkout --> + <actionGroup name="StorefrontAssertGuestShippingInfoActionGroup"> + <arguments> + <argument name="customerData" defaultValue="Simple_UK_Customer_For_Shipment"/> + </arguments> + <seeInField selector="{{CheckoutShippingGuestInfoSection.email}}" userInput="{{customerData.email}}" stepKey="assertEmailAddress"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.firstName}}" userInput="{{customerData.firstName}}" stepKey="assertFirstName"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.lastName}}" userInput="{{customerData.lastName}}" stepKey="assertLastName"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.company}}" userInput="{{customerData.company}}" stepKey="assertCompany"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.street}}" userInput="{{customerData.streetFirstLine}}" stepKey="assertAddressFirstLine"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.street2}}" userInput="{{customerData.streetSecondLine}}" stepKey="assertAddressSecondLine"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.city}}" userInput="{{customerData.city}}" stepKey="assertCity"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.country}}" userInput="{{customerData.country}}" stepKey="assertCountry"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.regionInput}}" userInput="{{customerData.region}}" stepKey="assertStateProvince"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.postcode}}" userInput="{{customerData.postcode}}" stepKey="assertZipPostalCode"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.telephone}}" userInput="{{customerData.telephone}}" stepKey="assertPhoneNumber"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingMethodPresentInCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingMethodPresentInCartActionGroup.xml new file mode 100644 index 0000000000000..3d8530ae83704 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingMethodPresentInCartActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Assert shipping method is present in cart --> + <actionGroup name="StorefrontAssertShippingMethodPresentInCartActionGroup"> + <arguments> + <argument name="shippingMethod" type="string"/> + </arguments> + <see selector="{{CheckoutCartSummarySection.shippingMethodLabel}}" userInput="{{shippingMethod}}" stepKey="assertShippingMethodIsPresentInCart"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCartEstimateShippingAndTaxActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCartEstimateShippingAndTaxActionGroup.xml new file mode 100644 index 0000000000000..4176859f99f70 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCartEstimateShippingAndTaxActionGroup.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Fill Estimate Shipping and Tax fields --> + <actionGroup name="StorefrontCartEstimateShippingAndTaxActionGroup"> + <arguments> + <argument name="estimateAddress" defaultValue="EstimateAddressCalifornia"/> + </arguments> + <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.country}}" visible="false" stepKey="clickOnEstimateShippingAndTax"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.country}}" stepKey="waitForCountrySelectorIsVisible"/> + <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="{{estimateAddress.country}}" stepKey="selectCountry"/> + <waitForLoadingMaskToDisappear stepKey="waitForCountryLoadingMaskDisappear"/> + <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{estimateAddress.state}}" stepKey="selectStateProvince"/> + <waitForLoadingMaskToDisappear stepKey="waitForStateLoadingMaskDisappear"/> + <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{estimateAddress.zipCode}}" stepKey="fillZipPostalCodeField"/> + <waitForLoadingMaskToDisappear stepKey="waitForZipLoadingMaskDisappear"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillGuestShippingInfoActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillGuestShippingInfoActionGroup.xml new file mode 100644 index 0000000000000..e7669d62c79a0 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillGuestShippingInfoActionGroup.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Fill data in checkout shipping section --> + <actionGroup name="StorefrontFillGuestShippingInfoActionGroup"> + <arguments> + <argument name="customerData" defaultValue="Simple_UK_Customer_For_Shipment"/> + </arguments> + <fillField selector="{{CheckoutShippingGuestInfoSection.email}}" userInput="{{customerData.email}}" stepKey="fillEmailAddressField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.firstName}}" userInput="{{customerData.firstName}}" stepKey="fillFirstNameField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.lastName}}" userInput="{{customerData.lastName}}" stepKey="fillLastNameField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.company}}" userInput="{{customerData.company}}" stepKey="fillCompanyField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.street}}" userInput="{{customerData.streetFirstLine}}" stepKey="fillStreetAddressFirstLineField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.street2}}" userInput="{{customerData.streetSecondLine}}" stepKey="fillStreetAddressSecondLineField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.city}}" userInput="{{customerData.city}}" stepKey="fillCityField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.telephone}}" userInput="{{customerData.telephone}}" stepKey="fillPhoneNumberField"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Data/EstimateAndTaxData.xml b/app/code/Magento/Checkout/Test/Mftf/Data/EstimateAndTaxData.xml new file mode 100644 index 0000000000000..36dea5a521a04 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Data/EstimateAndTaxData.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="EstimateAddressCalifornia"> + <data key="country">United States</data> + <data key="state">California</data> + <data key="zipCode">90240</data> + </entity> +</entities> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml index 8d14a9a561900..3100fae3b119b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml @@ -20,9 +20,12 @@ <element name="shippingHeading" type="button" selector="#block-shipping-heading"/> <element name="postcode" type="input" selector="input[name='postcode']" timeout="10"/> <element name="stateProvince" type="select" selector="select[name='region_id']" timeout="10"/> + <element name="stateProvinceInput" type="input" selector="input[name='region']"/> <element name="country" type="select" selector="select[name='country_id']" timeout="10"/> <element name="countryParameterized" type="select" selector="select[name='country_id'] > option:nth-child({{var}})" timeout="10" parameterized="true"/> <element name="estimateShippingAndTax" type="text" selector="#block-shipping-heading" timeout="5"/> <element name="flatRateShippingMethod" type="input" selector="#s_method_flatrate_flatrate" timeout="30"/> + <element name="shippingMethodLabel" type="text" selector="#co-shipping-method-form dl dt span"/> + <element name="shippingMethodElementId" type="radio" selector="#s_method_{{carrierCode}}_{{methodCode}}" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml index 6838824400b96..c97a8f291e941 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml @@ -13,9 +13,13 @@ <element name="firstName" type="input" selector="input[name=firstname]"/> <element name="lastName" type="input" selector="input[name=lastname]"/> <element name="street" type="input" selector="input[name='street[0]']"/> + <element name="street2" type="input" selector="input[name='street[1]']"/> <element name="city" type="input" selector="input[name=city]"/> <element name="region" type="select" selector="select[name=region_id]"/> + <element name="regionInput" type="input" selector="input[name=region]"/> <element name="postcode" type="input" selector="input[name=postcode]"/> + <element name="country" type="select" selector="select[name=country_id]"/> + <element name="company" type="input" selector="input[name=company]"/> <element name="telephone" type="input" selector="input[name=telephone]"/> <element name="next" type="button" selector="button.button.action.continue.primary" timeout="30"/> <element name="firstShippingMethod" type="radio" selector=".row:nth-of-type(1) .col-method .radio"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml index ab4b59fd67d03..77d903eab3934 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml @@ -17,5 +17,6 @@ <element name="shippingMethodRowByName" type="text" selector="//div[@id='checkout-shipping-method-load']//td[contains(., '{{var1}}')]/.." parameterized="true"/> <element name="shipHereButton" type="button" selector="//div/following-sibling::div/button[contains(@class, 'action-select-shipping-item')]"/> <element name="shippingMethodLoader" type="button" selector="//div[contains(@class, 'checkout-shipping-method')]/following-sibling::div[contains(@class, 'loading-mask')]"/> + <element name="freeShippingShippingMethod" type="input" selector="#s_method_freeshipping_freeshipping" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontPersistentDataForGuestCustomerWithPhysicalQuoteTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontPersistentDataForGuestCustomerWithPhysicalQuoteTest.xml new file mode 100644 index 0000000000000..20ff67a076e1e --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontPersistentDataForGuestCustomerWithPhysicalQuoteTest.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontPersistentDataForGuestCustomerWithPhysicalQuoteTest"> + <annotations> + <features value="Checkout"/> + <stories value="Checkout via Guest Checkout"/> + <title value="Persistent Data for Guest Customer with physical quote"/> + <description value="One can use Persistent Data for Guest Customer with physical quote"/> + <severity value="MAJOR"/> + <testCaseId value="MC-13479"/> + <group value="checkout"/> + </annotations> + <before> + <createData entity="SimpleProduct2" stepKey="createProduct"> + <field key="price">10</field> + </createData> + <createData entity="FreeShippinMethodConfig" stepKey="enableFreeShipping"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefront"/> + <executeJS function="window.localStorage.clear();" stepKey="clearLocalStorage"/> + </before> + <after> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <createData entity="FreeShippinMethodDefault" stepKey="disableFreeShipping"/> + </after> + <!-- 1. Add simple product to cart and go to checkout--> + <actionGroup ref="AddSimpleProductToCart" stepKey="addSimpleProductToCart"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + <!-- 2. Go to Shopping Cart --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCheckoutCartIndexPage"/> + <!-- 3. Open "Estimate Shipping and Tax" section and input data --> + <actionGroup ref="StorefrontCartEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxSection"/> + <actionGroup ref="StorefrontAssertShippingMethodPresentInCartActionGroup" stepKey="assertShippingMethodFlatRateIsPresentInCart"> + <argument name="shippingMethod" value="Flat Rate"/> + </actionGroup> + <actionGroup ref="StorefrontAssertShippingMethodPresentInCartActionGroup" stepKey="assertShippingMethodFreeShippingIsPresentInCart"> + <argument name="shippingMethod" value="Free Shipping"/> + </actionGroup> + <!-- 4. Select Flat Rate as shipping --> + <checkOption selector="{{CheckoutCartSummarySection.flatRateShippingMethod}}" stepKey="selectFlatRateShippingMethod"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappearAfterFlatRateSelection"/> + <see selector="{{CheckoutCartSummarySection.total}}" userInput="15" stepKey="assertOrderTotalField"/> + <!-- 5. Refresh browser page (F5) --> + <reloadPage stepKey="reloadPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <actionGroup ref="StorefrontAssertCartEstimateShippingAndTaxActionGroup" stepKey="assertCartEstimateShippingAndTaxAfterPageReload"/> + <actionGroup ref="StorefrontAssertCartShippingMethodSelectedActionGroup" stepKey="assertFlatRateShippingMethodIsChecked"> + <argument name="carrierCode" value="flatrate"/> + <argument name="methodCode" value="flatrate"/> + </actionGroup> + <!-- 6. Go to Checkout --> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="clickProceedToCheckout"/> + <actionGroup ref="StorefrontAssertCheckoutEstimateShippingInformationActionGroup" stepKey="assertCheckoutEstimateShippingInformationAfterGoingToCheckout"/> + <actionGroup ref="StorefrontAssertCheckoutShippingMethodSelectedActionGroup" stepKey="assertFlatRateShippingMethodIsCheckedAfterGoingToCheckout"> + <argument name="shippingMethod" value="Flat Rate"/> + </actionGroup> + <!-- 7. Change persisted data --> + <selectOption selector="{{CheckoutShippingGuestInfoSection.country}}" userInput="United Kingdom" stepKey="changeCountryField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.regionInput}}" userInput="" stepKey="changeStateProvinceField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.postcode}}" userInput="KW1 7NQ" stepKey="changeZipPostalCodeField"/> + <!-- 8. Change shipping rate, select Free Shipping --> + <checkOption selector="{{CheckoutShippingMethodsSection.checkShippingMethodByName('Free Shipping')}}" stepKey="checkFreeShippingAsShippingMethod"/> + <!-- 9. Fill other fields --> + <actionGroup ref="StorefrontFillGuestShippingInfoActionGroup" stepKey="fillOtherFieldsInCheckoutShippingSection"/> + <!-- 10. Refresh browser page(F5) --> + <reloadPage stepKey="reloadCheckoutPage"/> + <waitForPageLoad stepKey="waitForCheckoutPageLoad"/> + <actionGroup ref="StorefrontAssertGuestShippingInfoActionGroup" stepKey="assertGuestShippingPersistedInfoAfterReloadingCheckoutShippingPage"/> + <actionGroup ref="StorefrontAssertCheckoutShippingMethodSelectedActionGroup" stepKey="assertFreeShippingShippingMethodIsChecked"> + <argument name="shippingMethod" value="Free Shipping"/> + </actionGroup> + <!-- 11. Go back to the shopping cart --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCheckoutCartIndexPage1"/> + <actionGroup ref="StorefrontAssertCartEstimateShippingAndTaxActionGroup" stepKey="assertCartEstimateShippingAndTaxAfterGoingBackToShoppingCart"> + <argument name="customerData" value="Simple_UK_Customer_For_Shipment"/> + </actionGroup> + <actionGroup ref="StorefrontAssertCartShippingMethodSelectedActionGroup" stepKey="assertFreeShippingShippingMethodIsCheckedAfterGoingBackToShoppingCart"> + <argument name="carrierCode" value="freeshipping"/> + <argument name="methodCode" value="freeshipping"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/NewCustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/NewCustomerData.xml index cdd117c2a0b12..347a04251f9cd 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/NewCustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/NewCustomerData.xml @@ -20,4 +20,30 @@ <data key="PhoneNumber">9999</data> <data key="Country">Armenia</data> </entity> + <entity name="Simple_UK_Customer_For_Shipment" type="customer"> + <data key="firstName">John</data> + <data key="lastName">Doe</data> + <data key="email">johndoe@example.com</data> + <data key="company">Test Company</data> + <data key="streetFirstLine">39 St Maurices Road</data> + <data key="streetSecondLine">ap. 654</data> + <data key="city">PULDAGON</data> + <data key="telephone">077 5866 0667</data> + <data key="country">United Kingdom</data> + <data key="region"> </data> + <data key="postcode">KW1 7NQ</data> + </entity> + <entity name="Simple_US_CA_Customer_For_Shipment" type="customer"> + <data key="firstName">John</data> + <data key="lastName">Doe</data> + <data key="email">johndoeusca@example.com</data> + <data key="company">Magento</data> + <data key="streetFirstLine">123 Alphabet Drive</data> + <data key="streetSecondLine">ap. 350</data> + <data key="city">Los Angeles</data> + <data key="telephone">555-55-555-55</data> + <data key="country">United States</data> + <data key="region">California</data> + <data key="postcode">90240</data> + </entity> </entities> From cc5c711b316c072d72a7174dbd8bb2dff03b67a0 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Tue, 9 Apr 2019 17:41:54 +0530 Subject: [PATCH 204/585] Fixed wrong url redirect when edit product review from product view page (type casting to int) --- app/code/Magento/Review/Controller/Adminhtml/Product/Save.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php index 9c85ae7db22d9..57b1e538ddb6b 100644 --- a/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php +++ b/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php @@ -73,7 +73,7 @@ public function execute() } else { $resultRedirect->setPath('*/*/'); } - $productId = $this->getRequest()->getParam('productId'); + $productId = (int)$this->getRequest()->getParam('productId'); if ($productId) { $resultRedirect->setPath("catalog/product/edit/id/$productId"); } From b159dfb6004281991de5ee3f80936d69e65fe5ed Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 9 Apr 2019 15:54:38 +0300 Subject: [PATCH 205/585] magento/magento2#20772: MTF test fix. --- .../AssertAccessTokensErrorRevokeMessage.php | 46 ------------------- .../AssertAccessTokensSuccessfullyRevoked.php | 45 ++++++++++++++++++ ...lAccessTokensForAdminWithoutTokensTest.xml | 2 +- 3 files changed, 46 insertions(+), 47 deletions(-) delete mode 100644 dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php create mode 100644 dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensSuccessfullyRevoked.php diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php deleted file mode 100644 index b1a64c7c7e713..0000000000000 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\User\Test\Constraint; - -use Magento\User\Test\Page\Adminhtml\UserEdit; -use Magento\Mtf\Constraint\AbstractConstraint; - -/** - * Class AssertAccessTokensErrorRevokeMessage - * Assert that error message appears after click on 'Force Sing-In' button for user without tokens. - */ -class AssertAccessTokensErrorRevokeMessage extends AbstractConstraint -{ - /** - * User revoke tokens error message. - */ - const ERROR_MESSAGE = 'This user has no tokens.'; - - /** - * Assert that error message appears after click on 'Force Sing-In' button for user without tokens. - * - * @param UserEdit $userEdit - * @return void - */ - public function processAssert(UserEdit $userEdit) - { - \PHPUnit\Framework\Assert::assertEquals( - self::ERROR_MESSAGE, - $userEdit->getMessagesBlock()->getErrorMessage() - ); - } - - /** - * Return string representation of object - * - * @return string - */ - public function toString() - { - return self::ERROR_MESSAGE . ' error message is present on UserEdit page.'; - } -} diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensSuccessfullyRevoked.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensSuccessfullyRevoked.php new file mode 100644 index 0000000000000..b2e52f6a15a10 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensSuccessfullyRevoked.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\User\Test\Constraint; + +use Magento\User\Test\Page\Adminhtml\UserEdit; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Assert that success message appears after click on 'Force Sing-In' button. + */ +class AssertAccessTokensSuccessfullyRevoked extends AbstractConstraint +{ + /** + * User revoke tokens success message. + */ + const SUCCESS_MESSAGE = 'You have revoked the user\'s tokens.'; + + /** + * Assert that success message appears after click on 'Force Sing-In' button. + * + * @param UserEdit $userEdit + * @return void + */ + public function processAssert(UserEdit $userEdit): void + { + \PHPUnit\Framework\Assert::assertEquals( + self::SUCCESS_MESSAGE, + $userEdit->getMessagesBlock()->getSuccessMessage() + ); + } + + /** + * Return string representation of object + * + * @return string + */ + public function toString() + { + return self::SUCCESS_MESSAGE . ' message is present on UserEdit page.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/RevokeAllAccessTokensForAdminWithoutTokensTest.xml b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/RevokeAllAccessTokensForAdminWithoutTokensTest.xml index e5fcba9b72c25..afdb72d8c561e 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/RevokeAllAccessTokensForAdminWithoutTokensTest.xml +++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/RevokeAllAccessTokensForAdminWithoutTokensTest.xml @@ -9,7 +9,7 @@ <testCase name="Magento\User\Test\TestCase\RevokeAllAccessTokensForAdminWithoutTokensTest" summary="Revoke All Access Tokens for Admin without Tokens" ticketId="MAGETWO-29675"> <variation name="RevokeAllAccessTokensForAdminWithoutTokensTestVariation1"> <data name="user/dataset" xsi:type="string">custom_admin</data> - <constraint name="Magento\User\Test\Constraint\AssertAccessTokensErrorRevokeMessage" /> + <constraint name="Magento\User\Test\Constraint\AssertAccessTokensSuccessfullyRevoked" /> </variation> </testCase> </config> From 8d114560f9ed103cfea3f0712419f8bb698ed20a Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Tue, 9 Apr 2019 08:14:33 -0500 Subject: [PATCH 206/585] MAGETWO-99091: Name of categories in the Category tree on Product Edit page is not displayed according to the selected store view scope --- .../Product/Form/Modifier/CategoriesTest.php | 34 -------- .../Product/Form/Modifier/Categories.php | 78 +++++++++++++++---- 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php index cd6565f32ed18..a2d81854607a0 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php @@ -154,38 +154,4 @@ public function modifyMetaLockedDataProvider() { return [[true], [false]]; } - - public function testModifyMetaWithCaching() - { - $this->arrayManagerMock->expects($this->exactly(2)) - ->method('findPath') - ->willReturn(true); - $cacheManager = $this->getMockBuilder(CacheInterface::class) - ->getMockForAbstractClass(); - $cacheManager->expects($this->once()) - ->method('load') - ->with(Categories::CATEGORY_TREE_ID . '_'); - $cacheManager->expects($this->once()) - ->method('save'); - - $modifier = $this->createModel(); - $cacheContextProperty = new \ReflectionProperty( - Categories::class, - 'cacheManager' - ); - $cacheContextProperty->setAccessible(true); - $cacheContextProperty->setValue($modifier, $cacheManager); - - $groupCode = 'test_group_code'; - $meta = [ - $groupCode => [ - 'children' => [ - 'category_ids' => [ - 'sortOrder' => 10, - ], - ], - ], - ]; - $modifier->modifyMeta($meta); - } } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php index 681435851fbde..8dc4b8100345e 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php @@ -11,6 +11,7 @@ use Magento\Framework\App\CacheInterface; use Magento\Framework\DB\Helper as DbHelper; use Magento\Catalog\Model\Category as CategoryModel; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\UrlInterface; use Magento\Framework\Stdlib\ArrayManager; @@ -202,6 +203,7 @@ protected function createNewCategoryModal(array $meta) * * @param array $meta * @return array + * @throws LocalizedException * @since 101.0.0 */ protected function customizeCategoriesField(array $meta) @@ -306,20 +308,64 @@ protected function customizeCategoriesField(array $meta) * * @param string|null $filter * @return array + * @throws LocalizedException * @since 101.0.0 */ protected function getCategoriesTree($filter = null) { - $categoryTree = $this->getCacheManager()->load(self::CATEGORY_TREE_ID . '_' . $filter); - if ($categoryTree) { - return $this->serializer->unserialize($categoryTree); + $storeId = $this->locator->getStore()->getId(); + + $cachedCategoriesTree = $this->getCacheManager() + ->load($this->getCategoriesTreeCacheId($storeId, (string) $filter)); + if (!empty($cachedCategoriesTree)) { + return $this->serializer->unserialize($cachedCategoriesTree); } - $storeId = $this->locator->getStore()->getId(); + $categoriesTree = $this->retrieveCategoriesTree( + $storeId, + $this->retrieveShownCategoriesIds($storeId, (string) $filter) + ); + + $this->getCacheManager()->save( + $this->serializer->serialize($categoriesTree), + $this->getCategoriesTreeCacheId($storeId, (string) $filter), + [ + \Magento\Catalog\Model\Category::CACHE_TAG, + \Magento\Framework\App\Cache\Type\Block::CACHE_TAG + ] + ); + + return $categoriesTree; + } + + /** + * Get cache id for categories tree. + * + * @param int $storeId + * @param string $filter + * @return string + */ + private function getCategoriesTreeCacheId($storeId, $filter = '') + { + return self::CATEGORY_TREE_ID + . '_' . (string) $storeId + . '_' . $filter; + } + + /** + * Retrieve filtered list of categories id. + * + * @param int $storeId + * @param string $filter + * @return array + * @throws LocalizedException + */ + private function retrieveShownCategoriesIds($storeId, $filter = '') + { /* @var $matchingNamesCollection \Magento\Catalog\Model\ResourceModel\Category\Collection */ $matchingNamesCollection = $this->categoryCollectionFactory->create(); - if ($filter !== null) { + if (!empty($filter)) { $matchingNamesCollection->addAttributeToFilter( 'name', ['like' => $this->dbHelper->addLikeEscape($filter, ['position' => 'any'])] @@ -339,6 +385,19 @@ protected function getCategoriesTree($filter = null) } } + return $shownCategoriesIds; + } + + /** + * Retrieve tree of categories with attributes. + * + * @param int $storeId + * @param array $shownCategoriesIds + * @return array + * @throws LocalizedException + */ + private function retrieveCategoriesTree($storeId, array $shownCategoriesIds = []) + { /* @var $collection \Magento\Catalog\Model\ResourceModel\Category\Collection */ $collection = $this->categoryCollectionFactory->create(); @@ -365,15 +424,6 @@ protected function getCategoriesTree($filter = null) $categoryById[$category->getParentId()]['optgroup'][] = &$categoryById[$category->getId()]; } - $this->getCacheManager()->save( - $this->serializer->serialize($categoryById[CategoryModel::TREE_ROOT_ID]['optgroup']), - self::CATEGORY_TREE_ID . '_' . $filter, - [ - \Magento\Catalog\Model\Category::CACHE_TAG, - \Magento\Framework\App\Cache\Type\Block::CACHE_TAG - ] - ); - return $categoryById[CategoryModel::TREE_ROOT_ID]['optgroup']; } } From 4921f459324328f9b04916f1722e762f98466f5c Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 9 Apr 2019 09:05:50 -0500 Subject: [PATCH 207/585] MAGETWO-93628: Shopping cart is emptied after reset password procedure --- app/code/Magento/Customer/Model/AccountManagement.php | 6 +++++- .../Customer/Test/Unit/Model/AccountManagementTest.php | 4 +--- lib/internal/Magento/Framework/Session/SessionManager.php | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 0440eb161e9e0..1806ea05f2fea 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -702,7 +702,11 @@ public function resetPassword($email, $resetToken, $newPassword) $customerSecure->setRpTokenCreatedAt(null); $customerSecure->setPasswordHash($this->createPasswordHash($newPassword)); $this->destroyCustomerSessions($customer->getId()); - $this->sessionManager->destroy(['send_expire_cookie' => false]); + if ($this->sessionManager->isSessionExists()) { + //delete old session and move data to the new session + //use this instead of $this->sessionManager->regenerateId because last one doesn't delete old session + session_regenerate_id(true); + } $this->customerRepository->save($customer); return true; diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 24a96a929a067..209a9b077a307 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1607,9 +1607,7 @@ function ($string) { $this->customerSecure->expects($this->once())->method('setRpTokenCreatedAt')->with(null); $this->customerSecure->expects($this->any())->method('setPasswordHash')->willReturn(null); - $this->sessionManager->expects($this->once()) - ->method('destroy') - ->with(['send_expire_cookie' => false]); + $this->sessionManager->method('isSessionExists')->willReturn(false); $this->sessionManager->expects($this->atLeastOnce())->method('getSessionId'); $visitor = $this->getMockBuilder(\Magento\Customer\Model\Visitor::class) ->disableOriginalConstructor() diff --git a/lib/internal/Magento/Framework/Session/SessionManager.php b/lib/internal/Magento/Framework/Session/SessionManager.php index b306b879b7127..c7d201676b228 100644 --- a/lib/internal/Magento/Framework/Session/SessionManager.php +++ b/lib/internal/Magento/Framework/Session/SessionManager.php @@ -353,6 +353,7 @@ public function destroy(array $options = null) } session_regenerate_id(true); + session_destroy(); if ($options['send_expire_cookie']) { $this->expireSessionCookie(); } From 52f6df2a7e73503f0eebd7898f6bc6f80dee78c4 Mon Sep 17 00:00:00 2001 From: dimonovp <dimonovp@gmail.com> Date: Tue, 9 Apr 2019 17:37:53 +0300 Subject: [PATCH 208/585] MC-12180: Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie --- .../CatalogRecentlyProductsConfigData.xml | 25 +++ .../catalog_recently_products-meta.xml | 20 +++ ...listIsPersistedUnderLongTermCookieTest.xml | 169 ++++++++++++++++++ .../AdminCreateWidgetActionGroup.xml | 6 + .../Widget/Test/Mftf/Data/WidgetsData.xml | 20 +++ .../Mftf/Section/AdminNewWidgetSection.xml | 2 + .../Mftf/Section/StorefrontWidgetsSection.xml | 3 + 7 files changed, 245 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Data/CatalogRecentlyProductsConfigData.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml create mode 100644 app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/CatalogRecentlyProductsConfigData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/CatalogRecentlyProductsConfigData.xml new file mode 100644 index 0000000000000..d1e469deaebba --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/CatalogRecentlyProductsConfigData.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="EnableSynchronizeWidgetProductsWithBackendStorage" type="catalog_recently_products"> + <requiredEntity type="synchronize_with_backend">EnableCatalogRecentlyProductsSynchronize</requiredEntity> + </entity> + + <entity name="EnableCatalogRecentlyProductsSynchronize" type="synchronize_with_backend"> + <data key="value">1</data> + </entity> + + <entity name="DisableSynchronizeWidgetProductsWithBackendStorage" type="catalog_recently_products"> + <requiredEntity type="synchronize_with_backend">DefaultCatalogRecentlyProductsSynchronize</requiredEntity> + </entity> + + <entity name="DefaultCatalogRecentlyProductsSynchronize" type="synchronize_with_backend"> + <data key="value">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml b/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml new file mode 100644 index 0000000000000..dad4f5420d461 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> + <operation name="CatalogRecentlyProductsConfiguration" dataType="catalog_recently_products" type="create" auth="adminFormKey" url="/admin/system_config/save/section/catalog/" method="POST"> + <object key="groups" dataType="catalog_recently_products"> + <object key="recently_products" dataType="catalog_recently_products"> + <object key="fields" dataType="catalog_recently_products"> + <object key="synchronize_with_backend" dataType="synchronize_with_backend"> + <field key="value">integer</field> + </object> + </object> + </object> + </object> + </operation> +</operations> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml new file mode 100644 index 0000000000000..b47c5f9571931 --- /dev/null +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml @@ -0,0 +1,169 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest"> + <annotations> + <features value="Persistent"/> + <stories value="Check the widgets is persisted"/> + <title value="Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie"/> + <description value="Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-12180"/> + <group value="persistent"/> + <skip> + <issueId value="MC-15741"/> + </skip> + </annotations> + <before> + <createData entity="PersistentConfigEnabled" stepKey="enablePersistent"/> + <createData entity="PersistentLogoutClearDisable" stepKey="persistentLogoutClearDisable"/> + <createData entity="EnableSynchronizeWidgetProductsWithBackendStorage" stepKey="enableSynchronizeWidgetProductsWithBackendStorage"/> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct2"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <actionGroup ref="AdminCreateRecentlyProductsWidgetActionGroup" stepKey="createRecentlyComparedProductsWidget"> + <argument name="widget" value="RecentlyComparedProductsWidget"/> + </actionGroup> + <actionGroup ref="AdminCreateRecentlyProductsWidgetActionGroup" stepKey="createRecentlyViewedProductsWidget"> + <argument name="widget" value="RecentlyViewedProductsWidget"/> + </actionGroup> + </before> + <after> + <createData entity="PersistentConfigDefault" stepKey="setDefaultPersistentState"/> + <createData entity="PersistentLogoutClearEnabled" stepKey="persistentLogoutClearEnabled"/> + <createData entity="DisableSynchronizeWidgetProductsWithBackendStorage" stepKey="disableSynchronizeWidgetProductsWithBackendStorage"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createSimpleProduct2" stepKey="deleteSimpleProduct2"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutFromCustomer"/> + <actionGroup ref="AdminDeleteWidgetActionGroup" stepKey="deleteRecentlyComparedProductsWidget"> + <argument name="widget" value="RecentlyComparedProductsWidget"/> + </actionGroup> + <actionGroup ref="AdminDeleteWidgetActionGroup" stepKey="deleteRecentlyViewedProductsWidget"> + <argument name="widget" value="RecentlyViewedProductsWidget"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Login to storefront from customer--> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome"/> + + <!--Open the details page of Simple Product 1, Simple Product 2 and add to cart, get to the category--> + <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart2"> + <argument name="product" value="$$createSimpleProduct2$$"/> + </actionGroup> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage3"/> + <!--The Recently Viewed widget displays Simple Product 1 and Simple Product 2--> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" stepKey="waitWidgetRecentlyViewedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct2.name$$" stepKey="seeProduct2InRecentlyViewedWidget"/> + + <!--Add Simple Product 1 and Simple Product 2 to Wishlist--> + <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProduct1ToWishlist"> + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage4"/> + <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProduct2ToWishlist"> + <argument name="productVar" value="$$createSimpleProduct2$$"/> + </actionGroup> + <!--The My Wishlist widget displays Simple Product 1 and Simple Product 2--> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage5"/> + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebar"> + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProduct2InWishlistSidebar"> + <argument name="productVar" value="$$createSimpleProduct2$$"/> + </actionGroup> + + <!--Add to compare Simple Product and Simple Product 2--> + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="compareAddSimpleProduct1ToCompare" > + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="compareAddSimpleProduct2ToCompare" > + <argument name="productVar" value="$$createSimpleProduct2$$"/> + </actionGroup> + <!--The Compare Products widget displays Simple Product 1 and Simple Product 2--> + <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="compareSimpleProduct1InSidebar"> + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="compareSimpleProduct2InSidebar"> + <argument name="productVar" value="$$createSimpleProduct2$$"/> + </actionGroup> + + <!--Click Clear all in the Compare Products widget--> + <waitForElementVisible selector="{{WidgetSection.ClearCompare}}" stepKey="waitForClearCompareBtn"/> + <click selector="{{WidgetSection.ClearCompare}}" stepKey="clickClearCompareBtn"/> + <waitForElementVisible selector="{{WidgetSection.AcceptClear}}" stepKey="waitForAcceptBtn"/> + <click selector="{{WidgetSection.AcceptClear}}" stepKey="acceptClearCompare"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <!--The Recently Compared widget displays Simple Product 1 and Simple Product 2--> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" stepKey="waitWidgetRecentlyComparedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct2InRecentlyComparedWidget"/> + + <!--Place the order--> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToShoppingCartPage"/> + <actionGroup ref="PlaceOrderWithLoggedUserActionGroup" stepKey="placeOrder"> + <argument name="shippingMethod" value="Flat Rate"/> + </actionGroup> + <!--The Recently Ordered widget displays Simple Product 1 and Simple Product 2--> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage6"/> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" stepKey="waitWidgetRecentlyOrderedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct2InRecentlyOrderedWidget"/> + + <!--Sign out and check that widgets persist the information about the items--> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="storefrontSignOut"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage7"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome2"/> + <seeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkLinkNotYoy"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget2"/> + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebar2"> + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget2"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget2"/> + + <!--Click the *Not you?* link and check the price for Simple Product--> + <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickNext"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage8"/> + <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome3"/> + <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProduct1InRecentlyViewedWidget"/> + <dontSee selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="dontSeeProduct1InWishlistWidget"/> + <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyComparedWidget"/> + <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyOrderedWidget"/> + + <!--Login to storefront from customer again--> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer2"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage9"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome4"/> + <waitForElementVisible selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="assertWishlistSidebarProductName"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget3"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget3"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget3"/> + </test> +</tests> diff --git a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml index 969ab58b04876..5d2b894b86438 100644 --- a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml +++ b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml @@ -78,4 +78,10 @@ <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> </actionGroup> + <actionGroup name="AdminCreateRecentlyProductsWidgetActionGroup" extends="AdminCreateWidgetActionGroup"> + <selectOption selector="{{AdminNewWidgetSection.productAttributesToShow}}" parameterArray="['Name', 'Image', 'Price']" stepKey="selectAllProductAttributes"/> + <selectOption selector="{{AdminNewWidgetSection.productButtonsToShow}}" parameterArray="['Add to Cart', 'Add to Compare', 'Add to Wishlist']" stepKey="selectAllProductButtons"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml index 27222298408de..370077f6feefa 100644 --- a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml +++ b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml @@ -32,4 +32,24 @@ <data key="display_mode">Cart Price Rule Related</data> <data key="restrict_type">Header</data> </entity> + <entity name="RecentlyComparedProductsWidget" type="widget"> + <data key="type">Recently Compared Products</data> + <data key="design_theme">Magento Luma</data> + <data key="name" unique="suffix">Recently Compared Products</data> + <array key="store_ids"> + <item>All Store Views</item> + </array> + <data key="display_on">All Pages</data> + <data key="container">Sidebar Additional</data> + </entity> + <entity name="RecentlyViewedProductsWidget" type="widget"> + <data key="type">Recently Viewed Products</data> + <data key="design_theme">Magento Luma</data> + <data key="name" unique="suffix">Recently Viewed Products</data> + <array key="store_ids"> + <item>All Store Views</item> + </array> + <data key="display_on">All Pages</data> + <data key="container">Sidebar Additional</data> + </entity> </entities> diff --git a/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml index eebd6c10b5085..8abd8cb142016 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml @@ -35,5 +35,7 @@ <element name="displayMode" type="select" selector="select[id*='display_mode']"/> <element name="restrictTypes" type="select" selector="select[id*='types']"/> <element name="saveAndContinue" type="button" selector="#save_and_edit_button" timeout="30"/> + <element name="productAttributesToShow" type="multiselect" selector="select[name='parameters[show_attributes][]']"/> + <element name="productButtonsToShow" type="multiselect" selector="select[name='parameters[show_buttons][]']"/> </section> </sections> diff --git a/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml index 0e2f6cec73a92..cf6bfc484cc57 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml @@ -11,5 +11,8 @@ <section name="StorefrontWidgetsSection"> <element name="widgetProductsGrid" type="block" selector=".block.widget.block-products-list.grid"/> <element name="widgetProductName" type="text" selector=".product-item-name"/> + <element name="widgetRecentlyViewedProductsGrid" type="block" selector=".block.widget.block-viewed-products-grid" timeout="30"/> + <element name="widgetRecentlyComparedProductsGrid" type="block" selector=".block.widget.block-compared-products-grid" timeout="30"/> + <element name="widgetRecentlyOrderedProductsGrid" type="block" selector=".block.block-reorder" timeout="30"/> </section> </sections> From 78eaa685ce43f5778f14be3df1da235fb4885c6e Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Tue, 9 Apr 2019 10:14:15 -0500 Subject: [PATCH 209/585] 230: Implement cache tag generation for GraphQL queries - Fixed tag generation when id's are not resolved --- .../Magento/GraphQlCache/Model/Plugin/Query/Resolver.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php index f3cccdb0995d2..4fad3ede4e5bc 100644 --- a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php +++ b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php @@ -65,9 +65,12 @@ public function afterResolve( $cacheTag = isset($cache['cache_tag']) ? $cache['cache_tag'] : []; $cacheable = isset($cache['cacheable']) ? $cache['cacheable'] : true; if (!empty($cacheTag) && $this->request->isGet() && $cacheable) { - $cacheTags = [$cacheTag]; + $cacheTags = []; // Resolved value must have cache IDs defined $resolvedItemsIds = $this->extractResolvedItemsIds($resolvedValue); + if (!empty($resolvedItemsIds)) { + $cacheTags = [$cacheTag]; + } foreach ($resolvedItemsIds as $itemId) { $cacheTags[] = $cacheTag . '_' . $itemId; } From f2e7e5d1e088f5a2402421fd0f3dfc0aa3f0402e Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Tue, 9 Apr 2019 10:56:28 -0500 Subject: [PATCH 210/585] MC-4823: Convert ChangeCustomerGroupTest to MFTF --- .../Test/Mftf/Section/AdminCustomerAccountInformationSection.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml index 71e3e673477d2..37c2f0381ee05 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml @@ -31,5 +31,6 @@ <element name="firstNameRequiredMessage" type="text" selector="//input[@name='customer[firstname]']/../label[contains(.,'This is a required field.')]"/> <element name="lastNameRequiredMessage" type="text" selector="//input[@name='customer[lastname]']/../label[contains(.,'This is a required field.')]"/> <element name="emailRequiredMessage" type="text" selector="//input[@name='customer[email]']/../label[contains(.,'This is a required field.')]"/> + <element name="disabledGroup" type="text" selector="//div[@class='admin__action-group-wrap admin__action-multiselect-wrap action-select-wrap _disabled']"/> </section> </sections> From 39774de802d2bc50724eaee29a8d08fb960fad3a Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Tue, 9 Apr 2019 11:06:11 -0500 Subject: [PATCH 211/585] 230: Implement cache tag generation for GraphQL queries - Fixed case sensitivity in vcls --- app/code/Magento/PageCache/etc/varnish4.vcl | 4 ++-- app/code/Magento/PageCache/etc/varnish5.vcl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/PageCache/etc/varnish4.vcl b/app/code/Magento/PageCache/etc/varnish4.vcl index 35c43171cd9be..c3698451e8efb 100644 --- a/app/code/Magento/PageCache/etc/varnish4.vcl +++ b/app/code/Magento/PageCache/etc/varnish4.vcl @@ -122,8 +122,8 @@ sub vcl_hash { hash_data(server.ip); } - if (req.http.store) { - hash_data(req.http.store); + if (req.http.Store) { + hash_data(req.http.Store); } if (req.http.Content-Currency) { hash_data(req.http.Content-Currency); diff --git a/app/code/Magento/PageCache/etc/varnish5.vcl b/app/code/Magento/PageCache/etc/varnish5.vcl index 67f9786bd3cd2..7640eae43df69 100644 --- a/app/code/Magento/PageCache/etc/varnish5.vcl +++ b/app/code/Magento/PageCache/etc/varnish5.vcl @@ -129,8 +129,8 @@ sub vcl_hash { } /* {{ design_exceptions_code }} */ - if (req.http.store) { - hash_data(req.http.store); + if (req.http.Store) { + hash_data(req.http.Store); } if (req.http.Content-Currency) { hash_data(req.http.Content-Currency); From f4e5b432cc453cf308755cc41438f21b03330e45 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Tue, 9 Apr 2019 13:24:33 -0500 Subject: [PATCH 212/585] MC-4328: Convert AddProductsToCartBySkuFromCustomerAccountTest to MFTF --- .../Catalog/Test/Mftf/Data/ProductOptionData.xml | 4 ++-- .../Test/Mftf/Data/ProductOptionValueData.xml | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml index e91438dc7ce44..6dd5dadacaf68 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml @@ -74,8 +74,8 @@ <data key="type">drop_down</data> <data key="sort_order">4</data> <data key="is_require">true</data> - <requiredEntity type="product_option_value">ProductDropdownOption1</requiredEntity> - <requiredEntity type="product_option_value">ProductDropdownOption2</requiredEntity> + <requiredEntity type="product_option_value">ProductOptionValueWithSkuDropdown1</requiredEntity> + <requiredEntity type="product_option_value">ProductOptionValueWithSkuDropdown2</requiredEntity> </entity> <entity name="ProductOptionRadiobutton" type="product_option"> <var key="product_sku" entityType="product" entityKey="sku" /> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml index 94778edebf066..ebd15be0ab86a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml @@ -68,18 +68,18 @@ <data key="price">20</data> <data key="price_type">percent</data> </entity> - <entity name="ProductDropdownOption1" type="product_option_value"> - <data key="title">ProductDropdownOption1</data> + <entity name="ProductOptionValueWithSkuDropdown1" type="product_option_value"> + <data key="title">ProductOptionValueWithSkuDropdown1</data> <data key="sort_order">1</data> <data key="price">10</data> <data key="price_type">fixed</data> - <data key="sku">product_dropdown_option_1_sku</data> + <data key="sku">product_option_value_sku_dropdown_1_</data> </entity> - <entity name="ProductDropdownOption2" type="product_option_value"> - <data key="title">ProductDropdownOption2</data> + <entity name="ProductOptionValueWithSkuDropdown2" type="product_option_value"> + <data key="title">ProductOptionValueWithSkuDropdown2</data> <data key="sort_order">1</data> <data key="price">10</data> <data key="price_type">fixed</data> - <data key="sku">product_dropdown_option_2_sku</data> + <data key="sku">product_option_value_sku_dropdown_2_</data> </entity> </entities> From dabc0b17082193a3a82fc47277f4d0f78880bd1a Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 9 Apr 2019 13:48:43 -0500 Subject: [PATCH 213/585] MC-4789: Convert CreateSalesRuleEntityPartOneTest to MFTF - Fix mistake I made during merging --- .../AdminCreateCartPriceRuleConditionsSectionActionGroup.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml index 876dfb288494e..d2e4e81d4a489 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml @@ -29,8 +29,6 @@ <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition2}}" stepKey="selectCondition2"/> <waitForPageLoad stepKey="waitForSecondConditionLoad"/> <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickTheEllipsis"/> - <click selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" stepKey="clickSelectCountryDropdown"/> - <waitForPageLoad stepKey="waitForDropdownLoad"/> <selectOption selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" userInput="{{ruleName.shippingCountry}}" stepKey="fillShippingCountryParameter"/> </actionGroup> <actionGroup name="AdminCreateCartPriceRuleConditionsSectionShippingPostcodeActionGroup"> From 411c957fd6b30d0164a4cae6e4fa642c6cf79833 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 9 Apr 2019 14:37:18 -0500 Subject: [PATCH 214/585] MC-4789: Convert CreateSalesRuleEntityPartOneTest to MFTF - Remove poorly designed action groups and hardcoded actions in their place --- ...tPriceRuleConditionsSectionActionGroup.xml | 58 ------------------- ...AndVerifyRuleConditionIsNotAppliedTest.xml | 14 +++-- ...talAndVerifyRuleConditionIsAppliedTest.xml | 16 +++-- ...exConditionsAndVerifyDeleteMessageTest.xml | 35 ++++++----- 4 files changed, 40 insertions(+), 83 deletions(-) delete mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml deleted file mode 100644 index d2e4e81d4a489..0000000000000 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleConditionsSectionActionGroup.xml +++ /dev/null @@ -1,58 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCreateCartPriceRuleConditionsSectionSubtotalActionGroup"> - <arguments> - <argument name="ruleName" type="entity"/> - <argument name="condition1" type="string"/> - </arguments> - <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> - <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewCondition"/> - <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition1}}" stepKey="selectCondition1"/> - <waitForPageLoad stepKey="waitForConditionLoad"/> - <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis"/> - <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{ruleName.subtotal}}" stepKey="fillSubtotalParameter"/> - </actionGroup> - <actionGroup name="AdminCreateCartPriceRuleConditionsSectionShippingCountryActionGroup"> - <arguments> - <argument name="ruleName" type="entity"/> - <argument name="condition2" type="string"/> - </arguments> - <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> - <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewConditionButton"/> - <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition2}}" stepKey="selectCondition2"/> - <waitForPageLoad stepKey="waitForSecondConditionLoad"/> - <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickTheEllipsis"/> - <selectOption selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" userInput="{{ruleName.shippingCountry}}" stepKey="fillShippingCountryParameter"/> - </actionGroup> - <actionGroup name="AdminCreateCartPriceRuleConditionsSectionShippingPostcodeActionGroup"> - <arguments> - <argument name="ruleName" type="entity"/> - <argument name="condition3" type="string"/> - </arguments> - <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> - <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickOnNewCondition"/> - <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition3}}" stepKey="selectCondition3"/> - <waitForPageLoad stepKey="waitForThirdConditionLoad"/> - <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickOnEllipsis"/> - <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--3')}}" userInput="{{ruleName.shippingPostcode}}" stepKey="fillShippingPostcodeParameter"/> - </actionGroup> - <actionGroup name="AdminCreateCartPriceRuleConditionsSectionTotalItemQuantityActionGroup"> - <arguments> - <argument name="ruleName" type="entity"/> - <argument name="condition4" type="string"/> - </arguments> - <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> - <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickOnNewCondition"/> - <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="{{condition4}}" stepKey="selectCondition4"/> - <waitForPageLoad stepKey="waitForThirdConditionLoad"/> - <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickOnEllipsis"/> - <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{ruleName.totalItemQuantity}}" stepKey="fillTotalItemQuantity"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml index 38ca57e5da5dd..a3c57dd15a8d7 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml @@ -40,10 +40,14 @@ <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" parameterArray="[{{CartPriceRuleConditionNotApplied.customerGroups}}]" stepKey="selectCustomerGroup"/> <selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionNotApplied.coupon_type}}" stepKey="selectCouponType"/> <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToConditionsHeader"/> - <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionTotalItemQuantityActionGroup" stepKey="createActiveCartPriceRuleConditionsTotalItemQuantitySection"> - <argument name="ruleName" value="CartPriceRuleConditionNotApplied"/> - <argument name="condition4" value="Total Items Quantity"/> - </actionGroup> + + <!-- Fill condition 1: Total Items Quantity --> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="expandConditions"/> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewCondition"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="Total Items Quantity" stepKey="selectCondition"/> + <waitForPageLoad stepKey="waitForConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{CartPriceRuleConditionNotApplied.totalItemQuantity}}" stepKey="fillTotalItemQuantity"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> <argument name="ruleName" value="CartPriceRuleConditionNotApplied"/> </actionGroup> @@ -108,4 +112,4 @@ </actionGroup> <dontSee selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeAssertDiscountAmountForRuleConditionNotApplied"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml index 22b03287c8952..16d3feab38739 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml @@ -39,11 +39,15 @@ <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.websites}}" stepKey="selectWebsites"/> <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" parameterArray="[{{CartPriceRuleConditionAppliedForSubtotal.customerGroups}}]" stepKey="selectCustomerGroup"/> <selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.coupon_type}}" stepKey="selectCouponType"/> + + <!-- Expand the conditions section --> <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToConditionsHeader"/> - <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionSubtotalActionGroup" stepKey="createActiveCartPriceRuleConditionsSubtotalSection"> - <argument name="ruleName" value="CartPriceRuleConditionAppliedForSubtotal"/> - <argument name="condition1" value="Subtotal"/> - </actionGroup> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewCondition"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="Subtotal" stepKey="selectCondition1"/> + <waitForPageLoad stepKey="waitForConditionLoad"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.subtotal}}" stepKey="fillSubtotalParameter"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> <argument name="ruleName" value="CartPriceRuleConditionAppliedForSubtotal"/> </actionGroup> @@ -68,7 +72,7 @@ <seeInField selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.websites}}" stepKey="seeWebsites"/> <seeInField selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.customerGroups}}" stepKey="seeCustomerGroup"/> <seeInField selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.coupon_type}}" stepKey="seeCouponType"/> - <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions2"/> <seeInField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.subtotal}}" stepKey="seeSubtotalParameter"/> <conditionalClick selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.actionsHeader}}" visible="true" stepKey="clickExpandActions"/> <see selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.simple_action}}" stepKey="seeActionApplyType"/> @@ -115,4 +119,4 @@ </actionGroup> <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$280.00" stepKey="seeAssertDiscountAmountAppliedForSubtotalConditionIsTrue"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml index 4403010e1ffc9..ee686d465cd6c 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml @@ -24,19 +24,26 @@ <actionGroup ref="AdminCreateCartPriceRuleRuleInfoSectionActionGroup" stepKey="createActiveCartPriceRuleRuleInfoSection"> <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> </actionGroup> - <!--Fill values for Condition Section--> - <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionSubtotalActionGroup" stepKey="createActiveCartPriceRuleConditionsSubtotalSection"> - <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> - <argument name="condition1" value="Subtotal"/> - </actionGroup> - <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionShippingCountryActionGroup" stepKey="createActiveCartPriceRuleConditionsShippingCountrySection"> - <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> - <argument name="condition2" value="Shipping Country"/> - </actionGroup> - <actionGroup ref="AdminCreateCartPriceRuleConditionsSectionShippingPostcodeActionGroup" stepKey="createActiveCartPriceRuleConditionsShippingPostcodeSection"> - <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> - <argument name="condition3" value="Shipping Postcode"/> - </actionGroup> + <!-- Expand the conditions section --> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/> + <!-- Fill condition 1: Subtotal --> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewCondition1"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="Subtotal" stepKey="selectCondition1"/> + <waitForPageLoad stepKey="waitForConditionLoad1"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis1"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{ActiveSalesRuleWithComplexConditions.subtotal}}" stepKey="fillSubtotalParameter1"/> + <!-- Fill condition 2: Country --> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewCondition2"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="Shipping Country" stepKey="selectCondition2"/> + <waitForPageLoad stepKey="waitForConditionLoad2"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis2"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.selectCountryDropdown}}" userInput="{{ActiveSalesRuleWithComplexConditions.shippingCountry}}" stepKey="fillShippingCountryParameter2"/> + <!-- Fill condition 3: Shipping Postcode--> + <click selector="{{AdminCartPriceRulesFormSection.newCondition}}" stepKey="clickNewCondition3"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelect}}" userInput="Shipping Postcode" stepKey="selectCondition3"/> + <waitForPageLoad stepKey="waitForConditionLoad3"/> + <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis3"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--3')}}" userInput="{{ActiveSalesRuleWithComplexConditions.shippingPostcode}}" stepKey="fillShippingPostcodeParameter"/> <!--Fill values for Action Section--> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> @@ -66,4 +73,4 @@ <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions.name"/> </actionGroup> </test> -</tests> \ No newline at end of file +</tests> From 7816e8081a68fa2bba85f058e0c25f69777375d0 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 9 Apr 2019 15:07:38 -0500 Subject: [PATCH 215/585] MC-4789: Convert CreateSalesRuleEntityPartOneTest to MFTF - Clean up naming of action groups. Everything was named ruleName before my changes. --- ...reateCartPriceRuleActionsSectionActionGroup.xml | 14 +++++++------- ...CreateCartPriceRuleLabelsSectionActionGroup.xml | 6 +++--- ...fyRuleConditionAndFreeShippingIsAppliedTest.xml | 6 +++--- ...eRuleAndVerifyRuleConditionIsNotAppliedTest.xml | 6 +++--- ...SubtotalAndVerifyRuleConditionIsAppliedTest.xml | 6 +++--- ...CategoryAndVerifyRuleConditionIsAppliedTest.xml | 6 +++--- ...alWeightAndVerifyRuleConditionIsAppliedTest.xml | 6 +++--- ...ComplexConditionsAndVerifyDeleteMessageTest.xml | 6 +++--- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml index fd3619d23dabb..42608bf36096b 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionsSectionActionGroup.xml @@ -9,13 +9,13 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup"> <arguments> - <argument name="ruleName" type="entity"/> + <argument name="rule" type="entity"/> </arguments> <conditionalClick selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.actionsHeader}}" visible="true" stepKey="clickToExpandActions"/> - <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{ruleName.simple_action}}" stepKey="selectActionType"/> - <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{ruleName.discount_amount}}" stepKey="fillDiscountAmount"/> - <fillField selector="{{AdminCartPriceRulesFormSection.maximumQtyDiscount}}" userInput="{{ruleName.maximumQtyDiscount}}" stepKey="fillMaximumQtyDiscount"/> - <fillField selector="{{AdminCartPriceRulesFormSection.discountStep}}" userInput="{{ruleName.discount_step}}" stepKey="fillDiscountStep"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{rule.simple_action}}" stepKey="selectActionType"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{rule.discount_amount}}" stepKey="fillDiscountAmount"/> + <fillField selector="{{AdminCartPriceRulesFormSection.maximumQtyDiscount}}" userInput="{{rule.maximumQtyDiscount}}" stepKey="fillMaximumQtyDiscount"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountStep}}" userInput="{{rule.discount_step}}" stepKey="fillDiscountStep"/> </actionGroup> <actionGroup name="AdminCreateCartPriceRuleActionsSectionShippingAmountActionGroup"> <click selector="{{AdminCartPriceRulesFormSection.applyToShippingAmount}}" stepKey="clickApplyToShipping"/> @@ -25,8 +25,8 @@ </actionGroup> <actionGroup name="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup"> <arguments> - <argument name="ruleName" type="string"/> + <argument name="freeShippingOption" type="string"/> </arguments> - <selectOption selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{ruleName}}" stepKey="selectForMatchingItemsOnly"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.freeShipping}}" userInput="{{freeShippingOption}}" stepKey="selectForMatchingItemsOnly"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml index 11bdc57e60a18..e9d5f07701bd8 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleLabelsSectionActionGroup.xml @@ -9,10 +9,10 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminCreateCartPriceRuleLabelsSectionActionGroup"> <arguments> - <argument name="ruleName" type="entity"/> + <argument name="rule" type="entity"/> </arguments> <conditionalClick selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.labelsHeader}}" visible="true" stepKey="clickToExpandLabels"/> - <fillField selector="{{AdminCartPriceRulesFormSection.defaultRuleLabelAllStoreViews}}" userInput="{{ruleName.defaultRuleLabelAllStoreViews}}" stepKey="fillDefaultRuleLabelAllStoreViews"/> - <fillField selector="{{AdminCartPriceRulesFormSection.defaultStoreView}}" userInput="{{ruleName.defaultStoreView}}" stepKey="fillDefaultStoreView"/> + <fillField selector="{{AdminCartPriceRulesFormSection.defaultRuleLabelAllStoreViews}}" userInput="{{rule.defaultRuleLabelAllStoreViews}}" stepKey="fillDefaultRuleLabelAllStoreViews"/> + <fillField selector="{{AdminCartPriceRulesFormSection.defaultStoreView}}" userInput="{{rule.defaultStoreView}}" stepKey="fillDefaultStoreView"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml index 5ed2e423288d9..33184f79f6f0c 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml @@ -41,13 +41,13 @@ <selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.coupon_type}}" stepKey="selectCouponType"/> <scrollTo selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="scrollToActionsHeader"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> - <argument name="ruleName" value="CartPriceRuleConditionAndFreeShippingApplied"/> + <argument name="rule" value="CartPriceRuleConditionAndFreeShippingApplied"/> </actionGroup> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> - <argument name="ruleName" value="{{CartPriceRuleConditionAndFreeShippingApplied.simple_free_shipping}}"/> + <argument name="freeShippingOption" value="{{CartPriceRuleConditionAndFreeShippingApplied.simple_free_shipping}}"/> </actionGroup> <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> - <argument name="ruleName" value="CartPriceRuleConditionAndFreeShippingApplied"/> + <argument name="rule" value="CartPriceRuleConditionAndFreeShippingApplied"/> </actionGroup> <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="seeAssertCartPriceRuleSuccessSaveMessage"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml index a3c57dd15a8d7..22628e599823d 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml @@ -49,14 +49,14 @@ <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis"/> <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{CartPriceRuleConditionNotApplied.totalItemQuantity}}" stepKey="fillTotalItemQuantity"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> - <argument name="ruleName" value="CartPriceRuleConditionNotApplied"/> + <argument name="rule" value="CartPriceRuleConditionNotApplied"/> </actionGroup> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> - <argument name="ruleName" value="{{CartPriceRuleConditionNotApplied.simple_free_shipping}}"/> + <argument name="freeShippingOption" value="{{CartPriceRuleConditionNotApplied.simple_free_shipping}}"/> </actionGroup> <scrollTo selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="scrollToLabelsHeader"/> <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> - <argument name="ruleName" value="CartPriceRuleConditionNotApplied"/> + <argument name="rule" value="CartPriceRuleConditionNotApplied"/> </actionGroup> <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="seeAssertCartPriceRuleSuccessSaveMessage"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml index 16d3feab38739..ab62e51414e85 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml @@ -49,14 +49,14 @@ <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickEllipsis"/> <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{CartPriceRuleConditionAppliedForSubtotal.subtotal}}" stepKey="fillSubtotalParameter"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> - <argument name="ruleName" value="CartPriceRuleConditionAppliedForSubtotal"/> + <argument name="rule" value="CartPriceRuleConditionAppliedForSubtotal"/> </actionGroup> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> - <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForSubtotal.simple_free_shipping}}"/> + <argument name="freeShippingOption" value="{{CartPriceRuleConditionAppliedForSubtotal.simple_free_shipping}}"/> </actionGroup> <scrollTo selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="scrollToLabelsHeader"/> <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> - <argument name="ruleName" value="CartPriceRuleConditionAppliedForSubtotal"/> + <argument name="rule" value="CartPriceRuleConditionAppliedForSubtotal"/> </actionGroup> <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="seeAssertCartPriceRuleSuccessSaveMessage"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml index 87f963a78d718..24fb479537764 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml @@ -58,14 +58,14 @@ <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickOnEllipsis"/> <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1--1')}}" userInput="$$createCategory.id$$" stepKey="fillTotalItemQuantity"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> - <argument name="ruleName" value="CartPriceRuleConditionAppliedForCategory"/> + <argument name="rule" value="CartPriceRuleConditionAppliedForCategory"/> </actionGroup> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> - <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForCategory.simple_free_shipping}}"/> + <argument name="freeShippingOption" value="{{CartPriceRuleConditionAppliedForCategory.simple_free_shipping}}"/> </actionGroup> <scrollTo selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="scrollToLabelsHeader"/> <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> - <argument name="ruleName" value="CartPriceRuleConditionAppliedForCategory"/> + <argument name="rule" value="CartPriceRuleConditionAppliedForCategory"/> </actionGroup> <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="seeAssertCartPriceRuleSuccessSaveMessage"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml index bc0277e07cddf..c62b0dd869281 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml @@ -47,14 +47,14 @@ <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickOnEllipsis"/> <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1')}}" userInput="{{CartPriceRuleConditionAppliedForWeight.totalWeight}}" stepKey="fillTotalItemQuantity"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> - <argument name="ruleName" value="CartPriceRuleConditionAppliedForWeight"/> + <argument name="rule" value="CartPriceRuleConditionAppliedForWeight"/> </actionGroup> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> - <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForWeight.simple_free_shipping}}"/> + <argument name="freeShippingOption" value="{{CartPriceRuleConditionAppliedForWeight.simple_free_shipping}}"/> </actionGroup> <scrollTo selector="{{AdminCartPriceRulesFormSection.labelsHeader}}" stepKey="scrollToLabelsHeader"/> <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> - <argument name="ruleName" value="CartPriceRuleConditionAppliedForWeight"/> + <argument name="rule" value="CartPriceRuleConditionAppliedForWeight"/> </actionGroup> <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="seeAssertCartPriceRuleSuccessSaveMessage"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml index ee686d465cd6c..7baec93c73905 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml @@ -46,16 +46,16 @@ <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--3')}}" userInput="{{ActiveSalesRuleWithComplexConditions.shippingPostcode}}" stepKey="fillShippingPostcodeParameter"/> <!--Fill values for Action Section--> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> - <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> + <argument name="rule" value="ActiveSalesRuleWithComplexConditions"/> </actionGroup> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionShippingAmountActionGroup" stepKey="createActiveCartPriceRuleShippingAmountActionsSection"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionSubsequentRulesActionGroup" stepKey="createActiveCartPriceRuleDiscardSubsequentRulesActionsSection"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionFreeShippingActionGroup" stepKey="createActiveCartPriceRuleFreeShippingActionsSection"> - <argument name="ruleName" value="{{ActiveSalesRuleWithComplexConditions.simple_free_shipping}}"/> + <argument name="freeShippingOption" value="{{ActiveSalesRuleWithComplexConditions.simple_free_shipping}}"/> </actionGroup> <!--Fill values for Labels Section--> <actionGroup ref="AdminCreateCartPriceRuleLabelsSectionActionGroup" stepKey="createActiveCartPriceRuleLabelsSection"> - <argument name="ruleName" value="ActiveSalesRuleWithComplexConditions"/> + <argument name="rule" value="ActiveSalesRuleWithComplexConditions"/> </actionGroup> <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="assertVerifyCartPriceRuleSuccessSaveMessage"/> </before> From 683d881c59e387cb0f8a737f284050a33a0774a1 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 9 Apr 2019 15:17:52 -0500 Subject: [PATCH 216/585] MC-4789: Convert CreateSalesRuleEntityPartOneTest to MFTF - Improve stepKey name --- ...eWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml index 24fb479537764..e1a4ca40fd710 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml @@ -54,7 +54,7 @@ <click selector="{{AdminCartPriceRulesFormSection.addNewCondition('1--1')}}" stepKey="clickOnTheAddNewCondition"/> <waitForPageLoad stepKey="waitForToggleLoad"/> <selectOption selector="{{AdminCartPriceRulesFormSection.conditionSelectDropdown('1--1')}}" userInput="Category" stepKey="selectCategory"/> - <waitForElementVisible selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="a"/> + <waitForElementVisible selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="waitForEllipsis"/> <click selector="{{AdminCartPriceRulesFormSection.targetEllipsis}}" stepKey="clickOnEllipsis"/> <fillField selector="{{AdminCartPriceRulesFormSection.ruleFieldByIndex('1--1--1')}}" userInput="$$createCategory.id$$" stepKey="fillTotalItemQuantity"/> <actionGroup ref="AdminCreateCartPriceRuleActionsSectionDiscountFieldsActionGroup" stepKey="createActiveCartPriceRuleActionsSection"> From df413f51a0ec509358173b76322735d620a5c0d0 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Tue, 9 Apr 2019 14:45:54 -0500 Subject: [PATCH 217/585] MC-15779: Create coupon test functionality for our benchmark --- .../profiles/ce/extra_large.xml | 1 + .../performance-toolkit/profiles/ce/large.xml | 1 + .../profiles/ce/medium.xml | 1 + .../profiles/ce/medium_msite.xml | 1 + .../performance-toolkit/profiles/ce/small.xml | 1 + .../Setup/Fixtures/CouponCodesFixture.php | 164 +++++++++++++++ .../Unit/Fixtures/CouponCodesFixtureTest.php | 198 ++++++++++++++++++ 7 files changed, 367 insertions(+) create mode 100644 setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php create mode 100644 setup/src/Magento/Setup/Test/Unit/Fixtures/CouponCodesFixtureTest.php diff --git a/setup/performance-toolkit/profiles/ce/extra_large.xml b/setup/performance-toolkit/profiles/ce/extra_large.xml index 390bf7fb12003..911ac7fe06d3b 100644 --- a/setup/performance-toolkit/profiles/ce/extra_large.xml +++ b/setup/performance-toolkit/profiles/ce/extra_large.xml @@ -39,6 +39,7 @@ <catalog_price_rules>20</catalog_price_rules> <!-- Number of catalog price rules --> <cart_price_rules>20</cart_price_rules> <!-- Number of cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> + <coupon_codes>20</coupon_codes> <!-- Number of coupon codes --> <product_attribute_sets>100</product_attribute_sets> <!-- Number of product attribute sets --> <product_attribute_sets_attributes>30</product_attribute_sets_attributes> <!-- Number of attributes per set --> diff --git a/setup/performance-toolkit/profiles/ce/large.xml b/setup/performance-toolkit/profiles/ce/large.xml index ed91b22930af5..79abab0ba4b95 100644 --- a/setup/performance-toolkit/profiles/ce/large.xml +++ b/setup/performance-toolkit/profiles/ce/large.xml @@ -39,6 +39,7 @@ <catalog_price_rules>20</catalog_price_rules> <!-- Number of catalog price rules --> <cart_price_rules>20</cart_price_rules> <!-- Number of cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> + <coupon_codes>20</coupon_codes> <!-- Number of coupon codes --> <product_attribute_sets>50</product_attribute_sets> <!-- Number of product attribute sets --> <product_attribute_sets_attributes>20</product_attribute_sets_attributes> <!-- Number of attributes per set --> diff --git a/setup/performance-toolkit/profiles/ce/medium.xml b/setup/performance-toolkit/profiles/ce/medium.xml index f01eabb7898f3..d02370a7770b3 100644 --- a/setup/performance-toolkit/profiles/ce/medium.xml +++ b/setup/performance-toolkit/profiles/ce/medium.xml @@ -39,6 +39,7 @@ <catalog_price_rules>20</catalog_price_rules> <!-- Number of catalog price rules --> <cart_price_rules>20</cart_price_rules> <!-- Number of cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> + <coupon_codes>20</coupon_codes> <!-- Number of coupon codes --> <product_attribute_sets>30</product_attribute_sets> <!-- Number of product attribute sets --> <product_attribute_sets_attributes>10</product_attribute_sets_attributes> <!-- Number of attributes per set --> diff --git a/setup/performance-toolkit/profiles/ce/medium_msite.xml b/setup/performance-toolkit/profiles/ce/medium_msite.xml index a57fcad0779fe..2f9310c5242cb 100644 --- a/setup/performance-toolkit/profiles/ce/medium_msite.xml +++ b/setup/performance-toolkit/profiles/ce/medium_msite.xml @@ -45,6 +45,7 @@ <catalog_price_rules>20</catalog_price_rules> <!-- Number of catalog price rules --> <cart_price_rules>20</cart_price_rules> <!-- Number of cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> + <coupon_codes>20</coupon_codes> <!-- Number of coupon codes --> <product_attribute_sets>30</product_attribute_sets> <!-- Number of product attribute sets --> <product_attribute_sets_attributes>10</product_attribute_sets_attributes> <!-- Number of attributes per set --> diff --git a/setup/performance-toolkit/profiles/ce/small.xml b/setup/performance-toolkit/profiles/ce/small.xml index 60ae901d8f5e0..cf7768328bd69 100644 --- a/setup/performance-toolkit/profiles/ce/small.xml +++ b/setup/performance-toolkit/profiles/ce/small.xml @@ -39,6 +39,7 @@ <catalog_price_rules>20</catalog_price_rules> <!-- Number of catalog price rules --> <cart_price_rules>20</cart_price_rules> <!-- Number of cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> + <coupon_codes>20</coupon_codes> <!-- Number of coupon codes --> <product_attribute_sets>10</product_attribute_sets> <!-- Number of product attribute sets --> <product_attribute_sets_attributes>5</product_attribute_sets_attributes> <!-- Number of attributes per set --> diff --git a/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php new file mode 100644 index 0000000000000..31e5ab9ebd575 --- /dev/null +++ b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php @@ -0,0 +1,164 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Fixtures; + +/** + * Fixture for generating coupon codes + * + * Support the following format: + * <!-- Number of coupon codes --> + * <coupon_codes>{int}</coupon_codes> + * + * @see setup/performance-toolkit/profiles/ce/small.xml + */ +class CouponCodesFixture extends Fixture +{ + /** + * @var int + */ + protected $priority = 130; + + /** + * @var int + */ + protected $couponCodesCount = 0; + + /** + * @var \Magento\SalesRule\Model\RuleFactory + */ + private $ruleFactory; + + /** + * @var \Magento\SalesRule\Model\CouponFactory + */ + private $couponCodeFactory; + + /** + * Constructor + * + * @param FixtureModel $fixtureModel + * @param \Magento\SalesRule\Model\RuleFactory|null $ruleFactory + * @param \Magento\SalesRule\Model\CouponFactory|null $couponCodeFactory + */ + public function __construct( + FixtureModel $fixtureModel, + \Magento\SalesRule\Model\RuleFactory $ruleFactory = null, + \Magento\SalesRule\Model\CouponFactory $couponCodeFactory = null + ) { + parent::__construct($fixtureModel); + $this->ruleFactory = $ruleFactory ?: $this->fixtureModel->getObjectManager() + ->get(\Magento\SalesRule\Model\RuleFactory::class); + $this->couponCodeFactory = $couponCodeFactory ?: $this->fixtureModel->getObjectManager() + ->get(\Magento\SalesRule\Model\CouponFactory::class); + } + + /** + * {@inheritdoc} + * @SuppressWarnings(PHPMD) + */ + public function execute() + { + $this->fixtureModel->resetObjectManager(); + $this->couponCodesCount = $this->fixtureModel->getValue('coupon_codes', 0); + if (!$this->couponCodesCount) { + return; + } + + /** @var \Magento\Store\Model\StoreManager $storeManager */ + $storeManager = $this->fixtureModel->getObjectManager()->create(\Magento\Store\Model\StoreManager::class); + /** @var $category \Magento\Catalog\Model\Category */ + $category = $this->fixtureModel->getObjectManager()->get(\Magento\Catalog\Model\Category::class); + + //Get all websites + $categoriesArray = []; + $websites = $storeManager->getWebsites(); + foreach ($websites as $website) { + //Get all groups + $websiteGroups = $website->getGroups(); + foreach ($websiteGroups as $websiteGroup) { + $websiteGroupRootCategory = $websiteGroup->getRootCategoryId(); + $category->load($websiteGroupRootCategory); + $categoryResource = $category->getResource(); + //Get all categories + $resultsCategories = $categoryResource->getAllChildren($category); + foreach ($resultsCategories as $resultsCategory) { + $category->load($resultsCategory); + $structure = explode('/', $category->getPath()); + if (count($structure) > 2) { + $categoriesArray[] = [$category->getId(), $website->getId()]; + } + } + } + } + asort($categoriesArray); + $categoriesArray = array_values($categoriesArray); + + $this->generateCouponCodes($this->ruleFactory, $this->couponCodeFactory, $categoriesArray); + } + + /** + * @param \Magento\SalesRule\Model\RuleFactory $ruleFactory + * @param \Magento\SalesRule\Model\CouponFactory $couponCodeFactory + * @param array $categoriesArray + * @return void + */ + public function generateCouponCodes($ruleFactory, $couponCodeFactory, $categoriesArray) + { + for ($i = 0; $i < $this->couponCodesCount; $i++) { + $ruleName = sprintf('Coupon Code %1$d', $i); + $data = [ + 'rule_id' => null, + 'name' => $ruleName, + 'is_active' => '1', + 'website_ids' => $categoriesArray[$i % count($categoriesArray)][1], + 'customer_group_ids' => [ + 0 => '0', + 1 => '1', + 2 => '2', + 3 => '3', + ], + 'coupon_type' => \Magento\SalesRule\Model\Rule::COUPON_TYPE_SPECIFIC, + 'conditions' => [], + 'simple_action' => \Magento\SalesRule\Model\Rule::BY_PERCENT_ACTION, + 'discount_amount' => 5, + 'discount_step' => 0, + 'stop_rules_processing' => 1, + ]; + + $model = $ruleFactory->create(); + $model->loadPost($data); + $useAutoGeneration = (int)!empty($data['use_auto_generation']); + $model->setUseAutoGeneration($useAutoGeneration); + $model->save(); + + $coupon = $couponCodeFactory->create(); + $coupon->setRuleId($model->getId()) + ->setCode('CouponCode' . $i) + ->setIsPrimary(true) + ->setType(0); + $coupon->save(); + } + } + + /** + * {@inheritdoc} + */ + public function getActionTitle() + { + return 'Generating coupon codes'; + } + + /** + * {@inheritdoc} + */ + public function introduceParamLabels() + { + return [ + 'coupon_codes' => 'Coupon Codes' + ]; + } +} diff --git a/setup/src/Magento/Setup/Test/Unit/Fixtures/CouponCodesFixtureTest.php b/setup/src/Magento/Setup/Test/Unit/Fixtures/CouponCodesFixtureTest.php new file mode 100644 index 0000000000000..e28415961f26a --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Fixtures/CouponCodesFixtureTest.php @@ -0,0 +1,198 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Test\Unit\Fixtures; + +use \Magento\Setup\Fixtures\CouponCodesFixture; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class CouponCodesFixtureTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\Setup\Fixtures\CartPriceRulesFixture + */ + private $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Setup\Fixtures\FixtureModel + */ + private $fixtureModelMock; + + /** + * @var \Magento\SalesRule\Model\RuleFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $ruleFactoryMock; + + /** + * @var \Magento\SalesRule\Model\CouponFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $couponCodeFactoryMock; + + /** + * setUp + */ + public function setUp() + { + $this->fixtureModelMock = $this->createMock(\Magento\Setup\Fixtures\FixtureModel::class); + $this->ruleFactoryMock = $this->createPartialMock(\Magento\SalesRule\Model\RuleFactory::class, ['create']); + $this->couponCodeFactoryMock = $this->createPartialMock( + \Magento\SalesRule\Model\CouponFactory::class, + ['create'] + ); + $this->model = new CouponCodesFixture( + $this->fixtureModelMock, + $this->ruleFactoryMock, + $this->couponCodeFactoryMock + ); + } + + /** + * testExecute + */ + public function testExecute() + { + $storeMock = $this->createMock(\Magento\Store\Model\Store::class); + $storeMock->expects($this->once()) + ->method('getRootCategoryId') + ->will($this->returnValue(2)); + + $websiteMock = $this->createMock(\Magento\Store\Model\Website::class); + $websiteMock->expects($this->once()) + ->method('getGroups') + ->will($this->returnValue([$storeMock])); + $websiteMock->expects($this->once()) + ->method('getId') + ->will($this->returnValue('website_id')); + + $contextMock = $this->createMock(\Magento\Framework\Model\ResourceModel\Db\Context::class); + $abstractDbMock = $this->getMockForAbstractClass( + \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + [$contextMock], + '', + true, + true, + true, + ['getAllChildren'] + ); + $abstractDbMock->expects($this->once()) + ->method('getAllChildren') + ->will($this->returnValue([1])); + + $storeManagerMock = $this->createMock(\Magento\Store\Model\StoreManager::class); + $storeManagerMock->expects($this->once()) + ->method('getWebsites') + ->will($this->returnValue([$websiteMock])); + + $categoryMock = $this->createMock(\Magento\Catalog\Model\Category::class); + $categoryMock->expects($this->once()) + ->method('getResource') + ->will($this->returnValue($abstractDbMock)); + $categoryMock->expects($this->once()) + ->method('getPath') + ->will($this->returnValue('path/to/file')); + $categoryMock->expects($this->once()) + ->method('getId') + ->will($this->returnValue('category_id')); + + $objectValueMap = [ + [\Magento\Catalog\Model\Category::class, $categoryMock] + ]; + + $objectManagerMock = $this->createMock(\Magento\Framework\ObjectManager\ObjectManager::class); + $objectManagerMock->expects($this->once()) + ->method('create') + ->will($this->returnValue($storeManagerMock)); + $objectManagerMock->expects($this->once()) + ->method('get') + ->will($this->returnValueMap($objectValueMap)); + + $valueMap = [ + ['coupon_codes', 0, 1] + ]; + + $this->fixtureModelMock + ->expects($this->exactly(1)) + ->method('getValue') + ->will($this->returnValueMap($valueMap)); + $this->fixtureModelMock + ->expects($this->exactly(2)) + ->method('getObjectManager') + ->will($this->returnValue($objectManagerMock)); + + $ruleMock = $this->createMock(\Magento\SalesRule\Model\Rule::class); + $this->ruleFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($ruleMock); + + $couponMock = $this->createMock(\Magento\SalesRule\Model\Coupon::class); + $couponMock->expects($this->once()) + ->method('setRuleId') + ->willReturnSelf(); + $couponMock->expects($this->once()) + ->method('setCode') + ->willReturnSelf(); + $couponMock->expects($this->once()) + ->method('setIsPrimary') + ->willReturnSelf(); + $couponMock->expects($this->once()) + ->method('setType') + ->willReturnSelf(); + $couponMock->expects($this->once()) + ->method('save') + ->willReturnSelf(); + $this->couponCodeFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($couponMock); + + $this->model->execute(); + } + + /** + * testNoFixtureConfigValue + */ + public function testNoFixtureConfigValue() + { + $ruleMock = $this->createMock(\Magento\SalesRule\Model\Rule::class); + $ruleMock->expects($this->never())->method('save'); + + $objectManagerMock = $this->createMock(\Magento\Framework\ObjectManager\ObjectManager::class); + $objectManagerMock->expects($this->never()) + ->method('get') + ->with($this->equalTo(\Magento\SalesRule\Model\Rule::class)) + ->willReturn($ruleMock); + + $this->fixtureModelMock + ->expects($this->never()) + ->method('getObjectManager') + ->willReturn($objectManagerMock); + $this->fixtureModelMock + ->expects($this->once()) + ->method('getValue') + ->willReturn(false); + + $this->model->execute(); + } + + /** + * testGetActionTitle + */ + public function testGetActionTitle() + { + $this->assertSame('Generating coupon codes', $this->model->getActionTitle()); + } + + /** + * testIntroduceParamLabels + */ + public function testIntroduceParamLabels() + { + $this->assertSame([ + 'coupon_codes' => 'Coupon Codes' + ], $this->model->introduceParamLabels()); + } +} From 361f5485ed0081c5ecb25db4a5fa5e282b143b04 Mon Sep 17 00:00:00 2001 From: Viktor Tymchynskyi <vtymchynskyi@magento.com> Date: Tue, 9 Apr 2019 13:22:31 -0500 Subject: [PATCH 218/585] MAGETWO-99094: Orders in PayPal, but not created in Magento due to missing credit card exp_month - Expiration month and year read from PayPal response --- .../Payflow/Service/Response/Transaction.php | 51 ++++++- .../Controller/Transparent/ResponseTest.php | 134 ++++++++++++++++++ 2 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Controller/Transparent/ResponseTest.php diff --git a/app/code/Magento/Paypal/Model/Payflow/Service/Response/Transaction.php b/app/code/Magento/Paypal/Model/Payflow/Service/Response/Transaction.php index 06a8a5b680bf4..7143576b71a07 100644 --- a/app/code/Magento/Paypal/Model/Payflow/Service/Response/Transaction.php +++ b/app/code/Magento/Paypal/Model/Payflow/Service/Response/Transaction.php @@ -3,9 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Paypal\Model\Payflow\Service\Response; use Magento\Framework\DataObject; +use Magento\Framework\Intl\DateTimeFactory; use Magento\Payment\Model\Method\Logger; use Magento\Paypal\Model\Payflow\Service\Response\Handler\HandlerInterface; use Magento\Framework\Session\Generic; @@ -18,6 +21,7 @@ /** * Class Transaction + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Transaction { @@ -51,6 +55,11 @@ class Transaction */ private $logger; + /** + * @var DateTimeFactory + */ + private $dateTimeFactory; + /** * @param Generic $sessionTransparent * @param CartRepositoryInterface $quoteRepository @@ -58,6 +67,7 @@ class Transaction * @param PaymentMethodManagementInterface $paymentManagement * @param HandlerInterface $errorHandler * @param Logger $logger + * @param DateTimeFactory $dateTimeFactory */ public function __construct( Generic $sessionTransparent, @@ -65,7 +75,8 @@ public function __construct( Transparent $transparent, PaymentMethodManagementInterface $paymentManagement, HandlerInterface $errorHandler, - Logger $logger + Logger $logger, + DateTimeFactory $dateTimeFactory ) { $this->sessionTransparent = $sessionTransparent; $this->quoteRepository = $quoteRepository; @@ -73,6 +84,7 @@ public function __construct( $this->paymentManagement = $paymentManagement; $this->errorHandler = $errorHandler; $this->logger = $logger; + $this->dateTimeFactory = $dateTimeFactory; } /** @@ -114,8 +126,45 @@ public function savePaymentInQuote($response) $payment->setData(OrderPaymentInterface::CC_TYPE, $response->getData(OrderPaymentInterface::CC_TYPE)); $payment->setAdditionalInformation(Payflowpro::PNREF, $response->getData(Payflowpro::PNREF)); + $expDate = $response->getData('expdate'); + $expMonth = $this->getCcExpMonth($expDate); + $payment->setCcExpMonth($expMonth); + $expYear = $this->getCcExpYear($expDate); + $payment->setCcExpYear($expYear); + $this->errorHandler->handle($payment, $response); $this->paymentManagement->set($quote->getId(), $payment); } + + /** + * Extracts expiration month from PayPal response expiration date. + * + * @param string $expDate format {MMYY} + * @return int + */ + private function getCcExpMonth(string $expDate): int + { + return (int)substr($expDate, 0, 2); + } + + /** + * Extracts expiration year from PayPal response expiration date. + * + * @param string $expDate format {MMYY} + * @return int + */ + private function getCcExpYear(string $expDate): int + { + $last2YearDigits = (int)substr($expDate, 2, 2); + $currentDate = $this->dateTimeFactory->create('now', new \DateTimeZone('UTC')); + $first2YearDigits = (int)substr($currentDate->format('Y'), 0, 2); + + // case when credit card expires at next century + if ((int)$currentDate->format('y') > $last2YearDigits) { + $first2YearDigits++; + } + + return 100 * $first2YearDigits + $last2YearDigits; + } } diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/Transparent/ResponseTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Transparent/ResponseTest.php new file mode 100644 index 0000000000000..17464b6d65861 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Transparent/ResponseTest.php @@ -0,0 +1,134 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Paypal\Controller\Transparent; + +use Magento\Checkout\Model\Session; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Intl\DateTimeFactory; +use Magento\Framework\Session\Generic as GenericSession; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Api\PaymentMethodManagementInterface; + +/** + * Tests PayPal transparent response controller. + */ +class ResponseTest extends \Magento\TestFramework\TestCase\AbstractController +{ + /** + * Tests setting credit card expiration month and year to payment from PayPal response. + * + * @param string $currentDateTime + * @param string $paypalExpDate + * @param string $expectedCcMonth + * @param string $expectedCcYear + * @throws NoSuchEntityException + * + * @magentoConfigFixture current_store payment/payflowpro/active 1 + * @magentoDataFixture Magento/Sales/_files/quote.php + * @dataProvider paymentCcExpirationDateDataProvider + */ + public function testPaymentCcExpirationDate( + string $currentDateTime, + string $paypalExpDate, + string $expectedCcMonth, + string $expectedCcYear + ) { + $reservedOrderId = 'test01'; + $postData = [ + 'EXPDATE' => $paypalExpDate, + 'AMT' => '0.00', + 'RESPMSG' => 'Verified', + 'CVV2MATCH' => 'Y', + 'PNREF' => 'A10AAD866C87', + 'SECURETOKEN' => '3HYEHfG06skydAdBXbpIl8QJZ', + 'AVSDATA' => 'YNY', + 'RESULT' => '0', + 'IAVS' => 'N', + 'AVSADDR' => 'Y', + 'SECURETOKENID' => 'yqanLisRZbI0HAG8q3SbbKbhiwjNZAGf', + ]; + + $quote = $this->getQuote($reservedOrderId); + $this->getRequest()->setPostValue($postData); + + /** @var Session $checkoutSession */ + $checkoutSession = $this->_objectManager->get(GenericSession::class); + $checkoutSession->setQuoteId($quote->getId()); + $this->setCurrentDateTime($currentDateTime); + + $this->dispatch('paypal/transparent/response'); + + /** @var PaymentMethodManagementInterface $paymentManagment */ + $paymentManagment = $this->_objectManager->get(PaymentMethodManagementInterface::class); + $payment = $paymentManagment->get($quote->getId()); + + $this->assertEquals($expectedCcMonth, $payment->getCcExpMonth()); + $this->assertEquals($expectedCcYear, $payment->getCcExpYear()); + } + + /** + * @return array + */ + public function paymentCcExpirationDateDataProvider(): array + { + return [ + 'Expiration year in current century' => [ + 'currentDateTime' => '2019-07-05 00:00:00', + 'paypalExpDate' => '0321', + 'expectedCcMonth' => 3, + 'expectedCcYear' => 2021 + ], + 'Expiration year in next century' => [ + 'currentDateTime' => '2099-01-01 00:00:00', + 'paypalExpDate' => '1002', + 'expectedCcMonth' => 10, + 'expectedCcYear' => 2102 + ] + ]; + } + + /** + * Sets current date and time. + * + * @param string $date + */ + private function setCurrentDateTime(string $dateTime): void + { + $dateTime = new \DateTime($dateTime, new \DateTimeZone('UTC')); + $dateTimeFactory = $this->getMockBuilder(DateTimeFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $dateTimeFactory->method('create') + ->willReturn($dateTime); + + $this->_objectManager->addSharedInstance($dateTimeFactory, DateTimeFactory::class); + } + + /** + * Gets quote by reserved order ID. + * + * @param string $reservedOrderId + * @return CartInterface + */ + private function getQuote(string $reservedOrderId): CartInterface + { + $searchCriteria = $this->_objectManager->get(SearchCriteriaBuilder::class) + ->addFilter('reserved_order_id', $reservedOrderId) + ->create(); + + /** @var CartRepositoryInterface $quoteRepository */ + $quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class); + $items = $quoteRepository->getList($searchCriteria) + ->getItems(); + + return array_pop($items); + } +} From 18a294a26f0cd1e9a0964f4c045c8465c5b7c53a Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Tue, 9 Apr 2019 17:02:12 -0500 Subject: [PATCH 219/585] GraphQL-514: Test coverage for tag cache generation - added tests for coverage for category --- .../TestFramework/TestCase/GraphQl/Client.php | 4 +- .../TestCase/HttpClient/CurlClient.php | 8 +++ .../GraphQl/PageCache/CacheTagTest.php | 60 +++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php index aeca700c87220..eac7fecc267ef 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php @@ -130,8 +130,8 @@ public function getQueryResponseHeaders(string $query, array $variables = [], st $url = $this->getEndpointUrl(); $requestArray = [ 'query' => $query, - 'variables' => empty($variables) ? $variables : null, - 'operationName' => empty($operationName) ? $operationName : null + 'variables' => $variables ? $this->json->jsonEncode($variables) : null, + 'operationName' => !empty($operationName) ? $operationName : null ]; $responseHeader = $this->curlClient->getHttpHeaders($url, $requestArray, $headers); diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php index 24f622da7055a..11af91bd3e008 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php @@ -32,6 +32,14 @@ public function get($url, $data = [], $headers = []) return $resp["body"]; } + /** + * Perform a HTTP GET request and returns just the response headers + * + * @param $url + * @param array $data + * @param array $headers + * @return mixed + */ public function getHttpHeaders($url, $data = [], $headers = []) { if (!empty($data)) { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index 0c9f489f91e3c..7cb3afbc3eacb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -74,4 +74,64 @@ public function testCacheTagsAndCacheDebugHeaderFromResponse() ); } } + + /** + * Tests if Magento cache tags for categories are generated properly + * + * @magentoApiDataFixture Magento/Catalog/_files/category_product.php + */ + public function testCacheTagFromResponseHeaderForCategoriesWithProduct() + { + $productSku = 'simple333'; + $categoryId ='333'; + $query + = <<<'QUERY' +query GetCategoryQuery($id: Int!, $pageSize: Int!, $currentPage: Int!) { + category(id: $id) { + id + description + name + product_count + products(pageSize: $pageSize, currentPage: $currentPage) { + items { + id + name + url_key + } + total_count + } + } + } +QUERY; + $variables =[ + 'id' => 333, + 'pageSize'=> 10, + 'currentPage' => 1 + ]; + + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, $variables, '', []); + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + /** @var Product $product */ + $product =$productRepository->get($productSku,false,null, true); + + /** cache-debug header value should be a MISS when category is loaded first time */ + preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); + $this->assertEquals('MISS', rtrim($matchesMiss[1],"\r")); + + /** checks to see if the X-Magento-Tags for category is displayed correctly */ + preg_match('/X-Magento-Tags: (.*?)\n/', $responseMissHeaders, $headerCacheTags); + $actualCacheTags = explode(',', rtrim($headerCacheTags[1],"\r")); + $expectedCacheTags=['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $product->getId(),'FPC']; + foreach(array_keys($actualCacheTags) as $key){ + $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key] + ); + } + /** cache-debug header value should be MISS after updating child-product and reloading the category */ + $product->setPrice(15); + $product->save(); + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, $variables, '', []); + preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); + $this->assertEquals('MISS', rtrim($matchesMiss[1],"\r")); + } } From 758b056aedc937ae74f37bfb1481a3f1b2a115d9 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Tue, 9 Apr 2019 17:59:25 -0500 Subject: [PATCH 220/585] Issue-230: adding varnish - fixing promises --- .../Model/Resolver/Categories.php | 56 +++++----- .../Model/CacheableQueryHandler.php | 103 ++++++++++++++++++ .../Model/Plugin/Query/Resolver.php | 85 +++------------ .../Magento/GraphQl/Catalog/CategoryTest.php | 1 + .../GraphQl/Config/GraphQlReaderTest.php | 7 +- .../Controller/GraphQlControllerTest.php | 23 +++- .../GraphQl/Query/Resolver/ValueFactory.php | 27 ++++- 7 files changed, 196 insertions(+), 106 deletions(-) create mode 100644 app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php index cb392a7b2295d..b31144368aa68 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php @@ -94,35 +94,39 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $this->categoryIds = array_merge($this->categoryIds, $categoryIds); $that = $this; - return $this->valueFactory->create(function () use ($that, $categoryIds, $info) { - $categories = []; - if (empty($that->categoryIds)) { - return []; - } + return $this->valueFactory->create( + function () use ($that, $categoryIds, $info) { + $categories = []; + if (empty($that->categoryIds)) { + return []; + } - if (!$this->collection->isLoaded()) { - $that->attributesJoiner->join($info->fieldNodes[0], $this->collection); - $this->collection->addIdFilter($this->categoryIds); - } - /** @var CategoryInterface | \Magento\Catalog\Model\Category $item */ - foreach ($this->collection as $item) { - if (in_array($item->getId(), $categoryIds)) { - // Try to extract all requested fields from the loaded collection data - $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item, true); - $categories[$item->getId()]['model'] = $item; - $requestedFields = $that->attributesJoiner->getQueryFields($info->fieldNodes[0]); - $extractedFields = array_keys($categories[$item->getId()]); - $foundFields = array_intersect($requestedFields, $extractedFields); - if (count($requestedFields) === count($foundFields)) { - continue; - } + if (!$this->collection->isLoaded()) { + $that->attributesJoiner->join($info->fieldNodes[0], $this->collection); + $this->collection->addIdFilter($this->categoryIds); + } + /** @var CategoryInterface | \Magento\Catalog\Model\Category $item */ + foreach ($this->collection as $item) { + if (in_array($item->getId(), $categoryIds)) { + // Try to extract all requested fields from the loaded collection data + $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item, true); + $categories[$item->getId()]['model'] = $item; + $requestedFields = $that->attributesJoiner->getQueryFields($info->fieldNodes[0]); + $extractedFields = array_keys($categories[$item->getId()]); + $foundFields = array_intersect($requestedFields, $extractedFields); + if (count($requestedFields) === count($foundFields)) { + continue; + } - // If not all requested fields were extracted from the collection, start more complex extraction - $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item); + // If not all requested fields were extracted from the collection, start more complex extraction + $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item); + } } - } - return $categories; - }); + return $categories; + }, + $field, + $info + ); } } diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php new file mode 100644 index 0000000000000..405b8b0473eea --- /dev/null +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -0,0 +1,103 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Model; + +use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\GraphQl\Query\Resolver\Value; + +class CacheableQueryHandler +{ + /** + * @var CacheableQuery + */ + private $cacheableQuery; + + /** + * @var RequestInterface + */ + private $request; + + /** + * @param CacheableQuery $cacheableQuery + * @param RequestInterface $request + */ + public function __construct(CacheableQuery $cacheableQuery, RequestInterface $request) + { + $this->cacheableQuery = $cacheableQuery; + $this->request = $request; + } + + /** + * Set cache validity to the cacheableQuery after resolving any resolver or evaluating a promise in a query + * + * @param mixed $resolvedValue + * @param Field|null $field + * @param ResolveInfo|null $info + */ + public function handleCacheFromResolverResponse(array $resolvedValue, Field $field) + { + $cache = $field->getCache(); + $cacheTag = isset($cache['cache_tag']) ? $cache['cache_tag'] : []; + $cacheable = isset($cache['cacheable']) ? $cache['cacheable'] : true; + if (!empty($cacheTag) && $this->request->isGet() && $cacheable) { + $cacheTags = []; + // Resolved value must have cache IDs defined + $resolvedItemsIds = $this->extractResolvedItemsIds($resolvedValue); + if (!empty($resolvedItemsIds)) { + $cacheTags = [$cacheTag]; + } + foreach ($resolvedItemsIds as $itemId) { + $cacheTags[] = $cacheTag . '_' . $itemId; + } + $this->cacheableQuery->addCacheTags($cacheTags); + } + $this->setCacheValidity($cacheable); + } + + /** + * Extract ids for resolved items + * + * @param mixed|Value $resolvedValue + * @return array + */ + private function extractResolvedItemsIds(array $resolvedValue) : array + { + $ids = []; + if (isset($resolvedValue['ids']) && is_array($resolvedValue['ids'])) { + return $resolvedValue['ids']; + } + if (isset($resolvedValue['items']) && is_array($resolvedValue['items'])) { + return array_keys($resolvedValue['items']); + } + + if (isset($resolvedValue['id'])) { + $ids[] = $resolvedValue['id']; + return $ids; + } + + foreach ($resolvedValue as $item) { + if (isset($item['id'])) { + $ids[] = $item['id']; + } + } + return $ids; + } + + /** + * Set cache validity for the graphql request + * + * @param bool $isValid + */ + private function setCacheValidity(bool $isValid): void + { + $cacheValidity = $this->cacheableQuery->isCacheable() && $isValid; + $this->cacheableQuery->setCacheValidity($cacheValidity); + } +} \ No newline at end of file diff --git a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php index 4fad3ede4e5bc..ee14ba3bbdc94 100644 --- a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php +++ b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php @@ -11,8 +11,8 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\GraphQl\Model\Query\Resolver\Context; -use Magento\GraphQlCache\Model\CacheableQuery; -use Magento\Framework\App\RequestInterface; +use Magento\Framework\GraphQl\Query\Resolver\Value; +use Magento\GraphQlCache\Model\CacheableQueryHandler; /** * Plugin to handle cache validation that can be done after each resolver @@ -20,30 +20,24 @@ class Resolver { /** - * @var CacheableQuery + * @var CacheableQueryHandler */ - private $cacheableQuery; + private $cacheableQueryHandler; /** - * @var Request + * @param CacheableQueryHandler $cacheableQueryHandler */ - private $request; - - /** - * @param CacheableQuery $cacheableQuery - * @param RequestInterface $request - */ - public function __construct(CacheableQuery $cacheableQuery, RequestInterface $request) - { - $this->cacheableQuery = $cacheableQuery; - $this->request = $request; + public function __construct( + CacheableQueryHandler $cacheableQueryHandler + ) { + $this->cacheableQueryHandler = $cacheableQueryHandler; } /** * Set cache validity to the cacheableQuery after resolving any resolver in a query * * @param ResolverInterface $subject - * @param Object $resolvedValue + * @param mixed|Value $resolvedValue * @param Field $field * @param Context $context * @param ResolveInfo $info @@ -61,63 +55,10 @@ public function afterResolve( array $value = null, array $args = null ) { - $cache = $field->getCache(); - $cacheTag = isset($cache['cache_tag']) ? $cache['cache_tag'] : []; - $cacheable = isset($cache['cacheable']) ? $cache['cacheable'] : true; - if (!empty($cacheTag) && $this->request->isGet() && $cacheable) { - $cacheTags = []; - // Resolved value must have cache IDs defined - $resolvedItemsIds = $this->extractResolvedItemsIds($resolvedValue); - if (!empty($resolvedItemsIds)) { - $cacheTags = [$cacheTag]; - } - foreach ($resolvedItemsIds as $itemId) { - $cacheTags[] = $cacheTag . '_' . $itemId; - } - $this->cacheableQuery->addCacheTags($cacheTags); - } - $this->setCacheValidity($cacheable); - return $resolvedValue; - } - - /** - * Extract ids for resolved items - * - * @param Object $resolvedValue - * @return array - */ - private function extractResolvedItemsIds($resolvedValue) : array - { - if (isset($resolvedValue['ids']) && is_array($resolvedValue['ids'])) { - return $resolvedValue['ids']; - } - if (isset($resolvedValue['items']) && is_array($resolvedValue['items'])) { - return array_keys($resolvedValue['items']); - } - $ids = []; - if (isset($resolvedValue['id'])) { - $ids[] = $resolvedValue['id']; - return $ids; - } - + /** Only if array @see \Magento\Framework\GraphQl\Query\Resolver\Value */ if (is_array($resolvedValue)) { - foreach ($resolvedValue as $item) { - if (isset($item['id'])) { - $ids[] = $item['id']; - } - } + $this->cacheableQueryHandler->handleCacheFromResolverResponse($resolvedValue, $field); } - return $ids; - } - - /** - * Set cache validity for the graphql request - * - * @param bool $isValid - */ - private function setCacheValidity(bool $isValid): void - { - $cacheValidity = $this->cacheableQuery->isCacheable() && $isValid; - $this->cacheableQuery->setCacheValidity($cacheValidity); + return $resolvedValue; } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php index b2ce0400f7d83..63073a389f278 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php @@ -347,6 +347,7 @@ public function testCategoryProducts() $this->assertAttributes($response['category']['products']['items'][0]); $this->assertWebsites($firstProduct, $response['category']['products']['items'][0]['websites']); } + /** * @magentoApiDataFixture Magento/Catalog/_files/categories.php */ diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php index 10a6b9d8caae4..61cbd556ea235 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php @@ -183,7 +183,12 @@ enumValues(includeDeprecated: true) { $headers = $this->objectManager->create(\Zend\Http\Headers::class) ->addHeaders(['Content-Type' => 'application/json']); $request->setHeaders($headers); - $response = $this->graphQlController->dispatch($request); + + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->create(\Magento\Framework\App\Response\Http::class); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphQlController->dispatch($request); + $result->renderResult($response); $output = $this->jsonSerializer->unserialize($response->getContent()); $expectedOutput = require __DIR__ . '/../_files/schema_response_sdl_description.php'; diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php index d0d746812ec44..49cdca8372593 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php @@ -101,7 +101,11 @@ public function testDispatch() : void $headers = $this->objectManager->create(\Zend\Http\Headers::class) ->addHeaders(['Content-Type' => 'application/json']); $this->request->setHeaders($headers); - $response = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->create(\Magento\Framework\App\Response\Http::class); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + $result->renderResult($response); $output = $this->jsonSerializer->unserialize($response->getContent()); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); @@ -143,7 +147,11 @@ public function testDispatchWithGet() : void $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); - $response = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->create(\Magento\Framework\App\Response\Http::class); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + $result->renderResult($response); $output = $this->jsonSerializer->unserialize($response->getContent()); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); @@ -195,6 +203,11 @@ public function testDispatchGetWithParameterizedVariables() : void $this->request->setMethod('GET'); $this->request->setParams($queryParams); $response = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->create(\Magento\Framework\App\Response\Http::class); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + $result->renderResult($response); $output = $this->jsonSerializer->unserialize($response->getContent()); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); @@ -244,7 +257,11 @@ public function testError() : void $headers = $this->objectManager->create(\Zend\Http\Headers::class) ->addHeaders(['Content-Type' => 'application/json']); $this->request->setHeaders($headers); - $response = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->create(\Magento\Framework\App\Response\Http::class); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + $result->renderResult($response); $outputResponse = $this->jsonSerializer->unserialize($response->getContent()); if (isset($outputResponse['errors'][0])) { if (is_array($outputResponse['errors'][0])) { diff --git a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php index 5bd34224bb077..7f4c0da5bc0f8 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php @@ -8,6 +8,9 @@ namespace Magento\Framework\GraphQl\Query\Resolver; use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\GraphQlCache\Model\CacheableQueryHandler; /** * Create @see Value to return data from passed in callback to GraphQL library @@ -19,22 +22,38 @@ class ValueFactory */ private $objectManager; + /** + * @var CacheableQueryHandler + */ + private $cacheableQueryHandler; + /** * @param ObjectManagerInterface $objectManager + * @param CacheableQueryHandler $cacheableQueryHandler */ - public function __construct(ObjectManagerInterface $objectManager) + public function __construct(ObjectManagerInterface $objectManager, CacheableQueryHandler $cacheableQueryHandler) { $this->objectManager = $objectManager; + $this->cacheableQueryHandler = $cacheableQueryHandler; } /** - * Create value with passed in callback that returns data as parameter; + * Create value with passed in callback that returns data as parameter * * @param callable $callback + * @param ResolveInfo $info * @return Value + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function create(callable $callback) + public function create(callable $callback, Field $field = null, ResolveInfo $info = null) : Value { - return $this->objectManager->create(Value::class, ['callback' => $callback]); + /** @var \Magento\Framework\GraphQl\Query\Resolver\Value $value */ + $value = $this->objectManager->create(Value::class, ['callback' => $callback]); + $value->then(function () use ($value, $field, $info) { + if (is_array($value->promise->result) && $field) { + $this->cacheableQueryHandler->handleCacheFromResolverResponse($value->promise->result, $field); + } + }); + return $value; } } From 8e8dc28bc55e5bda8a1b98c97d044efc4529e32f Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 10 Apr 2019 11:30:56 +0300 Subject: [PATCH 221/585] graphQl-533: fixed set purchase order --- .../Model/Resolver/SetPaymentMethodOnCart.php | 5 +-- .../Customer/SetPaymentMethodOnCartTest.php | 38 +++++++++++++++++++ .../Guest/SetPaymentMethodOnCartTest.php | 38 +++++++++++++++++++ 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php index d1dcb4a48a76b..7d8933975779d 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php @@ -69,10 +69,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $paymentMethodCode = $args['input']['payment_method']['code']; - $poNumber = isset($args['input']['payment_method']['purchase_order_number']) - && empty($args['input']['payment_method']['purchase_order_number']) - ? $args['input']['payment_method']['purchase_order_number'] - : null; + $poNumber = $args['input']['payment_method']['purchase_order_number'] ?? null; $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); $payment = $this->paymentFactory->create([ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 73feefe2b094b..8241debc8b09c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -60,6 +60,44 @@ public function testSetPaymentOnCartWithSimpleProduct() self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + */ + public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() + { + $methodCode = Checkmo::PAYMENT_METHOD_CHECKMO_CODE; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "$maskedQuoteId" + payment_method: { + code: "$methodCode", + purchase_order_number: "123456" + } + }) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + } + /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php index 879d0fd917291..9dfb6b4c15a61 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php @@ -10,6 +10,7 @@ use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\OfflinePayments\Model\Cashondelivery; use Magento\OfflinePayments\Model\Checkmo; +use Magento\OfflinePayments\Model\Purchaseorder; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -52,6 +53,43 @@ public function testSetPaymentOnCartWithSimpleProduct() self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); } + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + */ + public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() + { + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "{$maskedQuoteId}", + payment_method: { + code: "{$methodCode}", + purchase_order_number: "123456" + } + }) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + } + /** * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php From 62fed32a567bbdf018b0b0c8e9631d44cc48194d Mon Sep 17 00:00:00 2001 From: Rafael Kassner <kassner@gmail.com> Date: Wed, 10 Apr 2019 12:20:12 +0200 Subject: [PATCH 222/585] Show the correct subtotal amount for partial creditmemos --- .../frontend/templates/email/items/creditmemo/default.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/view/frontend/templates/email/items/creditmemo/default.phtml b/app/code/Magento/Sales/view/frontend/templates/email/items/creditmemo/default.phtml index 1fca65932b0b0..20c2c1869fedb 100644 --- a/app/code/Magento/Sales/view/frontend/templates/email/items/creditmemo/default.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/email/items/creditmemo/default.phtml @@ -31,6 +31,6 @@ </td> <td class="item-qty"><?= /* @escapeNotVerified */ $_item->getQty() * 1 ?></td> <td class="item-price"> - <?= /* @escapeNotVerified */ $block->getItemPrice($_item->getOrderItem()) ?> + <?= /* @escapeNotVerified */ $block->getItemPrice($_item) ?> </td> </tr> From 9f41eb6fd9acd74f20138d844059eaf9115041fa Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Wed, 10 Apr 2019 14:23:08 +0300 Subject: [PATCH 223/585] Fix static test. --- app/code/Magento/Review/Block/Adminhtml/Edit/Form.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php b/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php index 8ca6d695113b9..4f7237a0b44be 100644 --- a/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php +++ b/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php @@ -4,11 +4,11 @@ * See COPYING.txt for license details. */ +namespace Magento\Review\Block\Adminhtml\Edit; + /** * Adminhtml Review Edit Form */ -namespace Magento\Review\Block\Adminhtml\Edit; - class Form extends \Magento\Backend\Block\Widget\Form\Generic { /** From 4e15099e35a4493c3925d10d1b2df1623ab6e3b7 Mon Sep 17 00:00:00 2001 From: Yuriy <Vechirko.Yuriy@gmail.com> Date: Wed, 10 Apr 2019 14:27:08 +0300 Subject: [PATCH 224/585] tests_correct --- .../Magento/Catalog/Model/Product/Copier.php | 12 +++- .../Test/Unit/Model/Product/CopierTest.php | 57 ++++++++++++++----- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Copier.php b/app/code/Magento/Catalog/Model/Product/Copier.php index 2cd9304af7890..3e899decaeb55 100644 --- a/app/code/Magento/Catalog/Model/Product/Copier.php +++ b/app/code/Magento/Catalog/Model/Product/Copier.php @@ -117,13 +117,21 @@ private function setDefaultUrl(Product $product, Product $duplicate) : void private function setStoresUrl(Product $product, Product $duplicate) : void { $storeIds = $duplicate->getStoreIds(); - $resource = $product->getResource(); $productId = $product->getId(); + $productResource = $product->getResource(); + $defaultUrlKey = $productResource->getAttributeRawValue( + $productId, + 'url_key', + \Magento\Store\Model\Store::DEFAULT_STORE_ID + ); $duplicate->setData('save_rewrites_history', false); foreach ($storeIds as $storeId) { $isDuplicateSaved = false; $duplicate->setStoreId($storeId); - $urlKey = $resource->getAttributeRawValue($productId, 'url_key', $storeId); + $urlKey = $productResource->getAttributeRawValue($productId, 'url_key', $storeId); + if ($urlKey === $defaultUrlKey) { + continue; + } do { $urlKey = $this->modifyUrl($urlKey); $duplicate->setUrlKey($urlKey); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php index e9eee5c766883..7ae5f70285faa 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php @@ -103,8 +103,44 @@ public function testCopy() ['linkField', null, '1'], ]); - $resourceMock = $this->createMock(\Magento\Catalog\Model\ResourceModel\Product::class); - $this->productMock->expects($this->once())->method('getResource')->will($this->returnValue($resourceMock)); + $entityMock = $this->getMockForAbstractClass( + \Magento\Eav\Model\Entity\AbstractEntity::class, + [], + '', + false, + true, + true, + ['checkAttributeUniqueValue'] + ); + $entityMock->expects($this->any()) + ->method('checkAttributeUniqueValue') + ->willReturn(true); + + $attributeMock = $this->getMockForAbstractClass( + \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class, + [], + '', + false, + true, + true, + ['getEntity'] + ); + $attributeMock->expects($this->any()) + ->method('getEntity') + ->willReturn($entityMock); + + $resourceMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product::class) + ->disableOriginalConstructor() + ->setMethods(['getAttributeRawValue', 'duplicate', 'getAttribute']) + ->getMock(); + $resourceMock->expects($this->any()) + ->method('getAttributeRawValue') + ->willReturn('urk-key-1'); + $resourceMock->expects($this->any()) + ->method('getAttribute') + ->willReturn($attributeMock); + + $this->productMock->expects($this->any())->method('getResource')->will($this->returnValue($resourceMock)); $duplicateMock = $this->createPartialMock( Product::class, @@ -119,11 +155,11 @@ public function testCopy() 'setCreatedAt', 'setUpdatedAt', 'setId', - 'setStoreId', 'getEntityId', 'save', 'setUrlKey', - 'getUrlKey', + 'setStoreId', + 'getStoreIds', ] ); $this->productFactoryMock->expects($this->once())->method('create')->will($this->returnValue($duplicateMock)); @@ -138,19 +174,13 @@ public function testCopy() )->with( \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED ); + $duplicateMock->expects($this->atLeastOnce())->method('setStoreId'); $duplicateMock->expects($this->once())->method('setCreatedAt')->with(null); $duplicateMock->expects($this->once())->method('setUpdatedAt')->with(null); $duplicateMock->expects($this->once())->method('setId')->with(null); - $duplicateMock->expects( - $this->once() - )->method( - 'setStoreId' - )->with( - \Magento\Store\Model\Store::DEFAULT_STORE_ID - ); + $duplicateMock->expects($this->atLeastOnce())->method('getStoreIds')->willReturn([]); $duplicateMock->expects($this->atLeastOnce())->method('setData')->willReturn($duplicateMock); $this->copyConstructorMock->expects($this->once())->method('build')->with($this->productMock, $duplicateMock); - $duplicateMock->expects($this->once())->method('getUrlKey')->willReturn('urk-key-1'); $duplicateMock->expects($this->once())->method('setUrlKey')->with('urk-key-2')->willReturn($duplicateMock); $duplicateMock->expects($this->once())->method('save'); @@ -158,7 +188,8 @@ public function testCopy() $duplicateMock->expects($this->any())->method('getData')->willReturnMap([ ['linkField', null, '2'], - ]); $this->optionRepositoryMock->expects($this->once()) + ]); + $this->optionRepositoryMock->expects($this->once()) ->method('duplicate') ->with($this->productMock, $duplicateMock); $resourceMock->expects($this->once())->method('duplicate')->with(1, 2); From ce4af9e43627d6d31acb0cb5a8a841e81a830a82 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 10 Apr 2019 15:01:12 +0300 Subject: [PATCH 225/585] magento/magento2#20772: Static test fix. --- app/code/Magento/Integration/Model/AdminTokenService.php | 2 +- .../Integration/Test/Unit/Model/AdminTokenServiceTest.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Integration/Model/AdminTokenService.php b/app/code/Magento/Integration/Model/AdminTokenService.php index 084d111a93f85..7726ff979c6d7 100644 --- a/app/code/Magento/Integration/Model/AdminTokenService.php +++ b/app/code/Magento/Integration/Model/AdminTokenService.php @@ -72,7 +72,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function createAdminAccessToken($username, $password) { diff --git a/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php index ef7cb549cab2b..83efe4074e15f 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php @@ -8,6 +8,9 @@ use Magento\Integration\Model\Oauth\Token; +/** + * Test for Magento\Integration\Model\AdminTokenService class. + */ class AdminTokenServiceTest extends \PHPUnit\Framework\TestCase { /** \Magento\Integration\Model\AdminTokenService */ From 4229953752aa4ba48cb9beaa679c2a300d666658 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Wed, 10 Apr 2019 15:33:58 +0300 Subject: [PATCH 226/585] MC-12180: Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie --- .../AdminCreateWidgetActionGroup.xml | 17 +++ .../Catalog/Test/Mftf/Data/WidgetsData.xml | 20 ++++ .../catalog_recently_products-meta.xml | 3 +- .../Test/Mftf/Page/AdminNewWidgetPage.xml | 1 + .../AdminCatalogProductWidgetSection.xml | 15 +++ .../Mftf/Section/StorefrontWidgetsSection.xml | 16 +++ ...listIsPersistedUnderLongTermCookieTest.xml | 105 +++++++++--------- .../AdminCreateWidgetActionGroup.xml | 6 - .../Widget/Test/Mftf/Data/WidgetsData.xml | 20 ---- .../Mftf/Section/AdminNewWidgetSection.xml | 2 - .../Mftf/Section/StorefrontWidgetsSection.xml | 3 - 11 files changed, 122 insertions(+), 86 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Section/AdminCatalogProductWidgetSection.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml new file mode 100644 index 0000000000000..dd66919640a73 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateRecentlyProductsWidgetActionGroup" extends="AdminCreateWidgetActionGroup"> + <selectOption selector="{{AdminCatalogProductWidgetSection.productAttributesToShow}}" parameterArray="['Name', 'Image', 'Price']" stepKey="selectAllProductAttributes"/> + <selectOption selector="{{AdminCatalogProductWidgetSection.productButtonsToShow}}" parameterArray="['Add to Cart', 'Add to Compare', 'Add to Wishlist']" stepKey="selectAllProductButtons"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> + <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" stepKey="waitForSuccessMessageAppears"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/WidgetsData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/WidgetsData.xml index 83f0a56c21545..18564ff101fd9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/WidgetsData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/WidgetsData.xml @@ -12,4 +12,24 @@ <data key="type">Catalog Product Link</data> <data key="template">Product Link Block Template</data> </entity> + <entity name="RecentlyComparedProductsWidget" type="widget"> + <data key="type">Recently Compared Products</data> + <data key="design_theme">Magento Luma</data> + <data key="name" unique="suffix">Recently Compared Products</data> + <array key="store_ids"> + <item>All Store Views</item> + </array> + <data key="display_on">All Pages</data> + <data key="container">Sidebar Additional</data> + </entity> + <entity name="RecentlyViewedProductsWidget" type="widget"> + <data key="type">Recently Viewed Products</data> + <data key="design_theme">Magento Luma</data> + <data key="name" unique="suffix">Recently Viewed Products</data> + <array key="store_ids"> + <item>All Store Views</item> + </array> + <data key="display_on">All Pages</data> + <data key="container">Sidebar Additional</data> + </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml b/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml index dad4f5420d461..0fe4f154d5ef5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml @@ -6,7 +6,8 @@ */ --> <operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> - <operation name="CatalogRecentlyProductsConfiguration" dataType="catalog_recently_products" type="create" auth="adminFormKey" url="/admin/system_config/save/section/catalog/" method="POST"> + <operation name="CatalogRecentlyProductsConfiguration" dataType="catalog_recently_products" type="create" + auth="adminFormKey" url="/admin/system_config/save/section/catalog/" method="POST" successRegex="/messages-message-success/"> <object key="groups" dataType="catalog_recently_products"> <object key="recently_products" dataType="catalog_recently_products"> <object key="fields" dataType="catalog_recently_products"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/AdminNewWidgetPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/AdminNewWidgetPage.xml index e23a503266e33..dd5d5aef08a7c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Page/AdminNewWidgetPage.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Page/AdminNewWidgetPage.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminNewWidgetPage" url="admin/widget_instance/new/" area="admin" module="Magento_Widget"> <section name="AdminNewWidgetSelectProductPopupSection"/> + <section name="AdminCatalogProductWidgetSection"/> </page> </pages> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCatalogProductWidgetSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCatalogProductWidgetSection.xml new file mode 100644 index 0000000000000..3261db1f63f24 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCatalogProductWidgetSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCatalogProductWidgetSection"> + <element name="productAttributesToShow" type="multiselect" selector="select[name='parameters[show_attributes][]']"/> + <element name="productButtonsToShow" type="multiselect" selector="select[name='parameters[show_buttons][]']"/> + </section> +</sections> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml new file mode 100644 index 0000000000000..dbe5ddcc366f1 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontWidgetsSection"> + <element name="widgetRecentlyViewedProductsGrid" type="block" selector=".block.widget.block-viewed-products-grid" timeout="30"/> + <element name="widgetRecentlyComparedProductsGrid" type="block" selector=".block.widget.block-compared-products-grid" timeout="30"/> + <element name="widgetRecentlyOrderedProductsGrid" type="block" selector=".block.block-reorder" timeout="30"/> + </section> +</sections> \ No newline at end of file diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml index b47c5f9571931..220d6b656c384 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml @@ -11,12 +11,13 @@ <test name="StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest"> <annotations> <features value="Persistent"/> - <stories value="Check the widgets is persisted"/> + <stories value="Catalog widget"/> <title value="Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie"/> <description value="Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie"/> <severity value="CRITICAL"/> <testCaseId value="MC-12180"/> <group value="persistent"/> + <group value="widget"/> <skip> <issueId value="MC-15741"/> </skip> @@ -29,7 +30,7 @@ <createData entity="_defaultProduct" stepKey="createSimpleProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <createData entity="SimpleProduct" stepKey="createSimpleProduct2"> + <createData entity="SimpleProduct" stepKey="createSecondSimpleProduct"> <requiredEntity createDataKey="createCategory"/> </createData> <createData entity="Simple_US_Customer" stepKey="createCustomer"/> @@ -48,7 +49,7 @@ <createData entity="DisableSynchronizeWidgetProductsWithBackendStorage" stepKey="disableSynchronizeWidgetProductsWithBackendStorage"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <deleteData createDataKey="createSimpleProduct2" stepKey="deleteSimpleProduct2"/> + <deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutFromCustomer"/> @@ -62,66 +63,62 @@ </after> <!--Login to storefront from customer--> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginCustomer"> <argument name="Customer" value="$$createCustomer$$"/> </actionGroup> - <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessage"/> <!--Open the details page of Simple Product 1, Simple Product 2 and add to cart, get to the category--> - <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart"> + <actionGroup ref="AddSimpleProductToCart" stepKey="addSimpleProductProductToCart"> <argument name="product" value="$$createSimpleProduct$$"/> </actionGroup> - <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart2"> - <argument name="product" value="$$createSimpleProduct2$$"/> + <actionGroup ref="AddSimpleProductToCart" stepKey="addSecondSimpleProductProductToCart"> + <argument name="product" value="$$createSecondSimpleProduct$$"/> </actionGroup> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage3"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterAddedProductToCart"/> <!--The Recently Viewed widget displays Simple Product 1 and Simple Product 2--> <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" stepKey="waitWidgetRecentlyViewedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct2.name$$" stepKey="seeProduct2InRecentlyViewedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeSimpleProductInRecentlyViewedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSecondSimpleProduct.name$$" stepKey="seeSecondSimpleProductInRecentlyViewedWidget"/> <!--Add Simple Product 1 and Simple Product 2 to Wishlist--> - <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProduct1ToWishlist"> + <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProductToWishlist"> <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage4"/> - <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProduct2ToWishlist"> - <argument name="productVar" value="$$createSimpleProduct2$$"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterProductAddToWishlist"/> + <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSecondSimpleProductToWishlist"> + <argument name="productVar" value="$$createSecondSimpleProduct$$"/> </actionGroup> <!--The My Wishlist widget displays Simple Product 1 and Simple Product 2--> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage5"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageToCheckProductsInWishlistSidebar"/> <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebar"> <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProduct2InWishlistSidebar"> - <argument name="productVar" value="$$createSimpleProduct2$$"/> + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSecondSimpleProductInWishlistSidebar"> + <argument name="productVar" value="$$createSecondSimpleProduct$$"/> </actionGroup> <!--Add to compare Simple Product and Simple Product 2--> - <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="compareAddSimpleProduct1ToCompare" > + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="addSimpleProductToCompare" > <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="compareAddSimpleProduct2ToCompare" > - <argument name="productVar" value="$$createSimpleProduct2$$"/> + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="addSecondSimpleProductToCompare" > + <argument name="productVar" value="$$createSecondSimpleProduct$$"/> </actionGroup> <!--The Compare Products widget displays Simple Product 1 and Simple Product 2--> - <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="compareSimpleProduct1InSidebar"> + <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="checkSimpleProductInCompareSidebar"> <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="compareSimpleProduct2InSidebar"> - <argument name="productVar" value="$$createSimpleProduct2$$"/> + <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="checkSecondSimpleProductInCompareSidebar"> + <argument name="productVar" value="$$createSecondSimpleProduct$$"/> </actionGroup> <!--Click Clear all in the Compare Products widget--> - <waitForElementVisible selector="{{WidgetSection.ClearCompare}}" stepKey="waitForClearCompareBtn"/> - <click selector="{{WidgetSection.ClearCompare}}" stepKey="clickClearCompareBtn"/> - <waitForElementVisible selector="{{WidgetSection.AcceptClear}}" stepKey="waitForAcceptBtn"/> - <click selector="{{WidgetSection.AcceptClear}}" stepKey="acceptClearCompare"/> - <waitForPageLoad stepKey="waitForPageLoad"/> + <actionGroup ref="StorefrontClearCompareActionGroup" stepKey="asd"/> <!--The Recently Compared widget displays Simple Product 1 and Simple Product 2--> <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" stepKey="waitWidgetRecentlyComparedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct2InRecentlyComparedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSecondSimpleProductInRecentlyComparedWidget"/> <!--Place the order--> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToShoppingCartPage"/> @@ -129,41 +126,41 @@ <argument name="shippingMethod" value="Flat Rate"/> </actionGroup> <!--The Recently Ordered widget displays Simple Product 1 and Simple Product 2--> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage6"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageToCheckProductsInRecentlyOrderedWidget"/> <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" stepKey="waitWidgetRecentlyOrderedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct2InRecentlyOrderedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSecondSimpleProductInRecentlyOrderedWidget"/> <!--Sign out and check that widgets persist the information about the items--> - <actionGroup ref="StorefrontSignOutActionGroup" stepKey="storefrontSignOut"/> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage7"/> - <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome2"/> - <seeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkLinkNotYoy"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget2"/> - <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebar2"> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="logoutFromCustomerToCheckThatWidgetsPersist"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterLogoutFromCustomer"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterLogoutFromCustomer"/> + <seeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkLinkNotYouAfterLogoutFromCustomer"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogout"/> + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebarAfterLogout"> <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget2"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget2"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogout"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogout"/> <!--Click the *Not you?* link and check the price for Simple Product--> - <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickNext"/> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage8"/> - <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome3"/> - <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProduct1InRecentlyViewedWidget"/> - <dontSee selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="dontSeeProduct1InWishlistWidget"/> + <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickLinkNotYou"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterClickNotYou"/> + <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterClickLinkNotYou"/> + <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyViewedWidget"/> + <dontSee selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="dontSeeProductInWishlistWidget"/> <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyComparedWidget"/> <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyOrderedWidget"/> <!--Login to storefront from customer again--> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer2"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomerAfterClearLongTermCookie"> <argument name="Customer" value="$$createCustomer$$"/> </actionGroup> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage9"/> - <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome4"/> - <waitForElementVisible selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="assertWishlistSidebarProductName"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget3"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget3"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget3"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageToCheckWidgets"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterLogin"/> + <waitForElementVisible selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="checkSimpleProductNameInWishlistSidebarAfterLogin"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogin"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogin"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogin"/> </test> </tests> diff --git a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml index 5d2b894b86438..969ab58b04876 100644 --- a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml +++ b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml @@ -78,10 +78,4 @@ <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> </actionGroup> - <actionGroup name="AdminCreateRecentlyProductsWidgetActionGroup" extends="AdminCreateWidgetActionGroup"> - <selectOption selector="{{AdminNewWidgetSection.productAttributesToShow}}" parameterArray="['Name', 'Image', 'Price']" stepKey="selectAllProductAttributes"/> - <selectOption selector="{{AdminNewWidgetSection.productButtonsToShow}}" parameterArray="['Add to Cart', 'Add to Compare', 'Add to Wishlist']" stepKey="selectAllProductButtons"/> - <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> - <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml index 370077f6feefa..27222298408de 100644 --- a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml +++ b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml @@ -32,24 +32,4 @@ <data key="display_mode">Cart Price Rule Related</data> <data key="restrict_type">Header</data> </entity> - <entity name="RecentlyComparedProductsWidget" type="widget"> - <data key="type">Recently Compared Products</data> - <data key="design_theme">Magento Luma</data> - <data key="name" unique="suffix">Recently Compared Products</data> - <array key="store_ids"> - <item>All Store Views</item> - </array> - <data key="display_on">All Pages</data> - <data key="container">Sidebar Additional</data> - </entity> - <entity name="RecentlyViewedProductsWidget" type="widget"> - <data key="type">Recently Viewed Products</data> - <data key="design_theme">Magento Luma</data> - <data key="name" unique="suffix">Recently Viewed Products</data> - <array key="store_ids"> - <item>All Store Views</item> - </array> - <data key="display_on">All Pages</data> - <data key="container">Sidebar Additional</data> - </entity> </entities> diff --git a/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml index 8abd8cb142016..eebd6c10b5085 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml @@ -35,7 +35,5 @@ <element name="displayMode" type="select" selector="select[id*='display_mode']"/> <element name="restrictTypes" type="select" selector="select[id*='types']"/> <element name="saveAndContinue" type="button" selector="#save_and_edit_button" timeout="30"/> - <element name="productAttributesToShow" type="multiselect" selector="select[name='parameters[show_attributes][]']"/> - <element name="productButtonsToShow" type="multiselect" selector="select[name='parameters[show_buttons][]']"/> </section> </sections> diff --git a/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml index cf6bfc484cc57..0e2f6cec73a92 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml @@ -11,8 +11,5 @@ <section name="StorefrontWidgetsSection"> <element name="widgetProductsGrid" type="block" selector=".block.widget.block-products-list.grid"/> <element name="widgetProductName" type="text" selector=".product-item-name"/> - <element name="widgetRecentlyViewedProductsGrid" type="block" selector=".block.widget.block-viewed-products-grid" timeout="30"/> - <element name="widgetRecentlyComparedProductsGrid" type="block" selector=".block.widget.block-compared-products-grid" timeout="30"/> - <element name="widgetRecentlyOrderedProductsGrid" type="block" selector=".block.block-reorder" timeout="30"/> </section> </sections> From ec2c6ca7df68de9aaccecfb899b102a2a3eaa631 Mon Sep 17 00:00:00 2001 From: Ryan Palmer <ryan.palmer@hub-mdp.co.uk> Date: Wed, 10 Apr 2019 10:28:51 +0100 Subject: [PATCH 227/585] Prevented /Magento/Sales/Model/Service/InvoiceService.php incorrectly discarding simple items when bundle items are mixed in a call to prepareInvoice without any qtys specified Renamed emptyQtys to isQtysEmpty --- app/code/Magento/Sales/Model/Service/InvoiceService.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Service/InvoiceService.php b/app/code/Magento/Sales/Model/Service/InvoiceService.php index 02242e92c8bf5..18efeba726c1b 100644 --- a/app/code/Magento/Sales/Model/Service/InvoiceService.php +++ b/app/code/Magento/Sales/Model/Service/InvoiceService.php @@ -149,6 +149,7 @@ public function setVoid($id) */ public function prepareInvoice(Order $order, array $qtys = []) { + $isQtysEmpty = empty($qtys); $invoice = $this->orderConverter->toInvoice($order); $totalQty = 0; $qtys = $this->prepareItemsQty($order, $qtys); @@ -161,7 +162,7 @@ public function prepareInvoice(Order $order, array $qtys = []) $qty = (double) $qtys[$orderItem->getId()]; } elseif ($orderItem->isDummy()) { $qty = $orderItem->getQtyOrdered() ? $orderItem->getQtyOrdered() : 1; - } elseif (empty($qtys)) { + } elseif ($isQtysEmpty) { $qty = $orderItem->getQtyToInvoice(); } else { $qty = 0; From 01b133aab5bd123245c1799e717ca0cc21588c35 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Wed, 10 Apr 2019 10:16:41 -0500 Subject: [PATCH 228/585] MC-4575: Convert CreateCustomerSegmentEntityWithCustomerConditionsPartTwoTest to MFTF --- .../StorefrontCheckCartDiscountAndSummaryActionGroup.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml index 115fbc4993e58..b9e2b38e9af7f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml @@ -14,6 +14,8 @@ <argument name="total" type="string"/> <argument name="discount" type="string"/> </arguments> + <waitForPageLoad stepKey="waitForPageLoad"/> + <waitForLoadingMaskToDisappear stepKey="waitForPrices"/> <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-${{discount}}" stepKey="assertDiscount"/> <see selector="{{CheckoutCartSummarySection.total}}" userInput="${{total}}" stepKey="assertTotal"/> </actionGroup> From e6bbd096492264056e21bc71d4ef93cc56f8e6f5 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Wed, 10 Apr 2019 10:17:49 -0500 Subject: [PATCH 229/585] MQE-1478: Fix all existing deprecation warnings in 2.3-develop --- .../Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml | 1 + .../Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml | 1 + .../Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml | 1 + .../Test/AdminImportCustomizableOptionToProductWithSKUTest.xml | 1 + .../Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml | 1 + ...rPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml | 1 + .../Test/ProductAvailableAfterEnablingSubCategoriesTest.xml | 1 + ...refrontSpecialPriceForDifferentTimezonesForWebsitesTest.xml | 1 + .../AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml | 1 + .../Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml | 1 + .../Mftf/Test/AdminUrlForProductRewrittenCorrectlyTest.xml | 1 + ...roductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml | 1 + .../Test/StorefrontUpdateShoppingCartSimpleProductQtyTest.xml | 2 ++ ...UpdateShoppingCartSimpleWithCustomOptionsProductQtyTest.xml | 2 ++ .../Cms/Test/Mftf/Test/StoreViewLanguageCorrectSwitchTest.xml | 1 + .../Test/Mftf/Test/ProductsQtyReturnAfterOrderCancelTest.xml | 1 + .../Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml | 1 + .../Test/Mftf/Test/AdminDeleteDownloadableProductTest.xml | 1 + .../Test/Mftf/Test/AdminDeleteGroupedProductTest.xml | 1 + ...refrontProductWithMapAssignedConfigProductIsCorrectTest.xml | 1 + .../Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml | 1 + .../AdminSubmitsOrderWithAndWithoutFieldsValidationTest.xml | 1 + .../Test/StorefrontSwatchAttributesDisplayInWidgetCMSTest.xml | 1 + .../Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml | 3 ++- 24 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml index 282331924bca3..02615ca5dd254 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml @@ -11,6 +11,7 @@ <test name="AdminCreateNewAttributeFromProductTest"> <annotations> <features value="Catalog"/> + <stories value="Product attributes"/> <title value="Check that New Attribute from Product is create"/> <description value="Check that New Attribute from Product is create"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml index 4d28ccbd44d2c..2f0482b3b36d5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml @@ -10,6 +10,7 @@ <test name="AdminDeleteAttributeSetTest"> <annotations> <features value="Catalog"/> + <stories value="Attribute sets"/> <title value="Delete Attribute Set"/> <description value="Admin should be able to delete an attribute set"/> <testCaseId value="MC-4413"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml index 54b83e034fb11..d0036a2adea5a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml @@ -10,6 +10,7 @@ <test name="DeleteProductAttributeTest"> <annotations> <features value="Catalog"/> + <stories value="Product attributes"/> <title value="Delete Product Attribute"/> <description value="Admin should able to delete a product attribute"/> <testCaseId value="MC-10887"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml index 79ff7bcade77b..4e182c2e0e5ac 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml @@ -11,6 +11,7 @@ <test name="AdminImportCustomizableOptionToProductWithSKUTest"> <annotations> <features value="Catalog"/> + <stories value="Customizable options"/> <title value="Import customizable options to a product with existing SKU"/> <description value="Import customizable options to a product with existing SKU"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml index 234a7c69913c9..eb014ca7f884d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml @@ -13,6 +13,7 @@ <stories value="View sorting by websites"/> <title value="Sorting by websites in Admin"/> <description value="Sorting products by websites in Admin"/> + <severity value="AVERAGE"/> </annotations> <before> <createData entity="_defaultCategory" stepKey="createCategory"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml index 51af9d78dfd46..4bcb82372e801 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml @@ -11,6 +11,7 @@ <test name="AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest"> <annotations> <features value="Catalog"/> + <stories value="Tier price"/> <title value="Check that 'tier price' block not available for simple product from options without 'tier price'"/> <description value="Check that 'tier price' block not available for simple product from options without 'tier price'"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml index 3dd55a9dfee92..461ebde29fcad 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml @@ -11,6 +11,7 @@ <test name="ProductAvailableAfterEnablingSubCategoriesTest"> <annotations> <features value="Catalog"/> + <stories value="Categories"/> <title value="Check that parent categories are showing products after enabling subcategories after fully reindex"/> <description value="Check that parent categories are showing products after enabling subcategories after fully reindex"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontSpecialPriceForDifferentTimezonesForWebsitesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontSpecialPriceForDifferentTimezonesForWebsitesTest.xml index 268e18d2b4efa..514e12bb355a8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontSpecialPriceForDifferentTimezonesForWebsitesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontSpecialPriceForDifferentTimezonesForWebsitesTest.xml @@ -11,6 +11,7 @@ <test name="StorefrontSpecialPriceForDifferentTimezonesForWebsitesTest"> <annotations> <features value="Catalog"/> + <stories value="Special price"/> <title value="Check that special price displayed when 'default config' scope timezone does not match 'website' scope timezone"/> <description value="Check that special price displayed when 'default config' scope timezone does not match 'website' scope timezone"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml index 053a8c33e640c..0ff7e0cd85217 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml @@ -11,6 +11,7 @@ <test name="AdminEnableAttributeIsUndefinedCatalogPriceRuleTest"> <annotations> <features value="CatalogRule"/> + <stories value="Catalog price rule"/> <title value="Enable 'is undefined' condition to Scope Catalog Price rules by custom product attribute"/> <description value="Enable 'is undefined' condition to Scope Catalog Price rules by custom product attribute"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml index 2fea5c988bf9d..b6417e12a6db7 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml @@ -11,6 +11,7 @@ <test name="MinimalQueryLengthForCatalogSearchTest"> <annotations> <features value="CatalogSearch"/> + <stories value="Catalog search"/> <title value="Minimal query length for catalog search"/> <description value="Minimal query length for catalog search"/> <severity value="AVERAGE"/> diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminUrlForProductRewrittenCorrectlyTest.xml b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminUrlForProductRewrittenCorrectlyTest.xml index 30a4290d882fb..5423267676507 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminUrlForProductRewrittenCorrectlyTest.xml +++ b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminUrlForProductRewrittenCorrectlyTest.xml @@ -10,6 +10,7 @@ <test name="AdminUrlForProductRewrittenCorrectlyTest"> <annotations> <features value="CatalogUrlRewrite"/> + <stories value="Url rewrites"/> <title value="Check that URL for product rewritten correctly"/> <description value="Check that URL for product rewritten correctly"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml index 3401369a8c749..5e7e76ae4f02a 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml @@ -11,6 +11,7 @@ <test name="StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest"> <annotations> <features value="Checkout"/> + <stories value="Minicart"/> <title value="Checking Product name in Minicart and on Checkout page with different store views"/> <description value="Checking Product name in Minicart and on Checkout page with different store views"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdateShoppingCartSimpleProductQtyTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdateShoppingCartSimpleProductQtyTest.xml index 423f4049f6722..72f6cf95a6fbe 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdateShoppingCartSimpleProductQtyTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdateShoppingCartSimpleProductQtyTest.xml @@ -11,9 +11,11 @@ <test name="StorefrontUpdateShoppingCartSimpleProductQtyTest"> <annotations> <features value="Checkout"/> + <stories value="Shopping cart"/> <title value="Check updating shopping cart while updating items qty"/> <description value="Check updating shopping cart while updating items qty"/> <testCaseId value="MC-14731" /> + <severity value="AVERAGE"/> <group value="shoppingCart"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdateShoppingCartSimpleWithCustomOptionsProductQtyTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdateShoppingCartSimpleWithCustomOptionsProductQtyTest.xml index 84080b04c80ee..7a653f13c4ee5 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdateShoppingCartSimpleWithCustomOptionsProductQtyTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdateShoppingCartSimpleWithCustomOptionsProductQtyTest.xml @@ -11,9 +11,11 @@ <test name="StorefrontUpdateShoppingCartSimpleWithCustomOptionsProductQtyTest"> <annotations> <features value="Checkout"/> + <stories value="Shopping cart"/> <title value="Check updating shopping cart while updating qty of items with custom options"/> <description value="Check updating shopping cart while updating qty of items with custom options"/> <testCaseId value="MC-14732" /> + <severity value="AVERAGE"/> <group value="shoppingCart"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/StoreViewLanguageCorrectSwitchTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/StoreViewLanguageCorrectSwitchTest.xml index 2c351a12af72e..d4796b2ef7d43 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/StoreViewLanguageCorrectSwitchTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/StoreViewLanguageCorrectSwitchTest.xml @@ -11,6 +11,7 @@ <test name="StoreViewLanguageCorrectSwitchTest"> <annotations> <features value="Cms"/> + <stories value="Store view language"/> <title value="Check that Store View(language) switches correct"/> <description value="Check that Store View(language) switches correct"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ProductsQtyReturnAfterOrderCancelTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ProductsQtyReturnAfterOrderCancelTest.xml index 456be43f80b8d..f6469e060747f 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ProductsQtyReturnAfterOrderCancelTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ProductsQtyReturnAfterOrderCancelTest.xml @@ -12,6 +12,7 @@ <annotations> <features value="ConfigurableProduct"/> + <stories value="Cancel order"/> <title value="Product qunatity return after order cancel"/> <description value="Check Product qunatity return after order cancel"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml index 3121bd0da9d2d..5d0eec935e192 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml @@ -11,6 +11,7 @@ <test name="StorefrontResetCustomerPasswordFailedTest"> <annotations> <features value="Customer"/> + <stories value="Reset password"/> <title value="Customer tries to reset password several times"/> <description value="Customer tries to reset password several times"/> <severity value="CRITICAL" /> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDeleteDownloadableProductTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDeleteDownloadableProductTest.xml index d7e93d3429b96..d3c2d6e5d71a4 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDeleteDownloadableProductTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDeleteDownloadableProductTest.xml @@ -10,6 +10,7 @@ <test name="AdminDeleteDownloadableProductTest"> <annotations> <features value="Downloadable"/> + <stories value="Downloadable product"/> <title value="Delete Downloadable Product"/> <description value="Admin should be able to delete a downloadable product"/> <testCaseId value="MC-11018"/> diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminDeleteGroupedProductTest.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminDeleteGroupedProductTest.xml index 966e24851395c..6768dd5a1a249 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminDeleteGroupedProductTest.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminDeleteGroupedProductTest.xml @@ -10,6 +10,7 @@ <test name="AdminDeleteGroupedProductTest"> <annotations> <features value="GroupedProduct"/> + <stories value="Delete product"/> <title value="Delete Grouped Product"/> <description value="Admin should be able to delete a grouped product"/> <testCaseId value="MC-11019"/> diff --git a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml index a874de3b223a2..d1eb1339fe856 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml @@ -11,6 +11,7 @@ <test name="StorefrontProductWithMapAssignedConfigProductIsCorrectTest"> <annotations> <features value="Msrp"/> + <stories value="Minimum advertised price"/> <title value="Check that simple products with MAP assigned to configurable product displayed correctly"/> <description value="Check that simple products with MAP assigned to configurable product displayed correctly"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml index f869841153aea..1ad736ade37fc 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml @@ -11,6 +11,7 @@ <test name="AdminCorrectnessInvoicedItemInBundleProductTest"> <annotations> <features value="Sales"/> + <stories value="Product invoice"/> <title value="Check correctness of invoiced items in a Bundle Product"/> <description value="Check correctness of invoiced items in a Bundle Product"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutFieldsValidationTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutFieldsValidationTest.xml index d418751c736e1..1490fc1a1a388 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutFieldsValidationTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutFieldsValidationTest.xml @@ -13,6 +13,7 @@ <stories value="Create orders"/> <title value="Fields validation is required to create an order from Admin Panel"/> <description value="Admin should not be able to submit orders without invalid address fields"/> + <severity value="AVERAGE"/> <group value="sales"/> </annotations> <before> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchAttributesDisplayInWidgetCMSTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchAttributesDisplayInWidgetCMSTest.xml index 1ab2cd793f3b8..323b10507fe28 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchAttributesDisplayInWidgetCMSTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchAttributesDisplayInWidgetCMSTest.xml @@ -11,6 +11,7 @@ <test name="StorefrontSwatchAttributesDisplayInWidgetCMSTest"> <annotations> <features value="ConfigurableProduct"/> + <stories value="Swatches"/> <title value="Swatch Attribute is not displayed in the Widget CMS"/> <description value="Swatch Attribute is not displayed in the Widget CMS"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml index 732470d2558c7..d249af983f715 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml @@ -10,7 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminTaxCalcWithApplyTaxOnSettingTest"> <annotations> - <features value="AdminTaxCalcWithApplyTaxOnSettingTest"/> + <features value="Tax"/> + <stories value="Tax calculation"/> <title value="Tax calculation process following 'Apply Tax On' setting"/> <description value="Tax calculation process following 'Apply Tax On' setting"/> <severity value="MAJOR"/> From 7850c0b0cbea3d93dc520255a7f4d0e5037e0b11 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <26227105+MilaLesechko@users.noreply.github.com> Date: Wed, 10 Apr 2019 10:20:53 -0500 Subject: [PATCH 230/585] MC-4571: Convert CreateCustomerSegmentEntityWithCustomerConditionsPartOneTest to MFTF --- .../StorefrontCheckCartDiscountAndSummaryActionGroup.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml index 115fbc4993e58..790674f03ea69 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml @@ -14,7 +14,9 @@ <argument name="total" type="string"/> <argument name="discount" type="string"/> </arguments> + <waitForPageLoad stepKey="waitForPageLoad"/> + <waitForLoadingMaskToDisappear stepKey="waitForPrices"/> <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-${{discount}}" stepKey="assertDiscount"/> <see selector="{{CheckoutCartSummarySection.total}}" userInput="${{total}}" stepKey="assertTotal"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> From aa7af6b33ce0dd4adf31e2d74a13fb973123d3eb Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Wed, 10 Apr 2019 10:55:10 -0500 Subject: [PATCH 231/585] Issue-230: adding varnish - fixing static --- .../Controller/HttpRequestValidatorInterface.php | 1 + .../GraphQlCache/Model/CacheableQueryHandler.php | 6 ++++++ .../Magento/TestFramework/TestCase/GraphQl/Client.php | 8 ++++++-- .../Magento/TestFramework/TestCase/GraphQlAbstract.php | 10 +++++----- .../TestCase/HttpClient/CurlClientWithCookies.php | 2 -- .../Framework/GraphQl/Query/Resolver/ValueFactory.php | 1 + 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php b/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php index 23e19195393f3..2d9d50569e344 100644 --- a/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php +++ b/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php @@ -9,6 +9,7 @@ use Magento\Framework\App\HttpRequestInterface; use Magento\Framework\GraphQl\Exception\GraphQlInputException; + /** * Use this interface to implement a validator for a Graphql HTTP requests */ diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php index 405b8b0473eea..cb070baa28689 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -12,6 +12,12 @@ use Magento\Framework\App\RequestInterface; use Magento\Framework\GraphQl\Query\Resolver\Value; +/** + * Handler of collecting tagging on cache. + * + * This class would be used to collect tags after each operation where we need to collect tags + * usually after data is fetched or resolved. + */ class CacheableQueryHandler { /** diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php index eac7fecc267ef..870f840bdfa13 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php @@ -125,8 +125,12 @@ private function processResponse(string $response) * @param array $headers * @return mixed */ - public function getQueryResponseHeaders(string $query, array $variables = [], string $operationName = '', array $headers = []) - { + public function getQueryResponseHeaders( + string $query, + array $variables = [], + string $operationName = '', + array $headers = [] + ) { $url = $this->getEndpointUrl(); $requestArray = [ 'query' => $query, diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php index 810ebcbb098fd..44ce9aeca8b69 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php @@ -93,11 +93,11 @@ public function graphQlQueryForHttpHeaders( array $headers = [] ) { return $response = $this->getGraphQlClient()->getQueryResponseHeaders( - $query, - $variables, - $operationName, - $this->composeHeaders($headers) - ); + $query, + $variables, + $operationName, + $this->composeHeaders($headers) + ); } /** diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClientWithCookies.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClientWithCookies.php index ecd748d89bb20..626e319e86687 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClientWithCookies.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClientWithCookies.php @@ -23,8 +23,6 @@ class CurlClientWithCookies protected $jsonSerializer; /** - * CurlClient constructor. - * * @param CurlClient $curlClient * @param \Magento\TestFramework\Helper\JsonSerializer $jsonSerializer */ diff --git a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php index 7f4c0da5bc0f8..bdacc4a7f4193 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php @@ -41,6 +41,7 @@ public function __construct(ObjectManagerInterface $objectManager, CacheableQuer * Create value with passed in callback that returns data as parameter * * @param callable $callback + * @param Field $field * @param ResolveInfo $info * @return Value * @SuppressWarnings(PHPMD.UnusedFormalParameter) From 887678e24f85431530d256cb8935c16e17be976c Mon Sep 17 00:00:00 2001 From: Mila Lesechko <26227105+MilaLesechko@users.noreply.github.com> Date: Wed, 10 Apr 2019 11:55:30 -0500 Subject: [PATCH 232/585] MC-4571: Convert CreateCustomerSegmentEntityWithCustomerConditionsPartOneTest to MFTF --- .../Test/Mftf/Section/AdminCartPriceRulesFormSection.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml index f2a607213c68b..e5e21df91930a 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml @@ -73,7 +73,6 @@ <element name="actionOperator" type="select" selector=".rule-param-edit select"/> <element name="applyDiscountToShipping" type="checkbox" selector="input[name='apply_to_shipping']"/> <element name="applyDiscountToShippingLabel" type="checkbox" selector="input[name='apply_to_shipping']+label"/> - <element name="discardSubsequentRules" type="checkbox" selector="input[name='stop_rules_processing']+label"/> <element name="discountAmount" type="input" selector="input[name='discount_amount']"/> <element name="maximumQtyDiscount" type="input" selector="input[name='discount_qty']"/> <element name="discountStep" type="input" selector="input[name='discount_step']"/> @@ -94,4 +93,4 @@ <element name="generateCouponsButton" type="button" selector="#coupons_generate_button" timeout="30"/> <element name="generatedCouponByIndex" type="text" selector="#couponCodesGrid_table > tbody > tr:nth-child({{var}}) > td.col-code" parameterized="true"/> </section> -</sections> \ No newline at end of file +</sections> From 87af7d28f843bcae1dbf110622d982fa848ee213 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Wed, 10 Apr 2019 11:58:39 -0500 Subject: [PATCH 233/585] Issue-230: adding varnish - fixing static --- .../Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php | 2 +- .../testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php | 2 +- .../testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php index 2ef081ebcfa90..9eb9bc76047a8 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php @@ -94,7 +94,7 @@ public function testProductFromSpecificAndDefaultStore() $nonExistingStoreCode = "non_existent_store"; $headerMapInvalidStoreCode = ['Store' => $nonExistingStoreCode]; $this->expectException(\Exception::class); - $this->expectExceptionMessage('Store code non_existent_store does not exist'); + $this->expectExceptionMessage('The store that was requested wasn\'t found. Verify the store and try again.'); $this->graphQlQuery($query, [], '', $headerMapInvalidStoreCode); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php index 19b72b9e3ca4c..a19ad16cf60cc 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php @@ -163,7 +163,7 @@ public function testGetCartWithWrongStore() * @magentoApiDataFixture Magento/Checkout/_files/active_quote_customer_not_default_store.php * * @expectedException \Exception - * @expectedExceptionMessage Store code not_existing_store does not exist + * @expectedExceptionMessage The store that was requested wasn't found. Verify the store and try again. */ public function testGetCartWithNotExistingStore() { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php index 832e15058a4ee..2678cf1be1540 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php @@ -133,7 +133,7 @@ public function testGetCartWithWrongStore() * @magentoApiDataFixture Magento/Checkout/_files/active_quote_guest_not_default_store.php * * @expectedException \Exception - * @expectedExceptionMessage Store code not_existing_store does not exist + * @expectedExceptionMessage The store that was requested wasn't found. Verify the store and try again. */ public function testGetCartWithNotExistingStore() { From e6182866ef31aa9be2378d7c4d02d71a3de488d2 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Wed, 10 Apr 2019 12:01:34 -0500 Subject: [PATCH 234/585] Issue-230: adding varnish - fixing static --- .../Magento/GraphQlCache/Model/CacheableQueryHandler.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php index cb070baa28689..61c756daeff46 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -45,9 +45,9 @@ public function __construct(CacheableQuery $cacheableQuery, RequestInterface $re * * @param mixed $resolvedValue * @param Field|null $field - * @param ResolveInfo|null $info + * @return void */ - public function handleCacheFromResolverResponse(array $resolvedValue, Field $field) + public function handleCacheFromResolverResponse(array $resolvedValue, Field $field) : void { $cache = $field->getCache(); $cacheTag = isset($cache['cache_tag']) ? $cache['cache_tag'] : []; @@ -100,10 +100,11 @@ private function extractResolvedItemsIds(array $resolvedValue) : array * Set cache validity for the graphql request * * @param bool $isValid + * @return void */ private function setCacheValidity(bool $isValid): void { $cacheValidity = $this->cacheableQuery->isCacheable() && $isValid; $this->cacheableQuery->setCacheValidity($cacheValidity); } -} \ No newline at end of file +} From 066a68febbd4cfb15e8cc271a984ce75bc8f6f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torben=20Ho=CC=88hn?= <torhoehn@gmail.com> Date: Wed, 10 Apr 2019 20:39:09 +0200 Subject: [PATCH 235/585] only trigger livereload by .css files --- dev/tools/grunt/configs/watch.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dev/tools/grunt/configs/watch.js b/dev/tools/grunt/configs/watch.js index 356d0b4b7b2d3..c85ecb00f7809 100644 --- a/dev/tools/grunt/configs/watch.js +++ b/dev/tools/grunt/configs/watch.js @@ -11,11 +11,8 @@ var combo = require('./combo'), var themeOptions = {}; -_.each(themes, function(theme, name) { +_.each(themes, function (theme, name) { themeOptions[name] = { - 'options': { - livereload: true - }, 'files': [ '<%= combo.autopath(\''+name+'\', path.pub) %>/**/*.less' ], From 3e59df0b8a49c1f8a34438ebb2a031e037d750d8 Mon Sep 17 00:00:00 2001 From: Vitaliy <v.boyko@atwix.com> Date: Wed, 10 Apr 2019 22:05:04 +0300 Subject: [PATCH 236/585] Update SetPaymentMethodOnCartTest.php --- .../GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 8241debc8b09c..8fa1af3fbc898 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -70,7 +70,7 @@ public function testSetPaymentOnCartWithSimpleProduct() */ public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() { - $methodCode = Checkmo::PAYMENT_METHOD_CHECKMO_CODE; + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = <<<QUERY From 73733e491d330cb1647d759ab2ae0d51561c9f7b Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 10 Apr 2019 14:31:30 -0500 Subject: [PATCH 237/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- .../Magento/Backend/Model/Auth/Session.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Backend/Model/Auth/Session.php b/app/code/Magento/Backend/Model/Auth/Session.php index 01f762de83de8..e253881c2253b 100644 --- a/app/code/Magento/Backend/Model/Auth/Session.php +++ b/app/code/Magento/Backend/Model/Auth/Session.php @@ -314,7 +314,7 @@ public function isValidForPath($path) * * @return User|null */ - public function getUser(): ?User + public function getUser() { if (!$this->user) { $userData = $this->getUserData(); @@ -335,7 +335,7 @@ public function getUser(): ?User * @param User|null $user * @return Session */ - public function setUser(?User $user): self + public function setUser($user) { $this->setUserData(null); if ($user) { @@ -351,7 +351,7 @@ public function setUser(?User $user): self * * @return bool */ - public function hasUser(): bool + public function hasUser() { return $this->user || $this->hasUserData(); } @@ -361,10 +361,10 @@ public function hasUser(): bool * * @return Session */ - public function unsUser(): self + public function unsUser() { $this->user = null; - $this->unsUserData(); + return $this->unsUserData(); } /** @@ -372,7 +372,7 @@ public function unsUser(): self * * @return Acl|null */ - public function getAcl(): ?Acl + public function getAcl() { if (!$this->acl) { $aclData = $this->getUserAclData(); @@ -393,7 +393,7 @@ public function getAcl(): ?Acl * @param Acl|null $acl * @return Session */ - public function setAcl(?Acl $acl): self + public function setAcl($acl) { $this->setUserAclData(null); if ($acl) { @@ -409,7 +409,7 @@ public function setAcl(?Acl $acl): self * * @return bool */ - public function hasAcl(): bool + public function hasAcl() { return $this->acl || $this->hasUserAclData(); } @@ -419,10 +419,10 @@ public function hasAcl(): bool * * @return Session */ - public function unsAcl(): self + public function unsAcl() { $this->acl = null; - $this->unsUserAclData(); + return $this->unsUserAclData(); } /** From 45ed4224e7bb423ab3ddca847de5f649706b9b91 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Wed, 10 Apr 2019 14:40:58 -0500 Subject: [PATCH 238/585] Issue-230: adding varnish - fix dependencies --- .../Model/Resolver/Categories.php | 56 +++++++++---------- .../Model/CacheableQueryHandler.php | 6 +- .../Model/Plugin/Query/Resolver.php | 9 +++ .../GraphQl/Query/Resolver/ValueFactory.php | 28 ++-------- 4 files changed, 41 insertions(+), 58 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php index b31144368aa68..cb392a7b2295d 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php @@ -94,39 +94,35 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $this->categoryIds = array_merge($this->categoryIds, $categoryIds); $that = $this; - return $this->valueFactory->create( - function () use ($that, $categoryIds, $info) { - $categories = []; - if (empty($that->categoryIds)) { - return []; - } - - if (!$this->collection->isLoaded()) { - $that->attributesJoiner->join($info->fieldNodes[0], $this->collection); - $this->collection->addIdFilter($this->categoryIds); - } - /** @var CategoryInterface | \Magento\Catalog\Model\Category $item */ - foreach ($this->collection as $item) { - if (in_array($item->getId(), $categoryIds)) { - // Try to extract all requested fields from the loaded collection data - $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item, true); - $categories[$item->getId()]['model'] = $item; - $requestedFields = $that->attributesJoiner->getQueryFields($info->fieldNodes[0]); - $extractedFields = array_keys($categories[$item->getId()]); - $foundFields = array_intersect($requestedFields, $extractedFields); - if (count($requestedFields) === count($foundFields)) { - continue; - } + return $this->valueFactory->create(function () use ($that, $categoryIds, $info) { + $categories = []; + if (empty($that->categoryIds)) { + return []; + } - // If not all requested fields were extracted from the collection, start more complex extraction - $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item); + if (!$this->collection->isLoaded()) { + $that->attributesJoiner->join($info->fieldNodes[0], $this->collection); + $this->collection->addIdFilter($this->categoryIds); + } + /** @var CategoryInterface | \Magento\Catalog\Model\Category $item */ + foreach ($this->collection as $item) { + if (in_array($item->getId(), $categoryIds)) { + // Try to extract all requested fields from the loaded collection data + $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item, true); + $categories[$item->getId()]['model'] = $item; + $requestedFields = $that->attributesJoiner->getQueryFields($info->fieldNodes[0]); + $extractedFields = array_keys($categories[$item->getId()]); + $foundFields = array_intersect($requestedFields, $extractedFields); + if (count($requestedFields) === count($foundFields)) { + continue; } + + // If not all requested fields were extracted from the collection, start more complex extraction + $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item); } + } - return $categories; - }, - $field, - $info - ); + return $categories; + }); } } diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php index 61c756daeff46..b408d29eeb4f8 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -8,9 +8,7 @@ namespace Magento\GraphQlCache\Model; use Magento\Framework\GraphQl\Config\Element\Field; -use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Framework\App\RequestInterface; -use Magento\Framework\GraphQl\Query\Resolver\Value; /** * Handler of collecting tagging on cache. @@ -44,7 +42,7 @@ public function __construct(CacheableQuery $cacheableQuery, RequestInterface $re * Set cache validity to the cacheableQuery after resolving any resolver or evaluating a promise in a query * * @param mixed $resolvedValue - * @param Field|null $field + * @param Field $field * @return void */ public function handleCacheFromResolverResponse(array $resolvedValue, Field $field) : void @@ -70,7 +68,7 @@ public function handleCacheFromResolverResponse(array $resolvedValue, Field $fie /** * Extract ids for resolved items * - * @param mixed|Value $resolvedValue + * @param array $resolvedValue * @return array */ private function extractResolvedItemsIds(array $resolvedValue) : array diff --git a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php index ee14ba3bbdc94..3c98d292b0dea 100644 --- a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php +++ b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php @@ -58,6 +58,15 @@ public function afterResolve( /** Only if array @see \Magento\Framework\GraphQl\Query\Resolver\Value */ if (is_array($resolvedValue)) { $this->cacheableQueryHandler->handleCacheFromResolverResponse($resolvedValue, $field); + } elseif ($resolvedValue instanceof \Magento\Framework\GraphQl\Query\Resolver\Value) { + $resolvedValue->then(function () use ($resolvedValue, $field) { + if (is_array($resolvedValue->promise->result) && $field) { + $this->cacheableQueryHandler->handleCacheFromResolverResponse( + $resolvedValue->promise->result, + $field + ); + } + }); } return $resolvedValue; } diff --git a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php index bdacc4a7f4193..5bd34224bb077 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ValueFactory.php @@ -8,9 +8,6 @@ namespace Magento\Framework\GraphQl\Query\Resolver; use Magento\Framework\ObjectManagerInterface; -use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Framework\GraphQl\Config\Element\Field; -use Magento\GraphQlCache\Model\CacheableQueryHandler; /** * Create @see Value to return data from passed in callback to GraphQL library @@ -22,39 +19,22 @@ class ValueFactory */ private $objectManager; - /** - * @var CacheableQueryHandler - */ - private $cacheableQueryHandler; - /** * @param ObjectManagerInterface $objectManager - * @param CacheableQueryHandler $cacheableQueryHandler */ - public function __construct(ObjectManagerInterface $objectManager, CacheableQueryHandler $cacheableQueryHandler) + public function __construct(ObjectManagerInterface $objectManager) { $this->objectManager = $objectManager; - $this->cacheableQueryHandler = $cacheableQueryHandler; } /** - * Create value with passed in callback that returns data as parameter + * Create value with passed in callback that returns data as parameter; * * @param callable $callback - * @param Field $field - * @param ResolveInfo $info * @return Value - * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function create(callable $callback, Field $field = null, ResolveInfo $info = null) : Value + public function create(callable $callback) { - /** @var \Magento\Framework\GraphQl\Query\Resolver\Value $value */ - $value = $this->objectManager->create(Value::class, ['callback' => $callback]); - $value->then(function () use ($value, $field, $info) { - if (is_array($value->promise->result) && $field) { - $this->cacheableQueryHandler->handleCacheFromResolverResponse($value->promise->result, $field); - } - }); - return $value; + return $this->objectManager->create(Value::class, ['callback' => $callback]); } } From 8434d74abd6393d2cb4ad45eff6c9ec292f4dc71 Mon Sep 17 00:00:00 2001 From: David Alger <davidmalger@gmail.com> Date: Wed, 10 Apr 2019 15:41:25 -0500 Subject: [PATCH 239/585] Fixed #15090: Update Magento_Config module to allow admin/url/use_custom in env.php --- .../Magento/Config/Model/Config/Backend/Admin/Usecustom.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php b/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php index 9a483de6a695b..d12569eebe5b2 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php +++ b/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php @@ -56,8 +56,9 @@ public function beforeSave() { $value = $this->getValue(); if ($value == 1) { - $customUrl = $this->getData('groups/url/fields/custom/value'); - if (empty($customUrl)) { + $customUrlField = $this->getData('groups/url/fields/custom/value'); + $customUrlConfig = $this->_config->getValue('admin/url/custom'); + if (empty($customUrlField) && empty($customUrlConfig)) { throw new \Magento\Framework\Exception\LocalizedException(__('Please specify the admin custom URL.')); } } From 435d269809ac8b3fdc182f7a5f4ef05b6f70c888 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Wed, 10 Apr 2019 17:53:39 -0500 Subject: [PATCH 240/585] Issue-230: adding varnish - fix Boc con constructor --- app/code/Magento/GraphQl/Controller/GraphQl.php | 17 ++++++++++++++--- .../GraphQlCache/Controller/Plugin/GraphQl.php | 12 ++++++------ .../GraphQlCache/Model/CacheableQuery.php | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index 4fccec6c046ef..748793b541547 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -16,8 +16,10 @@ use Magento\Framework\GraphQl\Schema\SchemaGeneratorInterface; use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\Webapi\Response; use Magento\Framework\GraphQl\Query\Fields as QueryFields; use Magento\Framework\Controller\Result\JsonFactory; +use Magento\Framework\App\ObjectManager; /** * Front controller for web API GraphQL area. @@ -26,6 +28,12 @@ */ class GraphQl implements FrontControllerInterface { + /** + * @var Response + * @deprecated + */ + private $response; + /** * @var SchemaGeneratorInterface */ @@ -67,6 +75,7 @@ class GraphQl implements FrontControllerInterface private $jsonFactory; /** + * @param Response $response * @param SchemaGeneratorInterface $schemaGenerator * @param SerializerInterface $jsonSerializer * @param QueryProcessor $queryProcessor @@ -74,9 +83,10 @@ class GraphQl implements FrontControllerInterface * @param ContextInterface $resolverContext * @param HttpRequestProcessor $requestProcessor * @param QueryFields $queryFields - * @param JsonFactory $jsonFactory + * @param JsonFactory|null $jsonFactory */ public function __construct( + Response $response, SchemaGeneratorInterface $schemaGenerator, SerializerInterface $jsonSerializer, QueryProcessor $queryProcessor, @@ -84,8 +94,9 @@ public function __construct( ContextInterface $resolverContext, HttpRequestProcessor $requestProcessor, QueryFields $queryFields, - JsonFactory $jsonFactory + JsonFactory $jsonFactory = null ) { + $this->response = $response; $this->schemaGenerator = $schemaGenerator; $this->jsonSerializer = $jsonSerializer; $this->queryProcessor = $queryProcessor; @@ -93,7 +104,7 @@ public function __construct( $this->resolverContext = $resolverContext; $this->requestProcessor = $requestProcessor; $this->queryFields = $queryFields; - $this->jsonFactory = $jsonFactory; + $this->jsonFactory = $jsonFactory ?:ObjectManager::getInstance()->get(JsonFactory::class); } /** diff --git a/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php b/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php index 1979ef1e0d0c8..588aa851e880a 100644 --- a/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php +++ b/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php @@ -24,7 +24,7 @@ class GraphQl /** * @var CacheableQuery */ - private $cacheInfo; + private $cacheableQuery; /** * @var Config @@ -42,18 +42,18 @@ class GraphQl private $requestProcessor; /** - * @param CacheableQuery $cacheInfo + * @param CacheableQuery $cacheableQuery * @param Config $config * @param HttpResponse $response * @param HttpRequestProcessor $requestProcessor */ public function __construct( - CacheableQuery $cacheInfo, + CacheableQuery $cacheableQuery, Config $config, HttpResponse $response, HttpRequestProcessor $requestProcessor ) { - $this->cacheInfo = $cacheInfo; + $this->cacheableQuery = $cacheableQuery; $this->config = $config; $this->response = $response; $this->requestProcessor = $requestProcessor; @@ -94,9 +94,9 @@ public function afterDispatch( ) { $sendNoCacheHeaders = false; if ($this->config->isEnabled() && $request->isGet()) { - if ($this->cacheInfo->shouldPopulateCacheHeadersWithTags()) { + if ($this->cacheableQuery->shouldPopulateCacheHeadersWithTags()) { $this->response->setPublicHeaders($this->config->getTtl()); - $this->response->setHeader('X-Magento-Tags', implode(',', $this->cacheInfo->getCacheTags()), true); + $this->response->setHeader('X-Magento-Tags', implode(',', $this->cacheableQuery->getCacheTags()), true); } else { $sendNoCacheHeaders = true; } diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQuery.php b/app/code/Magento/GraphQlCache/Model/CacheableQuery.php index 3a7600b58f66d..451e1039eec57 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQuery.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQuery.php @@ -8,7 +8,7 @@ namespace Magento\GraphQlCache\Model; /** - * CacheableQuery object is a registry for collecting cache related info and tags of all entities. + * CacheableQuery should be used as a singleton for collecting cache related info and tags of all entities. */ class CacheableQuery { From 39597253aac488f85fee3f87fafad9ec7effd12d Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Thu, 11 Apr 2019 11:21:33 +0300 Subject: [PATCH 241/585] Fix integration tests. --- .../Magento/Framework/View/Layout/etc/elements.xsd | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd index a5f8ace17bdcc..17857c9ab0658 100755 --- a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd +++ b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd @@ -14,7 +14,13 @@ <xs:sequence> <xs:element name="updater" type="updaterType" minOccurs="0" maxOccurs="1"/> </xs:sequence> - <xs:attribute name="shared" type="xs:boolean" default="true" use="optional"/> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="object"> + <xs:complexContent> + <xs:extension base="argumentType"> + <xs:attribute name="shared" use="optional" type="xs:boolean"/> </xs:extension> </xs:complexContent> </xs:complexType> From c75c2e16c610b02c02ec303155ce1352c2d992e2 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Thu, 11 Apr 2019 10:23:41 +0200 Subject: [PATCH 242/585] [fix] make return_path_email and set_return_path configurable in website and store scope --- app/code/Magento/Backend/etc/adminhtml/system.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml index 98b8e702b1c53..c762dbf58de62 100644 --- a/app/code/Magento/Backend/etc/adminhtml/system.xml +++ b/app/code/Magento/Backend/etc/adminhtml/system.xml @@ -323,11 +323,11 @@ <label>Port (25)</label> <comment>For Windows server only.</comment> </field> - <field id="set_return_path" translate="label" type="select" sortOrder="70" showInDefault="1" showInWebsite="0" showInStore="0"> + <field id="set_return_path" translate="label" type="select" sortOrder="70" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Set Return-Path</label> <source_model>Magento\Config\Model\Config\Source\Yesnocustom</source_model> </field> - <field id="return_path_email" translate="label" type="text" sortOrder="80" showInDefault="1" showInWebsite="0" showInStore="0"> + <field id="return_path_email" translate="label" type="text" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Return-Path Email</label> <validate>validate-email</validate> <backend_model>Magento\Config\Model\Config\Backend\Email\Address</backend_model> From a3cdeb7c89c4083c662c630076addba15e76a6c5 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Thu, 11 Apr 2019 11:24:44 +0300 Subject: [PATCH 243/585] MC-12180: Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie --- ...efrontAssertProductInWidgetActionGroup.xml | 37 +++++++++++ ...listIsPersistedUnderLongTermCookieTest.xml | 61 +++++++++++++------ 2 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductInWidgetActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductInWidgetActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductInWidgetActionGroup.xml new file mode 100644 index 0000000000000..c25b73bab21ae --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductInWidgetActionGroup.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Check the product in recently viewed widget --> + <actionGroup name="StorefrontAssertProductInRecentlyViewedWidgetActionGroup"> + <arguments> + <argument name="product"/> + </arguments> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" stepKey="waitWidgetRecentlyViewedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="{{product.name}}" stepKey="seeProductInRecentlyViewedWidget"/> + </actionGroup> + + <!-- Check the product in recently compared widget --> + <actionGroup name="StorefrontAssertProductInRecentlyComparedWidgetActionGroup"> + <arguments> + <argument name="product"/> + </arguments> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" stepKey="waitWidgetRecentlyComparedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="{{product.name}}" stepKey="seeProductInRecentlyComparedWidget"/> + </actionGroup> + + <!-- Check the product in recently ordered widget --> + <actionGroup name="StorefrontAssertProductInRecentlyOrderedWidgetActionGroup"> + <arguments> + <argument name="product"/> + </arguments> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" stepKey="waitWidgetRecentlyOrderedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="{{product.name}}" stepKey="seeProductInRecentlyOrderedWidget"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml index 220d6b656c384..dc6f87bef0ba8 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml @@ -18,6 +18,7 @@ <testCaseId value="MC-12180"/> <group value="persistent"/> <group value="widget"/> + <group value="catalog_widget"/> <skip> <issueId value="MC-15741"/> </skip> @@ -77,9 +78,12 @@ </actionGroup> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterAddedProductToCart"/> <!--The Recently Viewed widget displays Simple Product 1 and Simple Product 2--> - <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" stepKey="waitWidgetRecentlyViewedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeSimpleProductInRecentlyViewedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSecondSimpleProduct.name$$" stepKey="seeSecondSimpleProductInRecentlyViewedWidget"/> + <actionGroup ref="StorefrontAssertProductInRecentlyViewedWidgetActionGroup" stepKey="seeSimpleProductInRecentlyViewedWidget"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyViewedWidgetActionGroup" stepKey="seeSecondSimpleProductInRecentlyViewedWidget"> + <argument name="product" value="$$createSecondSimpleProduct$$"/> + </actionGroup> <!--Add Simple Product 1 and Simple Product 2 to Wishlist--> <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProductToWishlist"> @@ -114,11 +118,14 @@ </actionGroup> <!--Click Clear all in the Compare Products widget--> - <actionGroup ref="StorefrontClearCompareActionGroup" stepKey="asd"/> + <actionGroup ref="StorefrontClearCompareActionGroup" stepKey="clearCompareList"/> <!--The Recently Compared widget displays Simple Product 1 and Simple Product 2--> - <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" stepKey="waitWidgetRecentlyComparedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSecondSimpleProductInRecentlyComparedWidget"/> + <actionGroup ref="StorefrontAssertProductInRecentlyComparedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyComparedWidget"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyComparedWidgetActionGroup" stepKey="checkSecondSimpleProductInRecentlyComparedWidget"> + <argument name="product" value="$$createSecondSimpleProduct$$"/> + </actionGroup> <!--Place the order--> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToShoppingCartPage"/> @@ -127,24 +134,35 @@ </actionGroup> <!--The Recently Ordered widget displays Simple Product 1 and Simple Product 2--> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageToCheckProductsInRecentlyOrderedWidget"/> - <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" stepKey="waitWidgetRecentlyOrderedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSecondSimpleProductInRecentlyOrderedWidget"/> + <actionGroup ref="StorefrontAssertProductInRecentlyOrderedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyOrderedWidget"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyOrderedWidgetActionGroup" stepKey="checkSecondSimpleProductInRecentlyOrderedWidget"> + <argument name="product" value="$$createSecondSimpleProduct$$"/> + </actionGroup> <!--Sign out and check that widgets persist the information about the items--> <actionGroup ref="StorefrontSignOutActionGroup" stepKey="logoutFromCustomerToCheckThatWidgetsPersist"/> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterLogoutFromCustomer"/> <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterLogoutFromCustomer"/> <seeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkLinkNotYouAfterLogoutFromCustomer"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogout"/> + + <actionGroup ref="StorefrontAssertProductInRecentlyViewedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogout"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebarAfterLogout"> <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogout"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogout"/> + <actionGroup ref="StorefrontAssertProductInRecentlyComparedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogout"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyOrderedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogout"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> <!--Click the *Not you?* link and check the price for Simple Product--> <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickLinkNotYou"/> + <waitForPageLoad stepKey="waitForPageLoadAfterClickLinkNotYou"/> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterClickNotYou"/> <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterClickLinkNotYou"/> <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyViewedWidget"/> @@ -158,9 +176,18 @@ </actionGroup> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageToCheckWidgets"/> <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterLogin"/> - <waitForElementVisible selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="checkSimpleProductNameInWishlistSidebarAfterLogin"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogin"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogin"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogin"/> + + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductNameInWishlistSidebarAfterLogin"> + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyViewedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogin"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyComparedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogin"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyOrderedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogin"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> </test> </tests> From 91f116d99c0aeec8fb9af15d594da4276b44abd6 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Wed, 10 Apr 2019 14:58:00 +0300 Subject: [PATCH 244/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Fixed static/unit test falls; --- app/code/Magento/Ups/Model/Carrier.php | 289 +++++++++++++++---------- 1 file changed, 169 insertions(+), 120 deletions(-) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 14b71e5f75db3..09d6ba154a546 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -455,7 +455,7 @@ protected function _getCgiQuotes() { $rowRequest = $this->_rawRequest; if (self::USA_COUNTRY_ID == $rowRequest->getDestCountry()) { - $destPostal = substr($rowRequest->getDestPostal(), 0, 5); + $destPostal = substr((string)$rowRequest->getDestPostal(), 0, 5); } else { $destPostal = $rowRequest->getDestPostal(); } @@ -613,7 +613,7 @@ protected function _getXmlQuotes() $rowRequest = $this->_rawRequest; if (self::USA_COUNTRY_ID == $rowRequest->getDestCountry()) { - $destPostal = substr($rowRequest->getDestPostal(), 0, 5); + $destPostal = substr((string)$rowRequest->getDestPostal(), 0, 5); } else { $destPostal = $rowRequest->getDestPostal(); } @@ -833,76 +833,15 @@ protected function _parseXmlResponse($xmlResponse) $allowedCurrencies = $this->_currencyFactory->create()->getConfigAllowCurrencies(); foreach ($arr as $shipElement) { - $code = (string)$shipElement->Service->Code; - if (in_array($code, $allowedMethods)) { - //The location of tax information is in a different place - // depending on whether we are using negotiated rates or not - if ($negotiatedActive) { - $includeTaxesArr = $xml->getXpath( - "//RatingServiceSelectionResponse/RatedShipment/NegotiatedRates" - . "/NetSummaryCharges/TotalChargesWithTaxes" - ); - $includeTaxesActive = $this->getConfigFlag('include_taxes') && !empty($includeTaxesArr); - if ($includeTaxesActive) { - $cost = $shipElement->NegotiatedRates - ->NetSummaryCharges - ->TotalChargesWithTaxes - ->MonetaryValue; - - $responseCurrencyCode = $this->mapCurrencyCode( - (string)$shipElement->NegotiatedRates - ->NetSummaryCharges - ->TotalChargesWithTaxes - ->CurrencyCode - ); - } else { - $cost = $shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->MonetaryValue; - $responseCurrencyCode = $this->mapCurrencyCode( - (string)$shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->CurrencyCode - ); - } - } else { - $includeTaxesArr = $xml->getXpath( - "//RatingServiceSelectionResponse/RatedShipment/TotalChargesWithTaxes" - ); - $includeTaxesActive = $this->getConfigFlag('include_taxes') && !empty($includeTaxesArr); - if ($includeTaxesActive) { - $cost = $shipElement->TotalChargesWithTaxes->MonetaryValue; - $responseCurrencyCode = $this->mapCurrencyCode( - (string)$shipElement->TotalChargesWithTaxes->CurrencyCode - ); - } else { - $cost = $shipElement->TotalCharges->MonetaryValue; - $responseCurrencyCode = $this->mapCurrencyCode( - (string)$shipElement->TotalCharges->CurrencyCode - ); - } - } - - //convert price with Origin country currency code to base currency code - $successConversion = true; - if ($responseCurrencyCode) { - if (in_array($responseCurrencyCode, $allowedCurrencies)) { - $cost = (double)$cost * $this->_getBaseCurrencyRate($responseCurrencyCode); - } else { - $errorTitle = __( - 'We can\'t convert a rate from "%1-%2".', - $responseCurrencyCode, - $this->_request->getPackageCurrency()->getCode() - ); - $error = $this->_rateErrorFactory->create(); - $error->setCarrier('ups'); - $error->setCarrierTitle($this->getConfigData('title')); - $error->setErrorMessage($errorTitle); - $successConversion = false; - } - } - - if ($successConversion) { - $costArr[$code] = $cost; - $priceArr[$code] = $this->getMethodPrice((float)$cost, $code); - } - } + $this->processShippingRateForItem( + $shipElement, + $allowedMethods, + $allowedCurrencies, + $costArr, + $priceArr, + $negotiatedActive, + $xml + ); } } else { $arr = $xml->getXpath("//RatingServiceSelectionResponse/Response/Error/ErrorDescription/text()"); @@ -945,6 +884,99 @@ protected function _parseXmlResponse($xmlResponse) return $result; } + /** + * Processing rate for ship element + * + * @param \Magento\Framework\Simplexml\Element $shipElement + * @param array $allowedMethods + * @param array $allowedCurrencies + * @param array $costArr + * @param array $priceArr + * @param bool $negotiatedActive + * @param \Magento\Framework\Simplexml\Config $xml + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function processShippingRateForItem( + \Magento\Framework\Simplexml\Element $shipElement, + array $allowedMethods, + array $allowedCurrencies, + array &$costArr, + array &$priceArr, + bool $negotiatedActive, + \Magento\Framework\Simplexml\Config $xml + ): void { + $code = (string)$shipElement->Service->Code; + if (in_array($code, $allowedMethods)) { + //The location of tax information is in a different place + // depending on whether we are using negotiated rates or not + if ($negotiatedActive) { + $includeTaxesArr = $xml->getXpath( + "//RatingServiceSelectionResponse/RatedShipment/NegotiatedRates" + . "/NetSummaryCharges/TotalChargesWithTaxes" + ); + $includeTaxesActive = $this->getConfigFlag('include_taxes') && !empty($includeTaxesArr); + if ($includeTaxesActive) { + $cost = $shipElement->NegotiatedRates + ->NetSummaryCharges + ->TotalChargesWithTaxes + ->MonetaryValue; + + $responseCurrencyCode = $this->mapCurrencyCode( + (string)$shipElement->NegotiatedRates + ->NetSummaryCharges + ->TotalChargesWithTaxes + ->CurrencyCode + ); + } else { + $cost = $shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->MonetaryValue; + $responseCurrencyCode = $this->mapCurrencyCode( + (string)$shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->CurrencyCode + ); + } + } else { + $includeTaxesArr = $xml->getXpath( + "//RatingServiceSelectionResponse/RatedShipment/TotalChargesWithTaxes" + ); + $includeTaxesActive = $this->getConfigFlag('include_taxes') && !empty($includeTaxesArr); + if ($includeTaxesActive) { + $cost = $shipElement->TotalChargesWithTaxes->MonetaryValue; + $responseCurrencyCode = $this->mapCurrencyCode( + (string)$shipElement->TotalChargesWithTaxes->CurrencyCode + ); + } else { + $cost = $shipElement->TotalCharges->MonetaryValue; + $responseCurrencyCode = $this->mapCurrencyCode( + (string)$shipElement->TotalCharges->CurrencyCode + ); + } + } + + //convert price with Origin country currency code to base currency code + $successConversion = true; + if ($responseCurrencyCode) { + if (in_array($responseCurrencyCode, $allowedCurrencies)) { + $cost = (double)$cost * $this->_getBaseCurrencyRate($responseCurrencyCode); + } else { + $errorTitle = __( + 'We can\'t convert a rate from "%1-%2".', + $responseCurrencyCode, + $this->_request->getPackageCurrency()->getCode() + ); + $error = $this->_rateErrorFactory->create(); + $error->setCarrier('ups'); + $error->setCarrierTitle($this->getConfigData('title')); + $error->setErrorMessage($errorTitle); + $successConversion = false; + } + } + + if ($successConversion) { + $costArr[$code] = $cost; + $priceArr[$code] = $this->getMethodPrice((float)$cost, $code); + } + } + } + /** * Get tracking * @@ -1101,54 +1133,7 @@ protected function _parseXmlTrackingResponse($trackingValue, $xmlResponse) if ($activityTags) { $index = 1; foreach ($activityTags as $activityTag) { - $addressArr = []; - if (isset($activityTag->ActivityLocation->Address->City)) { - $addressArr[] = (string)$activityTag->ActivityLocation->Address->City; - } - if (isset($activityTag->ActivityLocation->Address->StateProvinceCode)) { - $addressArr[] = (string)$activityTag->ActivityLocation->Address->StateProvinceCode; - } - if (isset($activityTag->ActivityLocation->Address->CountryCode)) { - $addressArr[] = (string)$activityTag->ActivityLocation->Address->CountryCode; - } - $dateArr = []; - $date = (string)$activityTag->Date; - //YYYYMMDD - $dateArr[] = substr($date, 0, 4); - $dateArr[] = substr($date, 4, 2); - $dateArr[] = substr($date, -2, 2); - - $timeArr = []; - $time = (string)$activityTag->Time; - //HHMMSS - $timeArr[] = substr($time, 0, 2); - $timeArr[] = substr($time, 2, 2); - $timeArr[] = substr($time, -2, 2); - - if ($index === 1) { - $resultArr['status'] = (string)$activityTag->Status->StatusType->Description; - $resultArr['deliverydate'] = implode('-', $dateArr); - //YYYY-MM-DD - $resultArr['deliverytime'] = implode(':', $timeArr); - //HH:MM:SS - $resultArr['deliverylocation'] = (string)$activityTag->ActivityLocation->Description; - $resultArr['signedby'] = (string)$activityTag->ActivityLocation->SignedForByName; - if ($addressArr) { - $resultArr['deliveryto'] = implode(', ', $addressArr); - } - } else { - $tempArr = []; - $tempArr['activity'] = (string)$activityTag->Status->StatusType->Description; - $tempArr['deliverydate'] = implode('-', $dateArr); - //YYYY-MM-DD - $tempArr['deliverytime'] = implode(':', $timeArr); - //HH:MM:SS - if ($addressArr) { - $tempArr['deliverylocation'] = implode(', ', $addressArr); - } - $packageProgress[] = $tempArr; - } - $index++; + $this->processActivityTagInfo($activityTag, $index, $resultArr, $packageProgress); } $resultArr['progressdetail'] = $packageProgress; } @@ -1181,6 +1166,70 @@ protected function _parseXmlTrackingResponse($trackingValue, $xmlResponse) return $this->_result; } + /** + * Process tracking info from activity tag + * + * @param \Magento\Framework\Simplexml\Element $activityTag + * @param int $index + * @param array $resultArr + * @param array $packageProgress + */ + private function processActivityTagInfo( + \Magento\Framework\Simplexml\Element $activityTag, + int &$index, + array &$resultArr, + array &$packageProgress + ) { + $addressArr = []; + if (isset($activityTag->ActivityLocation->Address->City)) { + $addressArr[] = (string)$activityTag->ActivityLocation->Address->City; + } + if (isset($activityTag->ActivityLocation->Address->StateProvinceCode)) { + $addressArr[] = (string)$activityTag->ActivityLocation->Address->StateProvinceCode; + } + if (isset($activityTag->ActivityLocation->Address->CountryCode)) { + $addressArr[] = (string)$activityTag->ActivityLocation->Address->CountryCode; + } + $dateArr = []; + $date = (string)$activityTag->Date; + //YYYYMMDD + $dateArr[] = substr($date, 0, 4); + $dateArr[] = substr($date, 4, 2); + $dateArr[] = substr($date, -2, 2); + + $timeArr = []; + $time = (string)$activityTag->Time; + //HHMMSS + $timeArr[] = substr($time, 0, 2); + $timeArr[] = substr($time, 2, 2); + $timeArr[] = substr($time, -2, 2); + + if ($index === 1) { + $resultArr['status'] = (string)$activityTag->Status->StatusType->Description; + $resultArr['deliverydate'] = implode('-', $dateArr); + //YYYY-MM-DD + $resultArr['deliverytime'] = implode(':', $timeArr); + //HH:MM:SS + $resultArr['deliverylocation'] = (string)$activityTag->ActivityLocation->Description; + $resultArr['signedby'] = (string)$activityTag->ActivityLocation->SignedForByName; + if ($addressArr) { + $resultArr['deliveryto'] = implode(', ', $addressArr); + } + } else { + $tempArr = []; + $tempArr['activity'] = (string)$activityTag->Status->StatusType->Description; + $tempArr['deliverydate'] = implode('-', $dateArr); + //YYYY-MM-DD + $tempArr['deliverytime'] = implode(':', $timeArr); + //HH:MM:SS + if ($addressArr) { + $tempArr['deliverylocation'] = implode(', ', $addressArr); + } + $packageProgress[] = $tempArr; + } + $index++; + } + /** * Get tracking response * From 6cc22442ec2569545e708149ef04880614d6cc80 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Thu, 11 Apr 2019 17:36:54 +0300 Subject: [PATCH 245/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Fixed unit tests; --- app/code/Magento/Ups/Model/Carrier.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 09d6ba154a546..d3a0bb86b0496 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -473,7 +473,7 @@ protected function _getCgiQuotes() '47_rate_chart' => $rowRequest->getPickup(), '48_container' => $rowRequest->getContainer(), '49_residential' => $rowRequest->getDestType(), - 'weight_std' => strtolower($rowRequest->getUnitMeasure()), + 'weight_std' => strtolower((string)$rowRequest->getUnitMeasure()), ]; $params['47_rate_chart'] = $params['47_rate_chart']['label']; @@ -537,7 +537,7 @@ protected function _parseCgiResponse($response) $priceArr = []; if (strlen(trim($response)) > 0) { $rRows = explode("\n", $response); - $allowedMethods = explode(",", $this->getConfigData('allowed_methods')); + $allowedMethods = explode(",", (string)$this->getConfigData('allowed_methods')); foreach ($rRows as $rRow) { $row = explode('%', $rRow); switch (substr($row[0], -1)) { From 316133a0c2373bab06dfe81d926baec720a3dd92 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 11 Apr 2019 17:44:22 +0300 Subject: [PATCH 246/585] magento/magento2#20968: Unit test fix. --- .../Store/Test/Unit/Model/StoreTest.php | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php index f4a5010e51b88..dddc6828eb961 100644 --- a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php @@ -160,7 +160,7 @@ public function testGetWebsite() /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, - ['websiteRepository' => $websiteRepository,] + ['websiteRepository' => $websiteRepository] ); $model->setWebsiteId($websiteId); @@ -181,7 +181,7 @@ public function testGetWebsiteIfWebsiteIsNotExist() /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, - ['websiteRepository' => $websiteRepository,] + ['websiteRepository' => $websiteRepository] ); $model->setWebsiteId(null); @@ -207,7 +207,7 @@ public function testGetGroup() /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, - ['groupRepository' => $groupRepository,] + ['groupRepository' => $groupRepository] ); $model->setGroupId($groupId); @@ -228,7 +228,7 @@ public function testGetGroupIfGroupIsNotExist() /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, - ['groupRepository' => $groupRepository,] + ['groupRepository' => $groupRepository] ); $model->setGroupId(null); @@ -377,30 +377,31 @@ public function testGetBaseUrlEntryPoint() $configMock = $this->getMockForAbstractClass(\Magento\Framework\App\Config\ReinitableConfigInterface::class); $configMock->expects($this->atLeastOnce()) ->method('getValue') - ->will($this->returnCallback( - function ($path, $scope, $scopeCode) use ($expectedPath) { - return $expectedPath == $path ? 'http://domain.com/' . $path . '/' : null; - } - )); + ->willReturnCallback(function ($path, $scope, $scopeCode) use ($expectedPath) { + return $expectedPath == $path ? 'http://domain.com/' . $path . '/' : null; + }); + $this->requestMock->expects($this->once()) + ->method('getServer') + ->with('SCRIPT_FILENAME') + ->willReturn('test_script.php'); + /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, [ 'config' => $configMock, 'isCustomEntryPoint' => false, + 'request' => $this->requestMock ] ); $model->setCode('scopeCode'); $this->setUrlModifier($model); - $server = $_SERVER; - $_SERVER['SCRIPT_FILENAME'] = 'test_script.php'; $this->assertEquals( $expectedBaseUrl, $model->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_LINK, false) ); - $_SERVER = $server; } /** @@ -592,7 +593,7 @@ public function testGetAllowedCurrencies() /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, - ['config' => $configMock, 'currencyInstalled' => $currencyPath,] + ['config' => $configMock, 'currencyInstalled' => $currencyPath] ); $this->assertEquals($expectedResult, $model->getAllowedCurrencies()); @@ -666,8 +667,7 @@ public function isCurrentlySecureDataProvider() 'unsecure request, no secure base url registered' => [false, 443, false, true, null], 'unsecure request, not using registered port' => [false, 80], 'unsecure request, using registered port, not using secure in frontend' => [false, 443, false, false], - 'unsecure request, no secure base url registered, not using secure in frontend' => - [false, 443, false, false, null], + 'unsecure request, no secure base url registered, not using secure in frontend' => [false, 443, false, false, null], 'unsecure request, not using registered port, not using secure in frontend' => [false, 80, false, false], ]; } From 977a18a86f0fdcaae1926f0730c4e31ee022c743 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 11 Apr 2019 17:44:50 +0300 Subject: [PATCH 247/585] magento/magento2#20968: Integration tests fix. --- .../Plugin/RequestPreprocessorTest.php | 2 +- .../Magento/Store/Model/StoreTest.php | 21 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Store/App/FrontController/Plugin/RequestPreprocessorTest.php b/dev/tests/integration/testsuite/Magento/Store/App/FrontController/Plugin/RequestPreprocessorTest.php index ebf302c16bd69..0e158821f1802 100644 --- a/dev/tests/integration/testsuite/Magento/Store/App/FrontController/Plugin/RequestPreprocessorTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/App/FrontController/Plugin/RequestPreprocessorTest.php @@ -56,7 +56,7 @@ public function testHttpsPassSecureLoginPost() $this->prepareRequest(true); $this->dispatch('customer/account/loginPost/'); $redirectUrl = str_replace('http://', 'https://', $this->baseUrl) . - 'index.php/customer/account/'; + 'customer/account/'; $this->assertResponseRedirect($this->getResponse(), $redirectUrl); $this->assertTrue($this->_objectManager->get(Session::class)->isLoggedIn()); $this->setFrontendCompletelySecureRollback(); diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php index bb6d1687052e3..32862ed99c475 100644 --- a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php @@ -8,7 +8,6 @@ use Magento\Catalog\Model\ProductRepository; use Magento\Framework\App\Bootstrap; -use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\UrlInterface; use Magento\Store\Api\StoreRepositoryInterface; @@ -201,7 +200,7 @@ public function testGetBaseUrlInPub() */ public function testGetBaseUrlForCustomEntryPoint($type, $useCustomEntryPoint, $useStoreCode, $expected) { - /* config operations require store to be loaded */ + /* config operations require store to be loaded */ $this->model->load('default'); \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->get(\Magento\Framework\App\Config\MutableScopeConfigInterface::class) @@ -213,6 +212,10 @@ public function testGetBaseUrlForCustomEntryPoint($type, $useCustomEntryPoint, $ // emulate custom entry point $_SERVER['SCRIPT_FILENAME'] = 'custom_entry.php'; + $request = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\Framework\App\RequestInterface::class); + $request->setServer(new Parameters($_SERVER)); + if ($useCustomEntryPoint) { $property = new \ReflectionProperty($this->model, '_isCustomEntryPoint'); $property->setAccessible(true); @@ -298,11 +301,11 @@ public function testGetCurrentUrl() $url = $product->getUrlInStore(); $this->assertEquals( - $secondStore->getBaseUrl().'catalog/product/view/id/1/s/simple-product/', + $secondStore->getBaseUrl() . 'catalog/product/view/id/1/s/simple-product/', $url ); $this->assertEquals( - $secondStore->getBaseUrl().'?___from_store=default', + $secondStore->getBaseUrl() . '?___from_store=default', $secondStore->getCurrentUrl() ); $this->assertEquals( @@ -332,25 +335,25 @@ public function testGetCurrentUrlWithUseStoreInUrlFalse() $product->setStoreId($secondStore->getId()); $url = $product->getUrlInStore(); - /** @var \Magento\Catalog\Model\CategoryRepository $categoryRepository */ + /** @var \Magento\Catalog\Model\CategoryRepository $categoryRepository */ $categoryRepository = $objectManager->get(\Magento\Catalog\Model\CategoryRepository::class); $category = $categoryRepository->get(333, $secondStore->getStoreId()); $this->assertEquals( - $secondStore->getBaseUrl().'catalog/category/view/s/category-1/id/333/', + $secondStore->getBaseUrl() . 'catalog/category/view/s/category-1/id/333/', $category->getUrl() ); $this->assertEquals( - $secondStore->getBaseUrl(). + $secondStore->getBaseUrl() . 'catalog/product/view/id/333/s/simple-product-three/?___store=fixture_second_store', $url ); $this->assertEquals( - $secondStore->getBaseUrl().'?___store=fixture_second_store&___from_store=default', + $secondStore->getBaseUrl() . '?___store=fixture_second_store&___from_store=default', $secondStore->getCurrentUrl() ); $this->assertEquals( - $secondStore->getBaseUrl().'?___store=fixture_second_store', + $secondStore->getBaseUrl() . '?___store=fixture_second_store', $secondStore->getCurrentUrl(false) ); } From 063a684b4c8e0c92029aed8ec50277d021e3de0d Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Thu, 11 Apr 2019 09:48:08 -0500 Subject: [PATCH 248/585] MC-4575: Convert CreateCustomerSegmentEntityWithCustomerConditionsPartTwoTest to MFTF[A --- .../StorefrontCheckCartDiscountAndSummaryActionGroup.xml | 1 + .../Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml index 790674f03ea69..6c541db6defcc 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckCartDiscountAndSummaryActionGroup.xml @@ -17,6 +17,7 @@ <waitForPageLoad stepKey="waitForPageLoad"/> <waitForLoadingMaskToDisappear stepKey="waitForPrices"/> <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-${{discount}}" stepKey="assertDiscount"/> + <wait time="10" stepKey="waitForTotalPrice"/> <see selector="{{CheckoutCartSummarySection.total}}" userInput="${{total}}" stepKey="assertTotal"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml index 8d14a9a561900..e29d3e1fa145b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml @@ -14,7 +14,7 @@ <element name="shippingMethodForm" type="text" selector="#co-shipping-method-form"/> <element name="shippingMethod" type="text" selector="//*[@id='cart-totals']//tr[@class='totals shipping excl']//th//span[@class='value']"/> <element name="shipping" type="text" selector="//*[@id='cart-totals']//tr[@class='totals shipping excl']//td//span[@class='price']"/> - <element name="total" type="text" selector="//*[@id='cart-totals']//tr[@class='grand totals']//td//span[@class='price']"/> + <element name="total" type="text" selector="//*[@id='cart-totals']//tr[@class='grand totals']//td//span[@class='price']" timeout="10"/> <element name="proceedToCheckout" type="button" selector=".action.primary.checkout span" timeout="30"/> <element name="discountAmount" type="text" selector="td[data-th='Discount']"/> <element name="shippingHeading" type="button" selector="#block-shipping-heading"/> From cff19550d60e98ec5d7925db0069df6918e75d5f Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Thu, 11 Apr 2019 11:52:47 -0500 Subject: [PATCH 249/585] added tags to mtf tests --- .../Test/TestCase/CreateCatalogPriceRuleEntityTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.xml index 819fb7b25e497..25b46ccd6c093 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.xml @@ -29,6 +29,7 @@ <data name="catalogPriceRule/data/condition" xsi:type="string">-</data> <data name="catalogPriceRule/data/simple_action" xsi:type="string">Apply as fixed amount</data> <data name="catalogPriceRule/data/discount_amount" xsi:type="string">10</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleSuccessSaveMessage" /> <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleNoticeMessage" /> <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleForm" /> From b881a5d98db719eae436d80965ea41365b53295e Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Fri, 12 Apr 2019 00:41:22 +0530 Subject: [PATCH 250/585] Fixed #22223 Missing/Wrong data display on downloadable report table reports>downloads in BO --- .../ResourceModel/Product/Downloads/Collection.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php index 1985db0b90e2a..a7932e8a11f81 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php @@ -97,4 +97,15 @@ public function addFieldToFilter($field, $condition = null) } return $this; } + + /** + * Get SQL for get record count without left JOINs and group + * + * @return \Magento\Framework\DB\Select + */ + public function getSelectCountSql() { + $countSelect = parent::getSelectCountSql(); + $countSelect->reset(\Zend\Db\Sql\Select::GROUP); + return $countSelect; + } } From 184191f0d3e2dd1f26dc166c1e3295b998baba25 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 11 Apr 2019 15:52:37 -0500 Subject: [PATCH 251/585] MAGETWO-93628: Shopping cart is emptied after reset password procedure --- app/code/Magento/Customer/Model/AccountManagement.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 1806ea05f2fea..58a527769df78 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -1070,7 +1070,10 @@ public function validate(CustomerInterface $customer) $result = $this->getEavValidator()->isValid($customerModel); if ($result === false && is_array($this->getEavValidator()->getMessages())) { return $validationResults->setIsValid(false)->setMessages( - array_merge(...$this->getEavValidator()->getMessages()) + call_user_func_array( + 'array_merge', + $this->getEavValidator()->getMessages() + ) ); } return $validationResults->setIsValid(true)->setMessages([]); From 62e7573d9bd6079ab368394cafdb641de6a4d127 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 11 Apr 2019 17:38:51 -0500 Subject: [PATCH 252/585] Issue-230: adding varnish - fix composer suggest - put tags on cms - fix graphical passing variables as non decodable json - removing cacheable true, adding cacheable false to cart query to get accurate data --- app/code/Magento/CatalogGraphQl/composer.json | 1 + app/code/Magento/CatalogGraphQl/etc/schema.graphqls | 8 ++++---- app/code/Magento/CmsGraphQl/composer.json | 1 + app/code/Magento/CmsGraphQl/etc/schema.graphqls | 4 ++-- app/code/Magento/GraphQl/Controller/GraphQl.php | 2 ++ app/code/Magento/GraphQl/composer.json | 3 ++- app/code/Magento/QuoteGraphQl/composer.json | 3 ++- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 2 +- 8 files changed, 15 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/composer.json b/app/code/Magento/CatalogGraphQl/composer.json index eb86ac634412e..950b496263ffd 100644 --- a/app/code/Magento/CatalogGraphQl/composer.json +++ b/app/code/Magento/CatalogGraphQl/composer.json @@ -14,6 +14,7 @@ }, "suggest": { "magento/module-graph-ql": "*", + "magento/module-graph-ql-cache": "*", "magento/module-store-graph-ql": "*" }, "license": [ diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index ec7cd62ad9d2f..92f155c9c5ed9 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -9,11 +9,11 @@ type Query { currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") ): Products - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_p", cacheable: true) + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_p") category ( id: Int @doc(description: "Id of the category") ): CategoryTree - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_c", cacheable: true) + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_c") } enum CurrencyEnum @doc(description: "The list of available currency codes") { @@ -275,7 +275,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available") manufacturer: Int @doc(description: "A number representing the product's manufacturer") - categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @cache(cache_tag: "cat_c", cacheable: true) @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") + categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @cache(cache_tag: "cat_c") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") canonical_url: String @doc(description: "Canonical URL") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\CanonicalUrl") } @@ -396,7 +396,7 @@ interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."), currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") - ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cache_tag: "cat_p", cacheable: true) @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") + ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cache_tag: "cat_p") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") breadcrumbs: [Breadcrumb] @doc(description: "Breadcrumbs, parent categories info") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Breadcrumbs") } diff --git a/app/code/Magento/CmsGraphQl/composer.json b/app/code/Magento/CmsGraphQl/composer.json index 6a2e3950f93d0..18a6f1aa95e37 100644 --- a/app/code/Magento/CmsGraphQl/composer.json +++ b/app/code/Magento/CmsGraphQl/composer.json @@ -10,6 +10,7 @@ }, "suggest": { "magento/module-graph-ql": "*", + "magento/module-graph-ql-cache": "*", "magento/module-store-graph-ql": "*" }, "license": [ diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index e8abd2201b886..385c7ee1eacc0 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -13,10 +13,10 @@ type StoreConfig @doc(description: "The type contains information about a store type Query { cmsPage ( id: Int @doc(description: "Id of the CMS page") - ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") + ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cache_tag: "cms_p") cmsBlocks ( identifiers: [String] @doc(description: "Identifiers of the CMS blocks") - ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") + ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cache_tag: "cms_b") } type CmsPage @doc(description: "CMS page defines all CMS page information") { diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index 748793b541547..ed66c92c3bfb4 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -162,6 +162,8 @@ private function getDataFromRequest(RequestInterface $request) : array $data = $request->getParams(); $data['variables'] = isset($data['variables']) ? $this->jsonSerializer->unserialize($data['variables']) : null; + $data['variables'] = is_array($data['variables']) ? + $data['variables'] : null; } else { return []; } diff --git a/app/code/Magento/GraphQl/composer.json b/app/code/Magento/GraphQl/composer.json index a81fb61984e0c..3a1e8d1bfd9f4 100644 --- a/app/code/Magento/GraphQl/composer.json +++ b/app/code/Magento/GraphQl/composer.json @@ -9,7 +9,8 @@ "magento/framework": "*" }, "suggest": { - "magento/module-webapi": "*" + "magento/module-webapi": "*", + "magento/module-graph-ql-cache": "*" }, "license": [ "OSL-3.0", diff --git a/app/code/Magento/QuoteGraphQl/composer.json b/app/code/Magento/QuoteGraphQl/composer.json index 22ca9cfdfae9a..a3c07f7df2cee 100644 --- a/app/code/Magento/QuoteGraphQl/composer.json +++ b/app/code/Magento/QuoteGraphQl/composer.json @@ -14,7 +14,8 @@ "magento/module-sales": "*" }, "suggest": { - "magento/module-graph-ql": "*" + "magento/module-graph-ql": "*", + "magento/module-graph-ql-cache": "*" }, "license": [ "OSL-3.0", diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 9ec3492f64531..4f26d9260b348 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -2,7 +2,7 @@ # See COPYING.txt for license details. type Query { - cart(cart_id: String!): Cart @resolver (class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\Cart") @doc(description:"Returns information about shopping cart") + cart(cart_id: String!): Cart @resolver (class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\Cart") @doc(description:"Returns information about shopping cart") @cache(cacheable: false) } type Mutation { From 9e24d22ac0c6ff6afedefadc9401da6907980d48 Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Fri, 12 Apr 2019 12:39:19 +0530 Subject: [PATCH 253/585] Resolved Alignment Issue While Editing Order Data containing Downlodable Products #20917 --- .../templates/product/composite/fieldset/downloadable.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml b/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml index c86eb56a39008..79e93abf58b99 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml +++ b/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml @@ -29,7 +29,7 @@ value="<?= /* @escapeNotVerified */ $_link->getId() ?>" <?= /* @escapeNotVerified */ $block->getLinkCheckedValue($_link) ?> price="<?= /* @escapeNotVerified */ $block->getCurrencyPrice($_link->getPrice()) ?>"/> <?php endif; ?> - <label for="links_<?= /* @escapeNotVerified */ $_link->getId() ?>" class="label"> + <label for="links_<?= /* @escapeNotVerified */ $_link->getId() ?>" class="label admin__field-label"> <?= $block->escapeHtml($_link->getTitle()) ?> <?php if ($_link->getSampleFile() || $_link->getSampleUrl()): ?>  (<a href="<?= /* @escapeNotVerified */ $block->getLinkSampleUrl($_link) ?>" <?= $block->getIsOpenInNewWindow()?'onclick="this.target=\'_blank\'"':'' ?>><?= /* @escapeNotVerified */ __('sample') ?></a>) From 5c84c1ad6aecbf6209d04bcaa160c49f356344d4 Mon Sep 17 00:00:00 2001 From: Marius Strajeru <tzyganu@gmail.com> Date: Fri, 12 Apr 2019 14:13:14 +0300 Subject: [PATCH 254/585] #22299: Cms block cache key does not contain the store id --- app/code/Magento/Cms/Block/Block.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/code/Magento/Cms/Block/Block.php b/app/code/Magento/Cms/Block/Block.php index d0d75ea691195..4fc37b50dcbc0 100644 --- a/app/code/Magento/Cms/Block/Block.php +++ b/app/code/Magento/Cms/Block/Block.php @@ -84,4 +84,14 @@ public function getIdentities() { return [\Magento\Cms\Model\Block::CACHE_TAG . '_' . $this->getBlockId()]; } + + /** + * {@inheritdoc} + */ + public function getCacheKeyInfo() + { + $cacheKeyInfo = parent::getCacheKeyInfo(); + $cacheKeyInfo[] = $this->_storeManager->getStore()->getId(); + return $cacheKeyInfo; + } } From b39550ae4e947da335cea2e836005fc000b0082a Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 15:14:39 +0300 Subject: [PATCH 255/585] magento/magento2#/19806: Static test fix. --- app/code/Magento/Downloadable/Model/SampleRepository.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Downloadable/Model/SampleRepository.php b/app/code/Magento/Downloadable/Model/SampleRepository.php index 98af48d1df993..07c7631fade13 100644 --- a/app/code/Magento/Downloadable/Model/SampleRepository.php +++ b/app/code/Magento/Downloadable/Model/SampleRepository.php @@ -23,6 +23,7 @@ /** * Class SampleRepository + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInterface @@ -100,7 +101,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function getList($sku) { @@ -209,6 +210,8 @@ public function save( } /** + * Save sample. + * * @param \Magento\Catalog\Api\Data\ProductInterface $product * @param SampleInterface $sample * @param bool $isGlobalScopeContent @@ -257,6 +260,8 @@ protected function saveSample( } /** + * Update sample. + * * @param \Magento\Catalog\Api\Data\ProductInterface $product * @param SampleInterface $sample * @param bool $isGlobalScopeContent @@ -319,7 +324,7 @@ protected function updateSample( } /** - * {@inheritdoc} + * @inheritdoc */ public function delete($id) { From 49d5454b518332b8d95b91b66b75fa1399c63a8f Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 17:12:41 +0300 Subject: [PATCH 256/585] magento/magento2#20968: Static test fix. --- app/code/Magento/Store/Test/Unit/Model/StoreTest.php | 3 ++- .../integration/testsuite/Magento/Store/Model/StoreTest.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php index dddc6828eb961..a83ca833a15e0 100644 --- a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php @@ -667,7 +667,8 @@ public function isCurrentlySecureDataProvider() 'unsecure request, no secure base url registered' => [false, 443, false, true, null], 'unsecure request, not using registered port' => [false, 80], 'unsecure request, using registered port, not using secure in frontend' => [false, 443, false, false], - 'unsecure request, no secure base url registered, not using secure in frontend' => [false, 443, false, false, null], + 'unsecure request, no secure base url registered, not using secure in frontend' => + [false, 443, false, false, null], 'unsecure request, not using registered port, not using secure in frontend' => [false, 80, false, false], ]; } diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php index 32862ed99c475..00de5544d8fb7 100644 --- a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php @@ -15,6 +15,7 @@ /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * phpcs:disable Magento2.Security.Superglobal */ class StoreTest extends \PHPUnit\Framework\TestCase { @@ -408,7 +409,7 @@ public function testSaveValidation($badStoreData) /** * @return array */ - public static function saveValidationDataProvider() + public function saveValidationDataProvider() { return [ 'empty store name' => [['name' => '']], From 2f797226d472b51e6cffded421f6b53e75bf2b10 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Fri, 12 Apr 2019 10:09:05 -0500 Subject: [PATCH 257/585] Issue-230: adding varnish - add Id to the cms resovlers --- .../Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php | 1 + app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php | 1 + 2 files changed, 2 insertions(+) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php index 47a2439c4fad0..fa4944381b858 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php @@ -59,6 +59,7 @@ public function getData(string $blockIdentifier): array $renderedContent = $this->widgetFilter->filter($block->getContent()); $blockData = [ + BlockInterface::BLOCK_ID => $block->getId(), BlockInterface::IDENTIFIER => $block->getIdentifier(), BlockInterface::TITLE => $block->getTitle(), BlockInterface::CONTENT => $renderedContent, diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index 22009824452be..001209ba79677 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -55,6 +55,7 @@ public function getData(int $pageId): array $renderedContent = $this->widgetFilter->filter($page->getContent()); $pageData = [ + PageInterface::PAGE_ID => $page->getId(), 'url_key' => $page->getIdentifier(), PageInterface::TITLE => $page->getTitle(), PageInterface::CONTENT => $renderedContent, From f0831c7d4e225a8998601f11865c3ea05ccbd220 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Fri, 12 Apr 2019 18:18:32 +0300 Subject: [PATCH 258/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Added supress for static test; --- app/code/Magento/Ups/Model/Carrier.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index d3a0bb86b0496..0e2ce05f2d079 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -1528,6 +1528,7 @@ protected function _sendShipmentAcceptRequest(Element $shipmentConfirmResponse) $shippingLabelContent = (string)$response->ShipmentResults->PackageResults->LabelImage->GraphicImage; $trackingNumber = (string)$response->ShipmentResults->PackageResults->TrackingNumber; + // phpcs:ignore Magento2.Functions.DiscouragedFunction $result->setShippingLabelContent(base64_decode($shippingLabelContent)); $result->setTrackingNumber($trackingNumber); } From 955e16c7b9920ee41260d5873aac8756fceff111 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 12 Apr 2019 11:46:12 -0500 Subject: [PATCH 259/585] Issue-230: Implement cache tag generation for GraphQL queries - Implement cache tag indentity resolvers --- .../Resolver/Category/IdentityResolver.php | 26 +++++++ .../Resolver/Product/IdentityResolver.php | 33 +++++++++ .../CatalogGraphQl/etc/schema.graphqls | 10 ++- .../Model/Resolver/Block/IdentityResolver.php | 36 +++++++++ .../Model/Resolver/DataProvider/Page.php | 1 + .../Model/Resolver/Page/IdentityResolver.php | 28 +++++++ .../Magento/CmsGraphQl/etc/schema.graphqls | 4 +- .../Model/IdentityResolverInterface.php | 20 +++++ .../Model/CacheableQueryHandler.php | 74 ++++++++----------- .../Model/Plugin/Query/Resolver.php | 2 +- .../MetaReader/CacheTagReader.php | 6 ++ 11 files changed, 190 insertions(+), 50 deletions(-) create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Category/IdentityResolver.php create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php create mode 100644 app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php create mode 100644 app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php create mode 100644 app/code/Magento/GraphQl/Model/IdentityResolverInterface.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/IdentityResolver.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/IdentityResolver.php new file mode 100644 index 0000000000000..9334e3383f2f3 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/IdentityResolver.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogGraphQl\Model\Resolver\Category; + +use Magento\GraphQl\Model\IdentityResolverInterface; + +/** + * Identity for resolved category + */ +class IdentityResolver implements IdentityResolverInterface +{ + /** + * Get category ID from resolved data + * + * @param array $resolvedData + * @return array + */ + public function getIdentifiers(array $resolvedData): array + { + return empty($resolvedData['id']) ? [] : [$resolvedData['id']]; + } +} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php new file mode 100644 index 0000000000000..8c659bc968210 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogGraphQl\Model\Resolver\Product; + +use Magento\GraphQl\Model\IdentityResolverInterface; + +/** + * Identity for resolved products + */ +class IdentityResolver implements IdentityResolverInterface +{ + /** + * Get product ids for cache tag + * + * @param array $resolvedData + * @return array + */ + public function getIdentifiers(array $resolvedData) : array + { + $ids = []; + $items = $resolvedData['items'] ?? []; + foreach ($items as $item) { + $ids[] = $item['entity_id']; + } + + return $ids; + } +} diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 92f155c9c5ed9..a44f473974a4c 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -9,11 +9,13 @@ type Query { currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") ): Products - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_p") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") + @cache(cache_tag: "cat_p", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\IdentityResolver") category ( id: Int @doc(description: "Id of the category") ): CategoryTree - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_c") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") + @cache(cache_tag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\IdentityResolver") } enum CurrencyEnum @doc(description: "The list of available currency codes") { @@ -275,7 +277,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available") manufacturer: Int @doc(description: "A number representing the product's manufacturer") - categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @cache(cache_tag: "cat_c") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") + categories: [CategoryInterface] @doc(description: "The categories assigned to a product")@cache(cache_tag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\IdentityResolver") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") canonical_url: String @doc(description: "Canonical URL") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\CanonicalUrl") } @@ -396,7 +398,7 @@ interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."), currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") - ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cache_tag: "cat_p") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") + ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cache_tag: "cat_p", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\IdentityResolver") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") breadcrumbs: [Breadcrumb] @doc(description: "Breadcrumbs, parent categories info") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Breadcrumbs") } diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php new file mode 100644 index 0000000000000..0dd99ee558cb5 --- /dev/null +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CmsGraphQl\Model\Resolver\Block; + +use Magento\Cms\Api\Data\BlockInterface; +use Magento\GraphQl\Model\IdentityResolverInterface; + +/** + * Identity for resolved CMS block + */ +class IdentityResolver implements IdentityResolverInterface +{ + /** + * Get block identifiers from resolved data + * + * @param array $resolvedData + * @return array + */ + public function getIdentifiers(array $resolvedData): array + { + $ids = []; + $items = $resolvedData['items'] ?? []; + foreach ($items as $item) { + if (!empty($item[BlockInterface::IDENTIFIER])) { + $ids[] = $item[BlockInterface::IDENTIFIER ]; + } + } + + return $ids; + } +} diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index 22009824452be..001209ba79677 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -55,6 +55,7 @@ public function getData(int $pageId): array $renderedContent = $this->widgetFilter->filter($page->getContent()); $pageData = [ + PageInterface::PAGE_ID => $page->getId(), 'url_key' => $page->getIdentifier(), PageInterface::TITLE => $page->getTitle(), PageInterface::CONTENT => $renderedContent, diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php new file mode 100644 index 0000000000000..f912f76650263 --- /dev/null +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CmsGraphQl\Model\Resolver\Page; + +use Magento\Cms\Api\Data\PageInterface; +use Magento\GraphQl\Model\IdentityResolverInterface; + +/** + * Identity for resolved CMS page + */ +class IdentityResolver implements IdentityResolverInterface +{ + /** + * Get page ID from resolved data + * + * @param array $resolvedData + * @return array + */ + public function getIdentifiers(array $resolvedData): array + { + return empty($resolvedData[PageInterface::PAGE_ID]) ? [] : [$resolvedData[PageInterface::PAGE_ID]]; + } +} diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index 385c7ee1eacc0..b9a81b3457a37 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -13,10 +13,10 @@ type StoreConfig @doc(description: "The type contains information about a store type Query { cmsPage ( id: Int @doc(description: "Id of the CMS page") - ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cache_tag: "cms_p") + ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cache_tag: "cms_p", cacheIdentityResolver: "Magento\\CmsGraphQl\\Model\\Resolver\\Page\\IdentityResolver") cmsBlocks ( identifiers: [String] @doc(description: "Identifiers of the CMS blocks") - ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cache_tag: "cms_b") + ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cache_tag: "cms_b", cacheIdentityResolver: "Magento\\CmsGraphQl\\Model\\Resolver\\Block\\IdentityResolver") } type CmsPage @doc(description: "CMS page defines all CMS page information") { diff --git a/app/code/Magento/GraphQl/Model/IdentityResolverInterface.php b/app/code/Magento/GraphQl/Model/IdentityResolverInterface.php new file mode 100644 index 0000000000000..c9c6feff33996 --- /dev/null +++ b/app/code/Magento/GraphQl/Model/IdentityResolverInterface.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Model; + +interface IdentityResolverInterface +{ + + /** + * Get identifiers from resolved data + * + * @param array $resolvedData + * @return array + */ + public function getIdentifiers(array $resolvedData) : array; +} diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php index b408d29eeb4f8..3c8c79d0d4dd1 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -9,6 +9,7 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\App\RequestInterface; +use Magento\Framework\ObjectManagerInterface; /** * Handler of collecting tagging on cache. @@ -28,70 +29,57 @@ class CacheableQueryHandler */ private $request; + /** + * @var ObjectManagerInterface + */ + private $objectManager; + /** * @param CacheableQuery $cacheableQuery * @param RequestInterface $request + * @param ObjectManagerInterface $objectManager */ - public function __construct(CacheableQuery $cacheableQuery, RequestInterface $request) - { + public function __construct( + CacheableQuery $cacheableQuery, + RequestInterface $request, + ObjectManagerInterface $objectManager + ) { $this->cacheableQuery = $cacheableQuery; $this->request = $request; + $this->objectManager = $objectManager; } /** * Set cache validity to the cacheableQuery after resolving any resolver or evaluating a promise in a query * - * @param mixed $resolvedValue + * @param array $resolvedValue * @param Field $field * @return void */ public function handleCacheFromResolverResponse(array $resolvedValue, Field $field) : void { $cache = $field->getCache(); - $cacheTag = isset($cache['cache_tag']) ? $cache['cache_tag'] : []; - $cacheable = isset($cache['cacheable']) ? $cache['cacheable'] : true; - if (!empty($cacheTag) && $this->request->isGet() && $cacheable) { - $cacheTags = []; - // Resolved value must have cache IDs defined - $resolvedItemsIds = $this->extractResolvedItemsIds($resolvedValue); - if (!empty($resolvedItemsIds)) { - $cacheTags = [$cacheTag]; - } - foreach ($resolvedItemsIds as $itemId) { - $cacheTags[] = $cacheTag . '_' . $itemId; - } - $this->cacheableQuery->addCacheTags($cacheTags); - } - $this->setCacheValidity($cacheable); - } + $cacheIdentityResolverClass = $cache['cacheIdentityResolver'] ?? null; + $cacheable = $cache['cacheable']; + $cacheTag = $cache['cache_tag'] ?? null; - /** - * Extract ids for resolved items - * - * @param array $resolvedValue - * @return array - */ - private function extractResolvedItemsIds(array $resolvedValue) : array - { - $ids = []; - if (isset($resolvedValue['ids']) && is_array($resolvedValue['ids'])) { - return $resolvedValue['ids']; - } - if (isset($resolvedValue['items']) && is_array($resolvedValue['items'])) { - return array_keys($resolvedValue['items']); - } - - if (isset($resolvedValue['id'])) { - $ids[] = $resolvedValue['id']; - return $ids; - } + if (false === $cacheable) { + $this->setCacheValidity(false); + } elseif ($cacheTag && $cacheIdentityResolverClass && $this->request->isGet()) { + $cacheIdentityResolver = $this->objectManager->get($cacheIdentityResolverClass); + $cacheTagIds = $cacheIdentityResolver->getIdentifiers($resolvedValue); - foreach ($resolvedValue as $item) { - if (isset($item['id'])) { - $ids[] = $item['id']; + if (!empty($cacheTagIds)) { + $cacheTags = array_map( + function ($id) use ($cacheTag) { + return $cacheTag . '_' . $id; + }, + $cacheTagIds + ); + $this->cacheableQuery->addCacheTags($cacheTags); } + $this->setCacheValidity(true); } - return $ids; } /** diff --git a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php index 3c98d292b0dea..54cb5559923af 100644 --- a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php +++ b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php @@ -56,7 +56,7 @@ public function afterResolve( array $args = null ) { /** Only if array @see \Magento\Framework\GraphQl\Query\Resolver\Value */ - if (is_array($resolvedValue)) { + if (is_array($resolvedValue) && !empty($field->getCache())) { $this->cacheableQueryHandler->handleCacheFromResolverResponse($resolvedValue, $field); } elseif ($resolvedValue instanceof \Magento\Framework\GraphQl\Query\Resolver\Value) { $resolvedValue->then(function () use ($resolvedValue, $field) { diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php index 6fa66b80a8c81..e3a11a73c2624 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php @@ -36,6 +36,12 @@ public function read(\GraphQL\Language\AST\NodeList $directives) : array ["cacheable" => $directiveArgument->value->value] ); } + if ($directiveArgument->name->value == 'cacheIdentityResolver') { + $argMap = array_merge( + $argMap, + ["cacheIdentityResolver" => $directiveArgument->value->value] + ); + } } } } From 1a6e8bbb65c11c1fec1f7a178e033e1ca6e7ae68 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Fri, 12 Apr 2019 12:07:05 -0500 Subject: [PATCH 260/585] GraphQL-514: Test coverage for tag cache generation - integration test coverage for product --- .../GraphQl/PageCache/CacheTagTest.php | 21 ++- .../Controller/GraphQlCacheControllerTest.php | 122 ++++++++++++++++++ 2 files changed, 136 insertions(+), 7 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index 7cb3afbc3eacb..a01f31abb65d7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -10,6 +10,7 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Product; +use Magento\Deploy\Model\Mode; use Magento\TestFramework\ObjectManager; use Magento\TestFramework\App\State; use Magento\TestFramework\Helper\Bootstrap; @@ -18,16 +19,18 @@ class CacheTagTest extends GraphQlAbstract { /** - * @var \Magento\Framework\App\State - */ - protected $state; - - /** - * Tests various use cases for built-in cache for graphql query + * Tests if Magento cache tags and debug headers for products are generated properly * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_url_key.php */ public function testCacheTagsAndCacheDebugHeaderFromResponse() { + $this->markTestSkipped( + 'This test will stay skipped until DEVOPS-4924 is resolved' + ); + /** @var State $state */ + $state = Bootstrap::getObjectManager()->get(State::class); + $state->setMode(State::MODE_DEVELOPER); + $productSku='simple2'; $query = <<<QUERY @@ -43,6 +46,7 @@ public function testCacheTagsAndCacheDebugHeaderFromResponse() } QUERY; + /** cache-debug should be a MISS when product is queried for first time */ $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); @@ -60,7 +64,7 @@ public function testCacheTagsAndCacheDebugHeaderFromResponse() /** update the price attribute for the product in test */ $product->setPrice(15); $product->save(); - /** cache-debug header value should be a MISS after product attribute update */ + /** Cache invalidation happens and cache-debug header value is a MISS after product update */ $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); $this->assertEquals('MISS', rtrim($matchesMiss[1],"\r")); @@ -82,6 +86,9 @@ public function testCacheTagsAndCacheDebugHeaderFromResponse() */ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() { + $this->markTestSkipped( + 'This test will stay skipped until DEVOPS-4924 is resolved' + ); $productSku = 'simple333'; $categoryId ='333'; $query diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php new file mode 100644 index 0000000000000..98965ff41e737 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php @@ -0,0 +1,122 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Controller; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\App\Request\Http; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Tests cache debug headers and cache tag validation for a simple product query + * + * @magentoAppArea graphql + * + * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php + * @magentoDbIsolation disabled + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class GraphQlCacheControllerTest extends \Magento\TestFramework\Indexer\TestCase +{ + const CONTENT_TYPE = 'application/json'; + + /** @var \Magento\Framework\ObjectManagerInterface */ + private $objectManager; + + /** @var GraphQl */ + private $graphql; + + /** @var SerializerInterface */ + private $jsonSerializer; + + /** @var MetadataPool */ + private $metadataPool; + + /** @var Http */ + private $request; + + /** @var \Magento\Framework\App\Response\Http */ + private $response; + + + public static function setUpBeforeClass() + { + $db = Bootstrap::getInstance()->getBootstrap() + ->getApplication() + ->getDbInstance(); + if (!$db->isDbDumpExists()) { + throw new \LogicException('DB dump does not exist.'); + } + $db->restoreFromDbDump(); + + parent::setUpBeforeClass(); + } + + protected function setUp(): void + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); + $this->metadataPool = $this->objectManager->get(MetadataPool::class); + $this->request = $this->objectManager->get(Http::class); + $this->response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + + } + + /** + * Test request is dispatched and response is checked for debug headers and cache tags + * + * @magentoCache all enabled + * @return void + */ + public function testDispatchWithGetForCacheDebugHeadersAndCacheTags(): void + { + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + + /** @var ProductInterface $product */ + $product = $productRepository->get('simple1'); + + $query + = <<<QUERY + { + products(filter: {sku: {eq: "simple1"}}) + { + items { + id + name + sku + } + } + } +QUERY; + + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); + $result->renderResult($this->response); // + $this->assertEquals('MISS', $this->response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $actualCacheTags = explode(',', $this->response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; + foreach (array_keys($actualCacheTags) as $key) { + $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key] + ); + } + } +} + + From b0bac8b9ed13be9def9d6265a0962db25d216e5d Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 12 Apr 2019 12:40:23 -0500 Subject: [PATCH 261/585] Issue-230: Implement cache tag generation for GraphQL queries - Implement cache tag indentity resolvers --- .../Category/CategoriesIdentityResolver.php | 32 +++++++++++++++++++ ...r.php => CategoryTreeIdentityResolver.php} | 2 +- .../CatalogGraphQl/etc/schema.graphqls | 8 ++--- .../Model/CacheableQueryHandler.php | 8 ++--- 4 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php rename app/code/Magento/CatalogGraphQl/Model/Resolver/Category/{IdentityResolver.php => CategoryTreeIdentityResolver.php} (88%) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php new file mode 100644 index 0000000000000..df6689ae902e0 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogGraphQl\Model\Resolver\Category; + +use Magento\GraphQl\Model\IdentityResolverInterface; + +/** + * Identity for multiple resolved categories + */ +class CategoriesIdentityResolver implements IdentityResolverInterface +{ + /** + * Get category IDs from resolved data + * + * @param array $resolvedData + * @return array + */ + public function getIdentifiers(array $resolvedData): array + { + $ids = []; + if(!empty($resolvedData)) { + foreach($resolvedData as $category){ + $ids[] = $category['id']; + } + } + return $ids; + } +} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/IdentityResolver.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentityResolver.php similarity index 88% rename from app/code/Magento/CatalogGraphQl/Model/Resolver/Category/IdentityResolver.php rename to app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentityResolver.php index 9334e3383f2f3..a03fcbf71c79b 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/IdentityResolver.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentityResolver.php @@ -11,7 +11,7 @@ /** * Identity for resolved category */ -class IdentityResolver implements IdentityResolverInterface +class CategoryTreeIdentityResolver implements IdentityResolverInterface { /** * Get category ID from resolved data diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index a44f473974a4c..829e604f3b27c 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -9,13 +9,11 @@ type Query { currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") ): Products - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") - @cache(cache_tag: "cat_p", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\IdentityResolver") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_p", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\IdentityResolver") category ( id: Int @doc(description: "Id of the category") ): CategoryTree - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") - @cache(cache_tag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\IdentityResolver") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentityResolver") } enum CurrencyEnum @doc(description: "The list of available currency codes") { @@ -277,7 +275,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available") manufacturer: Int @doc(description: "A number representing the product's manufacturer") - categories: [CategoryInterface] @doc(description: "The categories assigned to a product")@cache(cache_tag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\IdentityResolver") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") + categories: [CategoryInterface] @doc(description: "The categories assigned to a product")@cache(cache_tag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoriesIdentityResolver") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") canonical_url: String @doc(description: "Canonical URL") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\CanonicalUrl") } diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php index 3c8c79d0d4dd1..b5d1fdaaff4fe 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -60,12 +60,10 @@ public function handleCacheFromResolverResponse(array $resolvedValue, Field $fie { $cache = $field->getCache(); $cacheIdentityResolverClass = $cache['cacheIdentityResolver'] ?? null; - $cacheable = $cache['cacheable']; + $cacheable = $cache['cacheable'] ?? true; $cacheTag = $cache['cache_tag'] ?? null; - if (false === $cacheable) { - $this->setCacheValidity(false); - } elseif ($cacheTag && $cacheIdentityResolverClass && $this->request->isGet()) { + if ($cacheTag && $cacheIdentityResolverClass && $this->request->isGet()) { $cacheIdentityResolver = $this->objectManager->get($cacheIdentityResolverClass); $cacheTagIds = $cacheIdentityResolver->getIdentifiers($resolvedValue); @@ -78,8 +76,8 @@ function ($id) use ($cacheTag) { ); $this->cacheableQuery->addCacheTags($cacheTags); } - $this->setCacheValidity(true); } + $this->setCacheValidity($cacheable); } /** From a74b0c1e0c4a57729620131ac1927b243f6556cf Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Fri, 12 Apr 2019 14:43:03 -0500 Subject: [PATCH 262/585] MAGETWO-93628: Shopping cart is emptied after reset password procedure --- app/code/Magento/Customer/Model/AccountManagement.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 58a527769df78..250d190f8fae7 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -705,6 +705,7 @@ public function resetPassword($email, $resetToken, $newPassword) if ($this->sessionManager->isSessionExists()) { //delete old session and move data to the new session //use this instead of $this->sessionManager->regenerateId because last one doesn't delete old session + // phpcs:ignore Magento2.Functions.DiscouragedFunction session_regenerate_id(true); } $this->customerRepository->save($customer); From 1d2e260798ee816a181cca5234964f81ff2d393f Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 12 Apr 2019 15:51:06 -0500 Subject: [PATCH 263/585] Issue-230: Implement cache tag generation for GraphQL queries - Implement cache tag indentity resolvers --- .../Category/CategoriesIdentityResolver.php | 7 +-- .../Category/CategoryTreeIdentityResolver.php | 3 +- .../Resolver/Product/IdentityResolver.php | 4 +- .../CatalogGraphQl/etc/schema.graphqls | 8 +-- .../Model/Resolver/Block/IdentityResolver.php | 4 +- .../Model/Resolver/Page/IdentityResolver.php | 2 +- .../Magento/CmsGraphQl/etc/schema.graphqls | 4 +- .../Model/CacheableQueryHandler.php | 44 +++++++++-------- .../Model/IdentityResolverPool.php | 49 +++++++++++++++++++ .../Query}/IdentityResolverInterface.php | 2 +- .../MetaReader/CacheTagReader.php | 4 +- 11 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 app/code/Magento/GraphQlCache/Model/IdentityResolverPool.php rename {app/code/Magento/GraphQl/Model => lib/internal/Magento/Framework/GraphQl/Query}/IdentityResolverInterface.php (89%) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php index df6689ae902e0..1fad463ddee19 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php @@ -3,10 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\CatalogGraphQl\Model\Resolver\Category; -use Magento\GraphQl\Model\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\IdentityResolverInterface; /** * Identity for multiple resolved categories @@ -22,8 +23,8 @@ class CategoriesIdentityResolver implements IdentityResolverInterface public function getIdentifiers(array $resolvedData): array { $ids = []; - if(!empty($resolvedData)) { - foreach($resolvedData as $category){ + if (!empty($resolvedData)) { + foreach ($resolvedData as $category) { $ids[] = $category['id']; } } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentityResolver.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentityResolver.php index a03fcbf71c79b..0bfe6d2e4699a 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentityResolver.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentityResolver.php @@ -3,10 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\CatalogGraphQl\Model\Resolver\Category; -use Magento\GraphQl\Model\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\IdentityResolverInterface; /** * Identity for resolved category diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php index 8c659bc968210..eece587eb4299 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php @@ -7,7 +7,7 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Product; -use Magento\GraphQl\Model\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\IdentityResolverInterface; /** * Identity for resolved products @@ -20,7 +20,7 @@ class IdentityResolver implements IdentityResolverInterface * @param array $resolvedData * @return array */ - public function getIdentifiers(array $resolvedData) : array + public function getIdentifiers(array $resolvedData): array { $ids = []; $items = $resolvedData['items'] ?? []; diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 829e604f3b27c..eece33fc26583 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -9,11 +9,11 @@ type Query { currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") ): Products - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_p", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\IdentityResolver") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cacheTag: "cat_p", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\IdentityResolver") category ( id: Int @doc(description: "Id of the category") ): CategoryTree - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cache_tag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentityResolver") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cacheTag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentityResolver") } enum CurrencyEnum @doc(description: "The list of available currency codes") { @@ -275,7 +275,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available") manufacturer: Int @doc(description: "A number representing the product's manufacturer") - categories: [CategoryInterface] @doc(description: "The categories assigned to a product")@cache(cache_tag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoriesIdentityResolver") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") + categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @cache(cacheTag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoriesIdentityResolver") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") canonical_url: String @doc(description: "Canonical URL") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\CanonicalUrl") } @@ -396,7 +396,7 @@ interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."), currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") - ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cache_tag: "cat_p", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\IdentityResolver") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") + ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cacheTag: "cat_p", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\IdentityResolver") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") breadcrumbs: [Breadcrumb] @doc(description: "Breadcrumbs, parent categories info") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Breadcrumbs") } diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php index 0dd99ee558cb5..4f5913c458d05 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php @@ -8,7 +8,7 @@ namespace Magento\CmsGraphQl\Model\Resolver\Block; use Magento\Cms\Api\Data\BlockInterface; -use Magento\GraphQl\Model\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\IdentityResolverInterface; /** * Identity for resolved CMS block @@ -26,7 +26,7 @@ public function getIdentifiers(array $resolvedData): array $ids = []; $items = $resolvedData['items'] ?? []; foreach ($items as $item) { - if (!empty($item[BlockInterface::IDENTIFIER])) { + if (is_array($item) && !empty($item[BlockInterface::IDENTIFIER])) { $ids[] = $item[BlockInterface::IDENTIFIER ]; } } diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php index f912f76650263..d139cb383233f 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php @@ -8,7 +8,7 @@ namespace Magento\CmsGraphQl\Model\Resolver\Page; use Magento\Cms\Api\Data\PageInterface; -use Magento\GraphQl\Model\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\IdentityResolverInterface; /** * Identity for resolved CMS page diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index b9a81b3457a37..1734cf80afd64 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -13,10 +13,10 @@ type StoreConfig @doc(description: "The type contains information about a store type Query { cmsPage ( id: Int @doc(description: "Id of the CMS page") - ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cache_tag: "cms_p", cacheIdentityResolver: "Magento\\CmsGraphQl\\Model\\Resolver\\Page\\IdentityResolver") + ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cacheTag: "cms_p", cacheIdentityResolver: "Magento\\CmsGraphQl\\Model\\Resolver\\Page\\IdentityResolver") cmsBlocks ( identifiers: [String] @doc(description: "Identifiers of the CMS blocks") - ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cache_tag: "cms_b", cacheIdentityResolver: "Magento\\CmsGraphQl\\Model\\Resolver\\Block\\IdentityResolver") + ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cacheTag: "cms_b", cacheIdentityResolver: "Magento\\CmsGraphQl\\Model\\Resolver\\Block\\IdentityResolver") } type CmsPage @doc(description: "CMS page defines all CMS page information") { diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php index b5d1fdaaff4fe..786c822d68226 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -9,7 +9,6 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\App\RequestInterface; -use Magento\Framework\ObjectManagerInterface; /** * Handler of collecting tagging on cache. @@ -30,23 +29,23 @@ class CacheableQueryHandler private $request; /** - * @var ObjectManagerInterface + * @var IdentityResolverPool */ - private $objectManager; + private $identityResolverPool; /** * @param CacheableQuery $cacheableQuery * @param RequestInterface $request - * @param ObjectManagerInterface $objectManager + * @param IdentityResolverPool $identityResolverPool */ public function __construct( CacheableQuery $cacheableQuery, RequestInterface $request, - ObjectManagerInterface $objectManager + IdentityResolverPool $identityResolverPool ) { $this->cacheableQuery = $cacheableQuery; $this->request = $request; - $this->objectManager = $objectManager; + $this->identityResolverPool = $identityResolverPool; } /** @@ -59,23 +58,28 @@ public function __construct( public function handleCacheFromResolverResponse(array $resolvedValue, Field $field) : void { $cache = $field->getCache(); - $cacheIdentityResolverClass = $cache['cacheIdentityResolver'] ?? null; + $cacheIdentityResolverClass = $cache['cacheIdentityResolver'] ?? ''; $cacheable = $cache['cacheable'] ?? true; - $cacheTag = $cache['cache_tag'] ?? null; + $cacheTag = $cache['cacheTag'] ?? null; - if ($cacheTag && $cacheIdentityResolverClass && $this->request->isGet()) { - $cacheIdentityResolver = $this->objectManager->get($cacheIdentityResolverClass); - $cacheTagIds = $cacheIdentityResolver->getIdentifiers($resolvedValue); - - if (!empty($cacheTagIds)) { - $cacheTags = array_map( - function ($id) use ($cacheTag) { - return $cacheTag . '_' . $id; - }, - $cacheTagIds - ); - $this->cacheableQuery->addCacheTags($cacheTags); + $cacheTags = []; + if ($cacheTag && $this->request->isGet()) { + if (!empty($cacheIdentityResolverClass)) { + $cacheIdentityResolver = $this->identityResolverPool->get($cacheIdentityResolverClass); + $cacheTagIds = $cacheIdentityResolver->getIdentifiers($resolvedValue); + if (!empty($cacheTagIds)) { + $cacheTags = array_map( + function ($id) use ($cacheTag) { + return $cacheTag . '_' . $id; + }, + $cacheTagIds + ); + } + } else { + $cacheTags[] = $cacheTag; } + + $this->cacheableQuery->addCacheTags($cacheTags); } $this->setCacheValidity($cacheable); } diff --git a/app/code/Magento/GraphQlCache/Model/IdentityResolverPool.php b/app/code/Magento/GraphQlCache/Model/IdentityResolverPool.php new file mode 100644 index 0000000000000..da97e5ba4f2e2 --- /dev/null +++ b/app/code/Magento/GraphQlCache/Model/IdentityResolverPool.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Model; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\GraphQl\Query\IdentityResolverInterface; + +/** + * Pool of IdentityResolverInterface objects + */ +class IdentityResolverPool +{ + /** + * @var IdentityResolverInterface[] + */ + private $identityResolvers = []; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @param ObjectManagerInterface $objectManager + */ + public function __construct(ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * Get an identity resolver by class name + * + * @param string $identityResolverClass + * @return IdentityResolverInterface + */ + public function get(string $identityResolverClass): IdentityResolverInterface + { + if (!isset($this->identityResolvers[$identityResolverClass])) { + $this->identityResolvers[$identityResolverClass] = $this->objectManager->create($identityResolverClass); + } + return $this->identityResolvers[$identityResolverClass]; + } +} diff --git a/app/code/Magento/GraphQl/Model/IdentityResolverInterface.php b/lib/internal/Magento/Framework/GraphQl/Query/IdentityResolverInterface.php similarity index 89% rename from app/code/Magento/GraphQl/Model/IdentityResolverInterface.php rename to lib/internal/Magento/Framework/GraphQl/Query/IdentityResolverInterface.php index c9c6feff33996..588052c8df6e7 100644 --- a/app/code/Magento/GraphQl/Model/IdentityResolverInterface.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/IdentityResolverInterface.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\Model; +namespace Magento\Framework\GraphQl\Query; interface IdentityResolverInterface { diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php index e3a11a73c2624..ae7ee4a1ec385 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php @@ -24,10 +24,10 @@ public function read(\GraphQL\Language\AST\NodeList $directives) : array foreach ($directives as $directive) { if ($directive->name->value == 'cache') { foreach ($directive->arguments as $directiveArgument) { - if ($directiveArgument->name->value == 'cache_tag') { + if ($directiveArgument->name->value == 'cacheTag') { $argMap = array_merge( $argMap, - ["cache_tag" => $directiveArgument->value->value] + ["cacheTag" => $directiveArgument->value->value] ); } if ($directiveArgument->name->value == 'cacheable') { From 999766cf2ffd177766e7fbcf253ff50d28264ab2 Mon Sep 17 00:00:00 2001 From: Arnoud Beekman <arnoud.beekman@mediact.nl> Date: Sun, 31 Mar 2019 16:22:32 +0200 Subject: [PATCH 264/585] Remove @SuppressWarnings and optimize imports Two @SuppressWarnings could be removed by splitting up the execute method by moving logic to separate private methods. Also the imports of this file are improved. --- .../Catalog/Controller/Category/View.php | 136 +++++++++++------- .../Unit/Controller/Category/ViewTest.php | 2 +- 2 files changed, 88 insertions(+), 50 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Category/View.php b/app/code/Magento/Catalog/Controller/Category/View.php index 2088bb5ea77cd..5129692146ff6 100644 --- a/app/code/Magento/Catalog/Controller/Category/View.php +++ b/app/code/Magento/Catalog/Controller/Category/View.php @@ -6,14 +6,28 @@ */ namespace Magento\Catalog\Controller\Category; -use Magento\Framework\App\Action\HttpPostActionInterface; -use Magento\Framework\App\Action\HttpGetActionInterface; use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Model\Category; +use Magento\Catalog\Model\Design; use Magento\Catalog\Model\Layer\Resolver; use Magento\Catalog\Model\Product\ProductList\ToolbarMemorizer; +use Magento\Catalog\Model\Session; +use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator; +use Magento\Framework\App\Action\Action; +use Magento\Framework\App\Action\Context; +use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Framework\App\ActionInterface; +use Magento\Framework\Controller\Result\ForwardFactory; +use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\DataObject; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\Framework\View\Result\Page; use Magento\Framework\View\Result\PageFactory; -use Magento\Framework\App\Action\Action; +use Magento\Store\Model\StoreManagerInterface; +use Psr\Log\LoggerInterface; /** * View a category on storefront. Needs to be accessible by POST because of the store switching. @@ -25,41 +39,41 @@ class View extends Action implements HttpGetActionInterface, HttpPostActionInter /** * Core registry * - * @var \Magento\Framework\Registry + * @var Registry */ protected $_coreRegistry = null; /** * Catalog session * - * @var \Magento\Catalog\Model\Session + * @var Session */ protected $_catalogSession; /** * Catalog design * - * @var \Magento\Catalog\Model\Design + * @var Design */ protected $_catalogDesign; /** - * @var \Magento\Store\Model\StoreManagerInterface + * @var StoreManagerInterface */ protected $_storeManager; /** - * @var \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator + * @var CategoryUrlPathGenerator */ protected $categoryUrlPathGenerator; /** - * @var \Magento\Framework\View\Result\PageFactory + * @var PageFactory */ protected $resultPageFactory; /** - * @var \Magento\Framework\Controller\Result\ForwardFactory + * @var ForwardFactory */ protected $resultForwardFactory; @@ -83,28 +97,28 @@ class View extends Action implements HttpGetActionInterface, HttpPostActionInter /** * Constructor * - * @param \Magento\Framework\App\Action\Context $context - * @param \Magento\Catalog\Model\Design $catalogDesign - * @param \Magento\Catalog\Model\Session $catalogSession - * @param \Magento\Framework\Registry $coreRegistry - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator - * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory - * @param \Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory + * @param Context $context + * @param Design $catalogDesign + * @param Session $catalogSession + * @param Registry $coreRegistry + * @param StoreManagerInterface $storeManager + * @param CategoryUrlPathGenerator $categoryUrlPathGenerator + * @param PageFactory $resultPageFactory + * @param ForwardFactory $resultForwardFactory * @param Resolver $layerResolver * @param CategoryRepositoryInterface $categoryRepository * @param ToolbarMemorizer|null $toolbarMemorizer * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( - \Magento\Framework\App\Action\Context $context, - \Magento\Catalog\Model\Design $catalogDesign, - \Magento\Catalog\Model\Session $catalogSession, - \Magento\Framework\Registry $coreRegistry, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator, + Context $context, + Design $catalogDesign, + Session $catalogSession, + Registry $coreRegistry, + StoreManagerInterface $storeManager, + CategoryUrlPathGenerator $categoryUrlPathGenerator, PageFactory $resultPageFactory, - \Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory, + ForwardFactory $resultForwardFactory, Resolver $layerResolver, CategoryRepositoryInterface $categoryRepository, ToolbarMemorizer $toolbarMemorizer = null @@ -125,7 +139,7 @@ public function __construct( /** * Initialize requested category object * - * @return \Magento\Catalog\Model\Category|bool + * @return Category|bool */ protected function _initCategory() { @@ -150,8 +164,8 @@ protected function _initCategory() 'catalog_controller_category_init_after', ['category' => $category, 'controller_action' => $this] ); - } catch (\Magento\Framework\Exception\LocalizedException $e) { - $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e); + } catch (LocalizedException $e) { + $this->_objectManager->get(LoggerInterface::class)->critical($e); return false; } @@ -161,13 +175,12 @@ protected function _initCategory() /** * Category view action * - * @return \Magento\Framework\Controller\ResultInterface - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) + * @return ResultInterface + * @throws NoSuchEntityException */ public function execute() { - if ($this->_request->getParam(\Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED)) { + if ($this->_request->getParam(ActionInterface::PARAM_NAME_URL_ENCODED)) { return $this->resultRedirectFactory->create()->setUrl($this->_redirect->getRedirectUrl()); } $category = $this->_initCategory(); @@ -188,29 +201,18 @@ public function execute() $page->getConfig()->setPageLayout($settings->getPageLayout()); } - $hasChildren = $category->hasChildren(); - if ($category->getIsAnchor()) { - $type = $hasChildren ? 'layered' : 'layered_without_children'; - } else { - $type = $hasChildren ? 'default' : 'default_without_children'; - } + $pageType = $this->getPageType($category); - if (!$hasChildren) { + if (!$category->hasChildren()) { // Two levels removed from parent. Need to add default page type. - $parentType = strtok($type, '_'); - $page->addPageLayoutHandles(['type' => $parentType], null, false); + $parentPageType = strtok($pageType, '_'); + $page->addPageLayoutHandles(['type' => $parentPageType], null, false); } - $page->addPageLayoutHandles(['type' => $type], null, false); + $page->addPageLayoutHandles(['type' => $pageType], null, false); $page->addPageLayoutHandles(['id' => $category->getId()]); // apply custom layout update once layout is loaded - $layoutUpdates = $settings->getLayoutUpdates(); - if ($layoutUpdates && is_array($layoutUpdates)) { - foreach ($layoutUpdates as $layoutUpdate) { - $page->addUpdate($layoutUpdate); - $page->addPageLayoutHandles(['layout_update' => sha1($layoutUpdate)], null, false); - } - } + $this->applyLayoutUpdates($page, $settings); $page->getConfig()->addBodyClass('page-products') ->addBodyClass('categorypath-' . $this->categoryUrlPathGenerator->getUrlPath($category)) @@ -221,4 +223,40 @@ public function execute() return $this->resultForwardFactory->create()->forward('noroute'); } } + + /** + * Get page type based on category + * + * @param Category $category + * @return string + */ + private function getPageType(Category $category) + { + $hasChildren = $category->hasChildren(); + if ($category->getIsAnchor()) { + return $hasChildren ? 'layered' : 'layered_without_children'; + } + + return $hasChildren ? 'default' : 'default_without_children'; + } + + /** + * Apply custom layout updates + * + * @param Page $page + * @param DataObject $settings + * @return void + */ + private function applyLayoutUpdates( + Page $page, + DataObject $settings + ) { + $layoutUpdates = $settings->getLayoutUpdates(); + if ($layoutUpdates && is_array($layoutUpdates)) { + foreach ($layoutUpdates as $layoutUpdate) { + $page->addUpdate($layoutUpdate); + $page->addPageLayoutHandles(['layout_update' => sha1($layoutUpdate)], null, false); + } + } + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Category/ViewTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Category/ViewTest.php index d93520297e485..60c6f2f1bd821 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Category/ViewTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Category/ViewTest.php @@ -124,7 +124,7 @@ protected function setUp() ->disableOriginalConstructor()->getMock(); $this->pageConfig->expects($this->any())->method('addBodyClass')->will($this->returnSelf()); - $this->page = $this->getMockBuilder(\Magento\Framework\View\Page::class) + $this->page = $this->getMockBuilder(\Magento\Framework\View\Result\Page::class) ->setMethods(['getConfig', 'initLayout', 'addPageLayoutHandles', 'getLayout', 'addUpdate']) ->disableOriginalConstructor()->getMock(); $this->page->expects($this->any())->method('getConfig')->will($this->returnValue($this->pageConfig)); From 1a64bfe09b09366539ff6858097ad564b385d777 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 12 Apr 2019 16:09:13 -0500 Subject: [PATCH 265/585] Issue-230: Implement cache tag generation for GraphQL queries - Add general cache tag for cache type --- .../GraphQlCache/Model/CacheableQueryHandler.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php index 786c822d68226..bf57e8c9736ca 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -64,21 +64,16 @@ public function handleCacheFromResolverResponse(array $resolvedValue, Field $fie $cacheTags = []; if ($cacheTag && $this->request->isGet()) { + $cacheTags[] = $cacheTag; if (!empty($cacheIdentityResolverClass)) { $cacheIdentityResolver = $this->identityResolverPool->get($cacheIdentityResolverClass); $cacheTagIds = $cacheIdentityResolver->getIdentifiers($resolvedValue); if (!empty($cacheTagIds)) { - $cacheTags = array_map( - function ($id) use ($cacheTag) { - return $cacheTag . '_' . $id; - }, - $cacheTagIds - ); + foreach ($cacheTagIds as $cacheTagId) { + $cacheTags[] = $cacheTag . '_' . $cacheTagId; + } } - } else { - $cacheTags[] = $cacheTag; } - $this->cacheableQuery->addCacheTags($cacheTags); } $this->setCacheValidity($cacheable); From bf8e919b4bf203cc6caa59ceee668ff7eddc8a58 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 13 Apr 2019 09:01:11 +0200 Subject: [PATCH 266/585] Code style fix --- .../Model/ResourceModel/Product/Downloads/Collection.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php index a7932e8a11f81..aeb0448f8e05a 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php @@ -103,7 +103,8 @@ public function addFieldToFilter($field, $condition = null) * * @return \Magento\Framework\DB\Select */ - public function getSelectCountSql() { + public function getSelectCountSql() + { $countSelect = parent::getSelectCountSql(); $countSelect->reset(\Zend\Db\Sql\Select::GROUP); return $countSelect; From 6dcd0e93317f796ccc89effb85616791dd243c74 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 13 Apr 2019 13:45:36 +0200 Subject: [PATCH 267/585] Refactoring. Use action groups and config data --- ...ssertDashboardPageIsVisibleActionGroup.xml | 15 ++++++++++++ .../Test/Mftf/Data/BackendConfigData.xml | 24 +++++++++++++++++++ .../AdminUserLoginWithStoreCodeInUrlTest.xml | 8 +++---- ...refrontAssertStoreCodeInUrlActionGroup.xml | 13 ++++++++++ .../Test/StorefrontAddStoreCodeInUrlTest.xml | 13 ++++------ ...StorefrontClickOnHeaderLogoActionGroup.xml | 16 +++++++++++++ 6 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml create mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml create mode 100644 app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml new file mode 100644 index 0000000000000..df22bb27d6b88 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminAssertDashboardPageIsVisibleActionGroup"> + <seeInCurrentUrl url="{{AdminDashboardPage.url}}" stepKey="seeDashboardUrl"/> + <see userInput="Dashboard" selector="{{AdminHeaderSection.pageTitle}}" stepKey="seeDashboardTitle"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml b/app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml new file mode 100644 index 0000000000000..4333446925474 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="StorefrontDisableAddStoreCodeToUrls"> + <!-- Magento default value --> + <data key="path">web/url/use_store</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="StorefrontEnableAddStoreCodeToUrls"> + <data key="path">web/url/use_store</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> +</entities> diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml index a8f86f3309b5c..51ba1a142803d 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml @@ -17,13 +17,13 @@ <group value="mtf_migrated"/> </annotations> <before> - <magentoCLI command="config:set web/url/use_store 1" stepKey="addStoreCodeToUrl"/> + <magentoCLI command="config:set {{StorefrontEnableAddStoreCodeToUrls.path}} {{StorefrontEnableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlEnable"/> </before> <after> - <magentoCLI command="config:set web/url/use_store 0" stepKey="addStoreCodeToUrlDisable"/> + <magentoCLI command="config:set {{StorefrontDisableAddStoreCodeToUrls.path}} {{StorefrontDisableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlDisable"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <see userInput="Dashboard" selector="{{AdminHeaderSection.pageTitle}}" stepKey="seeDashboardTitle"/> + <actionGroup ref="AdminAssertDashboardPageIsVisibleActionGroup" stepKey="seeDashboardPage"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml new file mode 100644 index 0000000000000..974526afbf21c --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertStoreCodeInUrlActionGroup"> + <seeInCurrentUrl url="{{StorefrontHomePage.url}}{{_defaultStore.code}}" stepKey="seeStoreCodeInURL"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml index b04267ef83d60..7bee46da1a226 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml @@ -17,16 +17,13 @@ <group value="mtf_migrated"/> </annotations> <before> - <magentoCLI command="config:set web/url/use_store 1" stepKey="addStoreCodeToUrl"/> + <magentoCLI command="config:set {{StorefrontEnableAddStoreCodeToUrls.path}} {{StorefrontEnableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlEnable"/> </before> <after> - <magentoCLI command="config:set web/url/use_store 0" stepKey="addStoreCodeToUrlDisable"/> + <magentoCLI command="config:set {{StorefrontDisableAddStoreCodeToUrls.path}} {{StorefrontDisableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlDisable"/> </after> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="gotToHomePage"/> - <waitForPageLoad stepKey="waitForHomePageLoaded1"/> - <click selector="{{StorefrontHeaderSection.logoLink}}" stepKey="clickOnLogo"/> - <waitForPageLoad stepKey="waitForHomePageLoaded2"/> - <seeInCurrentUrl url="{{StorefrontHomePage.url}}{{_defaultStore.code}}" stepKey="seeStoreCodeInURL"/> + <actionGroup ref="StorefrontClickOnHeaderLogoActionGroup" stepKey="clickOnStorefrontHeaderLogo"/> + <actionGroup ref="StorefrontAssertStoreCodeInUrlActionGroup" stepKey="seeStoreCodeInUrl"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml b/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml new file mode 100644 index 0000000000000..6e45429b9e1e8 --- /dev/null +++ b/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontClickOnHeaderLogoActionGroup"> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="gotToHomePage"/> + <waitForPageLoad stepKey="waitForHomePageLoaded1"/> + <click selector="{{StorefrontHeaderSection.logoLink}}" stepKey="clickOnLogo"/> + <waitForPageLoad stepKey="waitForHomePageLoaded2"/> + </actionGroup> +</actionGroups> From ae7179f7bee1b99597aee46da79f581a8a45a018 Mon Sep 17 00:00:00 2001 From: Oleg Volkov <sirwerwolf@gmail.com> Date: Sat, 13 Apr 2019 15:34:17 +0300 Subject: [PATCH 268/585] #21747 Fix catalog_product_flat_data attribute value for store during indexer --- .../Model/Indexer/Product/Flat/TableBuilder.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php index a3d958ea537e1..0865c311e7094 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php @@ -306,10 +306,11 @@ protected function _fillTemporaryTable( foreach ($columnsList as $columnName => $attribute) { $countTableName = 't' . $iterationNum++; $joinCondition = sprintf( - 'e.%3$s = %1$s.%3$s AND %1$s.attribute_id = %2$d AND %1$s.store_id = 0', + 'e.%3$s = %1$s.%3$s AND %1$s.attribute_id = %2$d AND (%1$s.store_id = %4$d OR %1$s.store_id = 0)', $countTableName, $attribute->getId(), - $metadata->getLinkField() + $metadata->getLinkField(), + $storeId ); $select->joinLeft( @@ -323,9 +324,10 @@ protected function _fillTemporaryTable( $columnValueName = $attributeCode . $valueFieldSuffix; if (isset($flatColumns[$columnValueName])) { $valueJoinCondition = sprintf( - 'e.%1$s = %2$s.option_id AND %2$s.store_id = 0', + 'e.%1$s = %2$s.option_id AND (%2$s.store_id = %3$d OR %2$s.store_id = 0)', $attributeCode, - $countTableName + $countTableName, + $storeId ); $selectValue->joinLeft( [ From 6124c6087c9f2c0c0b4ed3b7be27286c79b12d19 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 13 Apr 2019 14:46:57 +0200 Subject: [PATCH 269/585] Refactoring. Use action groups and config data --- .../AdminForgotPasswordFormSection.xml | 4 +- ...AdminFillForgotPasswordFormActionGroup.xml | 17 +++++++ ...AdminOpenForgotPasswordPageActionGroup.xml | 16 +++++++ ...minSubmitForgotPasswordFormActionGroup.xml | 13 +++++ ...AssertAdminLoginPageMessageActionGroup.xml | 19 ++++++++ .../Test/AdminResetUserPasswordFailedTest.xml | 48 +++++++++++++++++++ .../Mftf/Test/ResetUserPasswordFailedTest.xml | 37 -------------- .../TestCase/ResetUserPasswordFailedTest.xml | 3 +- 8 files changed, 116 insertions(+), 41 deletions(-) create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillForgotPasswordFormActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenForgotPasswordPageActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminSubmitForgotPasswordFormActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml delete mode 100644 app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml index 5c33369b38767..efaca22123354 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminForgotPasswordFormSection"> - <element name="email" type="input" selector="#email"/> - <element name="retrievePasswordButton" type="button" selector=".action-retrieve" timeout="30"/> + <element name="email" type="input" selector="#login-form input[name='email']"/> + <element name="retrievePasswordButton" type="button" selector="#login-form button[type='submit']" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillForgotPasswordFormActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillForgotPasswordFormActionGroup.xml new file mode 100644 index 0000000000000..01be51e72ec6d --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillForgotPasswordFormActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminFillForgotPasswordFormActionGroup"> + <arguments> + <argument name="email" type="string"/> + </arguments> + + <fillField selector="{{AdminForgotPasswordFormSection.email}}" userInput="{{email}}" stepKey="fillAdminEmail"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenForgotPasswordPageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenForgotPasswordPageActionGroup.xml new file mode 100644 index 0000000000000..fa17c5a7f8b76 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenForgotPasswordPageActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenForgotPasswordPageActionGroup"> + <amOnPage url="{{AdminLoginPage.url}}" stepKey="amOnAdminLoginPage"/> + <waitForPageLoad stepKey="waitForAdminLoginPage"/> + <click stepKey="clickForgotPasswordLink" selector="{{AdminLoginFormSection.forgotPasswordLink}}"/> + <waitForPageLoad stepKey="waitForAdminForgotPasswordPage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminSubmitForgotPasswordFormActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminSubmitForgotPasswordFormActionGroup.xml new file mode 100644 index 0000000000000..198bc713093ea --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminSubmitForgotPasswordFormActionGroup.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSubmitForgotPasswordFormActionGroup"> + <click selector="{{AdminForgotPasswordFormSection.retrievePasswordButton}}" stepKey="clickOnRetrievePasswordButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml new file mode 100644 index 0000000000000..5535d2314a69f --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertAdminLoginPageMessageActionGroup"> + <arguments> + <argument name="messageType" type="string"/> + <argument name="message" type="string"/> + </arguments> + + <waitForElementVisible selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="waitForAdminLoginFormMessage" /> + <see userInput="{{message}}" selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="seeAdminLoginFormMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml new file mode 100644 index 0000000000000..0d66ed38d4310 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminResetUserPasswordFailedTest"> + <annotations> + <features value="User"/> + <title value="Admin user should not be able to trigger the password reset procedure twice"/> + <description value="Admin user should not be able to trigger the password reset procedure twice"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <magentoCLI command="config:set {{AdminCaptchaDisableConfigData.path}} {{AdminCaptchaDisableConfigData.value}} " stepKey="disableAdminCaptcha"/> + </before> + <after> + <magentoCLI command="config:set {{AdminCaptchaEnableConfigData.path}} {{AdminCaptchaEnableConfigData.value}} " stepKey="enableAdminCaptcha"/> + </after> + + <!-- First attempt to reset password --> + <actionGroup ref="AdminOpenForgotPasswordPageActionGroup" stepKey="openAdminForgotPasswordPage1"/> + <actionGroup ref="AdminFillForgotPasswordFormActionGroup" stepKey="fillAdminForgotPasswordForm1"> + <argument name="email" value="customer@example.com"/> + </actionGroup> + <actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordForm1"/> + <actionGroup ref="AssertAdminLoginPageMessageActionGroup" stepKey="seeSuccessMessage"> + <argument name="messageType" value="success"/> + <argument name="message" value="We'll email you a link to reset your password."/> + </actionGroup> + + <!-- Second attempt to reset password --> + <actionGroup ref="AdminOpenForgotPasswordPageActionGroup" stepKey="openAdminForgotPasswordPage2"/> + <actionGroup ref="AdminFillForgotPasswordFormActionGroup" stepKey="fillAdminForgotPasswordForm2"> + <argument name="email" value="customer@example.com"/> + </actionGroup> + <actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordForm2"/> + <actionGroup ref="AssertAdminLoginPageMessageActionGroup" stepKey="seeErrorMessage"> + <argument name="messageType" value="error"/> + <argument name="message" value="We received too many requests for password resets. Please wait and try again later or contact hello@example.com."/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml b/app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml deleted file mode 100644 index 3a614c91aeebc..0000000000000 --- a/app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="ResetUserPasswordFailedTest"> - <annotations> - <features value="User"/> - <title value="Admin user should not be able to trigger the password reset procedure twice"/> - <description value="Admin user should not be able to trigger the password reset procedure twice"/> - <group value="security"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <magentoCLI command="config:set admin/captcha/enable 0" stepKey="disableAdminCaptcha"/> - </before> - - <amOnPage url="{{AdminLoginPage.url}}" stepKey="amOnAdminLoginPage"/> - <waitForPageLoad stepKey="waitForAdminLoginPage1"/> - <click stepKey="clickForgotPasswordLink1" selector="{{AdminLoginFormSection.forgotPasswordLink}}"/> - <fillField selector="{{AdminForgotPasswordFormSection.email}}" userInput="some@example.com" stepKey="fillAdminEmail1"/> - <click selector="{{AdminForgotPasswordFormSection.retrievePasswordButton}}" stepKey="clickOnRetrievePasswordButton1"/> - <waitForElementVisible selector="{{AdminUserLoginMessagesSection.successMessage}}" stepKey="waitForSuccessMessage" /> - <see stepKey="seeSuccessMessage" selector="{{AdminUserLoginMessagesSection.successMessage}}" userInput="We'll email you a link to reset your password."/> - <click stepKey="clickForgotPasswordLink2" selector="{{AdminLoginFormSection.forgotPasswordLink}}"/> - <waitForPageLoad stepKey="waitForAdminForgotPasswordPage2"/> - <fillField selector="{{AdminForgotPasswordFormSection.email}}" userInput="some@example.com" stepKey="fillAdminEmail2"/> - <click selector="{{AdminForgotPasswordFormSection.retrievePasswordButton}}" stepKey="clickOnRetrievePasswordButton2"/> - <waitForElementVisible selector="{{AdminUserLoginMessagesSection.errorMessage}}" stepKey="waitForFailMessage" /> - <see stepKey="seeErrorMessage" selector="{{AdminUserLoginMessagesSection.errorMessage}}" userInput="We received too many requests for password resets. Please wait and try again later or contact hello@example.com."/> - </test> -</tests> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml index 229e980fed91f..f43469358aa9c 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml @@ -8,10 +8,9 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Security\Test\TestCase\ResetUserPasswordFailedTest" summary="Prevent Locked Admin User to Log In into the Backend"> <variation name="ResetUserPasswordTestVariation1"> - <data name="tag" xsi:type="string">severity:S1</data> + <data name="tag" xsi:type="string">severity:S1,mftf_migrated:yes</data> <data name="customAdmin/dataset" xsi:type="string">custom_admin_with_default_role</data> <data name="attempts" xsi:type="string">2</data> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserPasswordResetFailed" /> </variation> </testCase> From d52da79f976c3fa469c56c8c249d39f39452dfc6 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Sat, 13 Apr 2019 17:08:12 +0300 Subject: [PATCH 270/585] Vitalii Boiko: removed redundant subscriptions for catalog rules --- app/code/Magento/CatalogRule/etc/mview.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/code/Magento/CatalogRule/etc/mview.xml b/app/code/Magento/CatalogRule/etc/mview.xml index 35efe33461afc..657af387da226 100644 --- a/app/code/Magento/CatalogRule/etc/mview.xml +++ b/app/code/Magento/CatalogRule/etc/mview.xml @@ -16,11 +16,8 @@ <table name="catalog_product_entity" entity_column="entity_id" /> <table name="catalog_product_entity_datetime" entity_column="entity_id" /> <table name="catalog_product_entity_decimal" entity_column="entity_id" /> - <table name="catalog_product_entity_gallery" entity_column="entity_id" /> <table name="catalog_product_entity_int" entity_column="entity_id" /> - <table name="catalog_product_entity_text" entity_column="entity_id" /> <table name="catalog_product_entity_tier_price" entity_column="entity_id" /> - <table name="catalog_product_entity_varchar" entity_column="entity_id" /> <table name="catalog_category_product" entity_column="product_id" /> </subscriptions> </view> From bbca40240268c2d2f5a7f1c7196527d6b9151488 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Sat, 13 Apr 2019 17:38:24 +0300 Subject: [PATCH 271/585] Vitalii Boiko: revert varchar and text tables --- app/code/Magento/CatalogRule/etc/mview.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/CatalogRule/etc/mview.xml b/app/code/Magento/CatalogRule/etc/mview.xml index 657af387da226..9e5a1c866a842 100644 --- a/app/code/Magento/CatalogRule/etc/mview.xml +++ b/app/code/Magento/CatalogRule/etc/mview.xml @@ -17,7 +17,9 @@ <table name="catalog_product_entity_datetime" entity_column="entity_id" /> <table name="catalog_product_entity_decimal" entity_column="entity_id" /> <table name="catalog_product_entity_int" entity_column="entity_id" /> + <table name="catalog_product_entity_text" entity_column="entity_id" /> <table name="catalog_product_entity_tier_price" entity_column="entity_id" /> + <table name="catalog_product_entity_varchar" entity_column="entity_id" /> <table name="catalog_category_product" entity_column="product_id" /> </subscriptions> </view> From 3c3d7ffbd99b2bf445d95375363d724ec8f8ed3d Mon Sep 17 00:00:00 2001 From: eugene-shab <dev.eugene.shab@gmail.com> Date: Sat, 13 Apr 2019 17:41:57 +0300 Subject: [PATCH 272/585] - Remove cart_address_id - remove condition from SetShippingMethodsOnCart --- .../QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php | 9 ++------- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 1 - 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php index 730cf1b0ffee3..3516f1fbea1ab 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php @@ -50,11 +50,6 @@ public function execute(ContextInterface $context, CartInterface $cart, array $s } $shippingMethodInput = current($shippingMethodsInput); - if (!isset($shippingMethodInput['cart_address_id']) || empty($shippingMethodInput['cart_address_id'])) { - throw new GraphQlInputException(__('Required parameter "cart_address_id" is missing.')); - } - $cartAddressId = $shippingMethodInput['cart_address_id']; - if (!isset($shippingMethodInput['carrier_code']) || empty($shippingMethodInput['carrier_code'])) { throw new GraphQlInputException(__('Required parameter "carrier_code" is missing.')); } @@ -65,7 +60,7 @@ public function execute(ContextInterface $context, CartInterface $cart, array $s } $methodCode = $shippingMethodInput['method_code']; - $quoteAddress = $this->getQuoteAddress->execute($cart, $cartAddressId, $context->getUserId()); - $this->assignShippingMethodToCart->execute($cart, $quoteAddress, $carrierCode, $methodCode); +// $quoteAddress = $this->getQuoteAddress->execute($cart, $context->getUserId()); +// $this->assignShippingMethodToCart->execute($cart, $quoteAddress, $carrierCode, $methodCode); } } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 9ec3492f64531..2f5e5b54c2fa1 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -110,7 +110,6 @@ input SetShippingMethodsOnCartInput { } input ShippingMethodInput { - cart_address_id: Int! carrier_code: String! method_code: String! } From bed152b45be8c1c227434e66017f2f51a845770f Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Sat, 13 Apr 2019 16:20:14 +0300 Subject: [PATCH 273/585] magento/magento2#22317: CodeSniffer should not mark correctly aligned DocBlock elements as code style violation. --- .../Annotation/AnnotationFormatValidator.php | 40 +++++ .../MethodAnnotationStructureSniff.php | 1 + .../Annotation/MethodArgumentsSniff.php | 154 ++++++++++++++---- 3 files changed, 161 insertions(+), 34 deletions(-) diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php index 3f477f7ce5033..b102fa87b76a8 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php @@ -249,6 +249,46 @@ public function validateTagGroupingFormat(File $phpcsFile, int $commentStartPtr) } } + /** + * Validates tag aligning format + * + * @param File $phpcsFile + * @param int $commentStartPtr + */ + public function validateTagAligningFormat(File $phpcsFile, int $commentStartPtr) : void + { + $tokens = $phpcsFile->getTokens(); + $noAlignmentPositions = []; + $actualPositions = []; + $stackPtr = null; + foreach ($tokens[$commentStartPtr]['comment_tags'] as $position => $tag) { + $content = $tokens[$tag]['content']; + if (preg_match('/^@/', $content) && ($tokens[$tag]['line'] === $tokens[$tag + 2]['line'])) { + $noAlignmentPositions[] = $tokens[$tag + 1]['column'] + 1; + $actualPositions[] = $tokens[$tag + 2]['column']; + $stackPtr = $stackPtr ?? $tag; + } + + } + + if (!$this->allTagsAligned($actualPositions) + && !$this->noneTagsAligned($actualPositions, $noAlignmentPositions)) { + $phpcsFile->addFixableError( + 'Tags visual alignment must be consistent', + $stackPtr, + 'MethodArguments' + ); + } + } + + private function allTagsAligned(array $actualPositions) { + return count(array_unique($actualPositions)) === 1; + } + + private function noneTagsAligned(array $actualPositions, array $noAlignmentPositions) { + return $actualPositions === $noAlignmentPositions; + } + /** * Validates extra newline before short description * diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodAnnotationStructureSniff.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodAnnotationStructureSniff.php index 445671d245e03..f05ae64a170d7 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodAnnotationStructureSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodAnnotationStructureSniff.php @@ -75,6 +75,7 @@ public function process(File $phpcsFile, $stackPtr) $emptyTypeTokens ); $this->annotationFormatValidator->validateTagGroupingFormat($phpcsFile, $commentStartPtr); + $this->annotationFormatValidator->validateTagAligningFormat($phpcsFile, $commentStartPtr); } } } diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php index 879334d8c553b..5bd4667c4f4be 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php @@ -8,8 +8,8 @@ namespace Magento\Sniffs\Annotation; -use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; /** * Sniff to validate method arguments annotations @@ -42,7 +42,7 @@ class MethodArgumentsSniff implements Sniff /** * @inheritdoc */ - public function register() : array + public function register(): array { return [ T_FUNCTION @@ -55,7 +55,7 @@ public function register() : array * @param string $type * @return bool */ - private function isTokenBeforeClosingCommentTagValid(string $type) : bool + private function isTokenBeforeClosingCommentTagValid(string $type): bool { return in_array($type, $this->validTokensBeforeClosingCommentTag); } @@ -68,7 +68,7 @@ private function isTokenBeforeClosingCommentTagValid(string $type) : bool * @param int $stackPtr * @return bool */ - private function validateCommentBlockExists(File $phpcsFile, int $previousCommentClosePtr, int $stackPtr) : bool + private function validateCommentBlockExists(File $phpcsFile, int $previousCommentClosePtr, int $stackPtr): bool { $tokens = $phpcsFile->getTokens(); for ($tempPtr = $previousCommentClosePtr + 1; $tempPtr < $stackPtr; $tempPtr++) { @@ -85,7 +85,7 @@ private function validateCommentBlockExists(File $phpcsFile, int $previousCommen * @param string $type * @return bool */ - private function isInvalidType(string $type) : bool + private function isInvalidType(string $type): bool { return in_array(strtolower($type), $this->invalidTypes); } @@ -98,7 +98,7 @@ private function isInvalidType(string $type) : bool * @param int $closedParenthesisPtr * @return array */ - private function getMethodArguments(File $phpcsFile, int $openParenthesisPtr, int $closedParenthesisPtr) : array + private function getMethodArguments(File $phpcsFile, int $openParenthesisPtr, int $closedParenthesisPtr): array { $tokens = $phpcsFile->getTokens(); $methodArguments = []; @@ -121,7 +121,7 @@ private function getMethodArguments(File $phpcsFile, int $openParenthesisPtr, in * @param array $paramDefinitions * @return array */ - private function getMethodParameters(array $paramDefinitions) : array + private function getMethodParameters(array $paramDefinitions): array { $paramName = []; for ($i = 0; $i < count($paramDefinitions); $i++) { @@ -143,7 +143,7 @@ private function validateInheritdocAnnotationWithoutBracesExists( File $phpcsFile, int $previousCommentOpenPtr, int $previousCommentClosePtr - ) : bool { + ): bool { return $this->validateInheritdocAnnotationExists( $phpcsFile, $previousCommentOpenPtr, @@ -163,7 +163,7 @@ private function validateInheritdocAnnotationWithBracesExists( File $phpcsFile, int $previousCommentOpenPtr, int $previousCommentClosePtr - ) : bool { + ): bool { return $this->validateInheritdocAnnotationExists( $phpcsFile, $previousCommentOpenPtr, @@ -186,7 +186,7 @@ private function validateInheritdocAnnotationExists( int $previousCommentOpenPtr, int $previousCommentClosePtr, string $inheritdocAnnotation - ) : bool { + ): bool { $tokens = $phpcsFile->getTokens(); for ($ptr = $previousCommentOpenPtr; $ptr < $previousCommentClosePtr; $ptr++) { if (strtolower($tokens[$ptr]['content']) === $inheritdocAnnotation) { @@ -213,7 +213,7 @@ private function validateParameterAnnotationForArgumentExists( int $previousCommentOpenPtr, int $previousCommentClosePtr, int $stackPtr - ) : void { + ): void { if ($argumentsCount > 0 && $parametersCount === 0) { $inheritdocAnnotationWithoutBracesExists = $this->validateInheritdocAnnotationWithoutBracesExists( $phpcsFile, @@ -256,7 +256,7 @@ private function validateCommentBlockDoesnotHaveExtraParameterAnnotation( int $argumentsCount, int $parametersCount, int $stackPtr - ) : void { + ): void { if ($argumentsCount < $parametersCount && $argumentsCount > 0) { $phpcsFile->addFixableError( 'Extra @param found in method annotation', @@ -287,10 +287,10 @@ private function validateArgumentNameInParameterAnnotationExists( File $phpcsFile, array $methodArguments, array $paramDefinitions - ) : void { + ): void { $parameterNames = $this->getMethodParameters($paramDefinitions); if (!in_array($methodArguments[$ptr], $parameterNames)) { - $error = $methodArguments[$ptr]. ' parameter is missing in method annotation'; + $error = $methodArguments[$ptr] . ' parameter is missing in method annotation'; $phpcsFile->addFixableError($error, $stackPtr, 'MethodArguments'); } } @@ -310,7 +310,7 @@ private function validateParameterPresentInMethodSignature( array $methodArguments, File $phpcsFile, array $paramPointers - ) : void { + ): void { if (!in_array($paramDefinitionsArguments, $methodArguments)) { $phpcsFile->addFixableError( $paramDefinitionsArguments . ' parameter is missing in method arguments signature', @@ -333,7 +333,7 @@ private function validateParameterOrderIsCorrect( array $methodArguments, File $phpcsFile, array $paramPointers - ) : void { + ): void { $parameterNames = $this->getMethodParameters($paramDefinitions); $paramDefinitionsCount = count($paramDefinitions); for ($ptr = 0; $ptr < $paramDefinitionsCount; $ptr++) { @@ -342,7 +342,7 @@ private function validateParameterOrderIsCorrect( ) { if ($methodArguments[$ptr] != $parameterNames[$ptr]) { $phpcsFile->addFixableError( - $methodArguments[$ptr].' parameter is not in order', + $methodArguments[$ptr] . ' parameter is not in order', $paramPointers[$ptr], 'MethodArguments' ); @@ -366,12 +366,12 @@ private function validateDuplicateAnnotationDoesnotExists( array $paramPointers, File $phpcsFile, array $methodArguments - ) : void { + ): void { $argumentsCount = count($methodArguments); $parametersCount = count($paramPointers); if ($argumentsCount <= $parametersCount && $argumentsCount > 0) { $duplicateParameters = []; - for ($i = 0; $i < sizeof($paramDefinitions); $i++) { + for ($i = 0; $i < count($paramDefinitions); $i++) { if (isset($paramDefinitions[$i]['paramName'])) { $parameterContent = $paramDefinitions[$i]['paramName']; for ($j = $i + 1; $j < count($paramDefinitions); $j++) { @@ -408,7 +408,7 @@ private function validateParameterAnnotationFormatIsCorrect( array $methodArguments, array $paramDefinitions, array $paramPointers - ) : void { + ): void { switch (count($paramDefinitions)) { case 0: $phpcsFile->addFixableError( @@ -429,7 +429,7 @@ private function validateParameterAnnotationFormatIsCorrect( case 2: if ($this->isInvalidType($paramDefinitions[0])) { $phpcsFile->addFixableError( - $paramDefinitions[0].' is not a valid PHP type', + $paramDefinitions[0] . ' is not a valid PHP type', $paramPointers[$ptr], 'MethodArguments' ); @@ -451,7 +451,7 @@ private function validateParameterAnnotationFormatIsCorrect( ); if ($this->isInvalidType($paramDefinitions[0])) { $phpcsFile->addFixableError( - $paramDefinitions[0].' is not a valid PHP type', + $paramDefinitions[0] . ' is not a valid PHP type', $paramPointers[$ptr], 'MethodArguments' ); @@ -480,7 +480,7 @@ private function validateMethodParameterAnnotations( array $methodArguments, int $previousCommentOpenPtr, int $previousCommentClosePtr - ) : void { + ): void { $argumentCount = count($methodArguments); $paramCount = count($paramPointers); $this->validateParameterAnnotationForArgumentExists( @@ -510,8 +510,14 @@ private function validateMethodParameterAnnotations( $phpcsFile, $paramPointers ); + $this->validateFormattingConsistency( + $paramDefinitions, + $methodArguments, + $phpcsFile, + $paramPointers + ); + $tokens = $phpcsFile->getTokens(); for ($ptr = 0; $ptr < count($methodArguments); $ptr++) { - $tokens = $phpcsFile->getTokens(); if (isset($paramPointers[$ptr])) { $this->validateArgumentNameInParameterAnnotationExists( $stackPtr, @@ -520,7 +526,7 @@ private function validateMethodParameterAnnotations( $methodArguments, $paramDefinitions ); - $paramContent = $tokens[$paramPointers[$ptr]+2]['content']; + $paramContent = $tokens[$paramPointers[$ptr] + 2]['content']; $paramContentExplode = explode(' ', $paramContent); $this->validateParameterAnnotationFormatIsCorrect( $ptr, @@ -540,36 +546,40 @@ public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $numTokens = count($tokens); - $previousCommentOpenPtr = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, $stackPtr-1, 0); - $previousCommentClosePtr = $phpcsFile->findPrevious(T_DOC_COMMENT_CLOSE_TAG, $stackPtr-1, 0); + $previousCommentOpenPtr = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, $stackPtr - 1, 0); + $previousCommentClosePtr = $phpcsFile->findPrevious(T_DOC_COMMENT_CLOSE_TAG, $stackPtr - 1, 0); if (!$this->validateCommentBlockExists($phpcsFile, $previousCommentClosePtr, $stackPtr)) { $phpcsFile->addError('Comment block is missing', $stackPtr, 'MethodArguments'); return; } - $openParenthesisPtr = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr+1, $numTokens); - $closedParenthesisPtr = $phpcsFile->findNext(T_CLOSE_PARENTHESIS, $stackPtr+1, $numTokens); + $openParenthesisPtr = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr + 1, $numTokens); + $closedParenthesisPtr = $phpcsFile->findNext(T_CLOSE_PARENTHESIS, $stackPtr + 1, $numTokens); $methodArguments = $this->getMethodArguments($phpcsFile, $openParenthesisPtr, $closedParenthesisPtr); $paramPointers = $paramDefinitions = []; for ($tempPtr = $previousCommentOpenPtr; $tempPtr < $previousCommentClosePtr; $tempPtr++) { if (strtolower($tokens[$tempPtr]['content']) === '@param') { $paramPointers[] = $tempPtr; - $paramAnnotationParts = explode(' ', $tokens[$tempPtr+2]['content']); + $content = preg_replace('/\s+/', ' ', $tokens[$tempPtr + 2]['content'], 2); + $paramAnnotationParts = explode(' ', $content, 3); if (count($paramAnnotationParts) === 1) { if ((preg_match('/^\$.*/', $paramAnnotationParts[0]))) { $paramDefinitions[] = [ 'type' => null, - 'paramName' => rtrim(ltrim($tokens[$tempPtr+2]['content'], '&'), ',') + 'paramName' => rtrim(ltrim($tokens[$tempPtr + 2]['content'], '&'), ','), + 'comment' => null ]; } else { $paramDefinitions[] = [ - 'type' => $tokens[$tempPtr+2]['content'], - 'paramName' => null + 'type' => $tokens[$tempPtr + 2]['content'], + 'paramName' => null, + 'comment' => null ]; } } else { $paramDefinitions[] = [ 'type' => $paramAnnotationParts[0], - 'paramName' => rtrim(ltrim($paramAnnotationParts[1], '&'), ',') + 'paramName' => rtrim(ltrim($paramAnnotationParts[1], '&'), ','), + 'comment' => $paramAnnotationParts[2] ?? null, ]; } } @@ -584,4 +594,80 @@ public function process(File $phpcsFile, $stackPtr) $previousCommentClosePtr ); } + + /** + * Validates function params format consistency. + * + * @param array $paramDefinitions + * @param array $methodArguments + * @param File $phpcsFile + * @param array $paramPointers + * + * @see https://devdocs.magento.com/guides/v2.3/coding-standards/docblock-standard-general.html#format-consistency + */ + private function validateFormattingConsistency( + array $paramDefinitions, + array $methodArguments, + File $phpcsFile, + array $paramPointers + ): void { + $argumentPositions = []; + $commentPositions = []; + $tokens = $phpcsFile->getTokens(); + for ($ptr = 0; $ptr < count($methodArguments); $ptr++) { + if (isset($paramPointers[$ptr])) { + $paramContent = $tokens[$paramPointers[$ptr] + 2]['content']; + $paramDefinition = $paramDefinitions[$ptr]; + $argumentPositions[] = strpos($paramContent, $paramDefinition['paramName']); + $commentPositions[] = $paramDefinition['comment'] + ? strpos($paramContent, $paramDefinition['comment']) : null; + } + } + if (!$this->allParamsAligned($argumentPositions, $commentPositions) + && !$this->noneParamsAligned($argumentPositions, $commentPositions, $paramDefinitions)) { + $phpcsFile->addFixableError( + 'Visual alignment must be consistent', + $paramPointers[0], + 'MethodArguments' + ); + } + } + + /** + * Check all params are aligned. + * + * @param array $argumentPositions + * @param array $commentPositions + * @return bool + */ + private function allParamsAligned(array $argumentPositions, array $commentPositions): bool + { + return count(array_unique($argumentPositions)) === 1 + && count(array_unique(array_filter($commentPositions))) <= 1; + } + + /** + * Check none of params are aligned. + * + * @param array $argumentPositions + * @param array $commentPositions + * @param array $paramDefinitions + * @return bool + */ + private function noneParamsAligned(array $argumentPositions, array $commentPositions, array $paramDefinitions): bool + { + $flag = true; + foreach ($argumentPositions as $index => $argumentPosition) { + $commentPosition = $commentPositions[$index]; + $type = $paramDefinitions[$index]['type']; + $paramName = $paramDefinitions[$index]['paramName']; + if (($argumentPosition !== strlen($type) + 1) || + (isset($commentPosition) && ($commentPosition !== $argumentPosition + strlen($paramName) + 1))) { + $flag = false; + break; + } + } + + return $flag; + } } From 6ab1392502017a73629e2b5d2abc7cbd8aebb43f Mon Sep 17 00:00:00 2001 From: eugene-shab <dev.eugene.shab@gmail.com> Date: Sat, 13 Apr 2019 18:41:08 +0300 Subject: [PATCH 274/585] debug --- .../QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php index 3516f1fbea1ab..fccda9e28c11e 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php @@ -62,5 +62,7 @@ public function execute(ContextInterface $context, CartInterface $cart, array $s // $quoteAddress = $this->getQuoteAddress->execute($cart, $context->getUserId()); // $this->assignShippingMethodToCart->execute($cart, $quoteAddress, $carrierCode, $methodCode); + $quoteAddress = $cart->getShippingAddress(); + $this->assignShippingMethodToCart->execute($cart, $quoteAddress, $carrierCode, $methodCode); } } From 12c848c79237bb4e6237e4ac4dd5d989ec9bbc53 Mon Sep 17 00:00:00 2001 From: Pieter Hoste <hoste.pieter@gmail.com> Date: Sun, 14 Apr 2019 19:45:14 +0200 Subject: [PATCH 275/585] Fixes a less compilation error: '.no-link a' isn't defined when .email-non-inline() isn't active, so when using '.no-link a', it should be wrapped inside .email-non-inline(). --- .../Magento/blank/Magento_Sales/web/css/source/_email.less | 6 ++++-- .../Magento/luma/Magento_Sales/web/css/source/_email.less | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_email.less b/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_email.less index 215d7d8b322b4..b189d4e08ba17 100644 --- a/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_email.less +++ b/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_email.less @@ -68,8 +68,10 @@ } // Remove address and phone number link color on iOS -.address-details a { - &:extend(.no-link a); +.email-non-inline() { + .address-details a { + &:extend(.no-link a); + } } .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) { diff --git a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less index 3f19d1020bab9..31c128e07e3a6 100644 --- a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less +++ b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less @@ -76,8 +76,10 @@ } // Remove address and phone number link color on iOS -.address-details a { - &:extend(.no-link a); +.email-non-inline() { + .address-details a { + &:extend(.no-link a); + } } .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) { From 87ae19b8b9505de542ef87a8ff960d26d8efdaf1 Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Mon, 15 Apr 2019 08:56:45 +0300 Subject: [PATCH 276/585] MC-11944: Create Order from Admin within Offline Payment Methods --- .../Sales/Test/TestCase/CreateOrderBackendPartOneTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendPartOneTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendPartOneTest.xml index 3e7b8fad1f04d..880c66483d5f2 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendPartOneTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendPartOneTest.xml @@ -8,7 +8,6 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\CreateOrderBackendPartOneTest" summary="Create Order from Admin within Offline Payment Methods" ticketId="MAGETWO-28696"> <variation name="CreateOrderBackendTestVariation1" ticketId="MAGETWO-17063"> - <data name="issue" xsi:type="string">https://github.com/magento-engcom/msi/issues/1624</data> <data name="description" xsi:type="string">Create order with simple product for registered US customer using Fixed shipping method and Cash on Delivery payment method</data> <data name="products/0" xsi:type="string">catalogProductSimple::with_one_custom_option</data> <data name="customer/dataset" xsi:type="string">default</data> @@ -70,7 +69,6 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderByDateInOrdersGrid" /> </variation> <variation name="CreateOrderBackendTestVariation4"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="description" xsi:type="string">Create order with virtual product for registered UK customer using Bank Transfer payment method</data> <data name="products/0" xsi:type="string">catalogProductVirtual::default</data> <data name="customer/dataset" xsi:type="string">default</data> From 9d592efec6cb0045b22a591009895f20c2e165a9 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Mon, 15 Apr 2019 10:09:48 +0300 Subject: [PATCH 277/585] MC-5264: Create root category with all fields --- .../Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml index ea6808ee2a7f5..663439fd62a1d 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml @@ -17,7 +17,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" /> </variation> <variation name="CreateCategoryEntityTestVariation2_RootCategory_AllFields"> - <data name="issue" xsi:type="string">MAGETWO-60635: [CE][Categories] Design update dates are incorrect after save</data> <data name="description" xsi:type="string">Create root category with all fields</data> <data name="addCategory" xsi:type="string">addRootCategory</data> <data name="category/data/is_active" xsi:type="string">Yes</data> @@ -58,7 +57,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage" /> </variation> <variation name="CreateCategoryEntityTestVariation4_Subcategory_AllFields"> - <data name="issue" xsi:type="string">MAGETWO-60635: [CE][Categories] Design update dates are incorrect after save</data> <data name="description" xsi:type="string">Create not anchor subcategory specifying all fields</data> <data name="addCategory" xsi:type="string">addSubcategory</data> <data name="category/data/parent_id/dataset" xsi:type="string">default_category</data> From 6cbf55d40ebb33e5fb73c68ba62df83f2af98aa2 Mon Sep 17 00:00:00 2001 From: niravkrish <nirav.patel@krishtechnolabs.com> Date: Mon, 15 Apr 2019 14:20:41 +0530 Subject: [PATCH 278/585] Fixed - search icon click not working issue in admin ui grid sticky header --- .../Ui/view/base/web/js/grid/search/search.js | 23 +++++++++++++++---- .../web/templates/grid/search/search.html | 3 ++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/search/search.js b/app/code/Magento/Ui/view/base/web/js/grid/search/search.js index 999e3262dbbdd..ce53b23b79e11 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/search/search.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/search/search.js @@ -11,8 +11,9 @@ define([ 'uiLayout', 'mage/translate', 'mageUtils', - 'uiElement' -], function (_, layout, $t, utils, Element) { + 'uiElement', + 'jquery' +], function (_, layout, $t, utils, Element, $) { 'use strict'; return Element.extend({ @@ -29,11 +30,13 @@ define([ tracks: { value: true, previews: true, - inputValue: true + inputValue: true, + focused: true }, imports: { inputValue: 'value', - updatePreview: 'value' + updatePreview: 'value', + focused: false }, exports: { value: '${ $.provider }:params.search' @@ -88,6 +91,18 @@ define([ return this; }, + /** + * Click To ScrollTop. + */ + scrollTo: function ($data) { + $('html, body').animate({ + scrollTop: 0 + }, 'slow', function () { + $data.focused = false; + $data.focused = true; + }); + }, + /** * Resets input value to the last applied state. * diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html b/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html index 13b82a93eca25..fcad729a95fbb 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html @@ -5,7 +5,7 @@ */ --> <div class="data-grid-search-control-wrap"> - <label class="data-grid-search-label" attr="title: $t('Search'), for: index"> + <label class="data-grid-search-label" attr="title: $t('Search'), for: index" data-bind="click: scrollTo"> <span translate="'Search'"/> </label> <input class="admin__control-text data-grid-search-control" type="text" @@ -16,6 +16,7 @@ placeholder: $t(placeholder) }, textInput: inputValue, + hasFocus: focused, keyboard: { 13: apply.bind($data, false), 27: cancel From ef5d0013c487b992eb93b41b0e8f2abee8917e81 Mon Sep 17 00:00:00 2001 From: Sudhanshu Bajaj <sudhanshu.b@lsretail.com> Date: Mon, 15 Apr 2019 16:52:23 +0800 Subject: [PATCH 279/585] Spelling Mistake in Setup > Patch --- .../Magento/Framework/Setup/Patch/DependentPatchInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php b/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php index abda94a0e6f8e..21fafd273f9ed 100644 --- a/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php +++ b/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php @@ -6,7 +6,7 @@ namespace Magento\Framework\Setup\Patch; /** - * Each patch can have dependecies, that should be applied before such patch + * Each patch can have dependencies, that should be applied before such patch * * / Patch2 --- Patch3 * / From d334e2e6808dd5d6e616dc34894710b02861a6f5 Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Mon, 15 Apr 2019 14:44:38 +0530 Subject: [PATCH 280/585] Fixed Value of created_at and updated_at columns --- app/code/Magento/Ui/etc/db_schema.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/etc/db_schema.xml b/app/code/Magento/Ui/etc/db_schema.xml index e2a04b0cdc72d..13a384024f18a 100644 --- a/app/code/Magento/Ui/etc/db_schema.xml +++ b/app/code/Magento/Ui/etc/db_schema.xml @@ -18,8 +18,8 @@ comment="Mark current bookmark per user and identifier"/> <column xsi:type="varchar" name="title" nullable="true" length="255" comment="Bookmark title"/> <column xsi:type="longtext" name="config" nullable="true" comment="Bookmark config"/> - <column xsi:type="datetime" name="created_at" on_update="false" nullable="false" comment="Bookmark created at"/> - <column xsi:type="datetime" name="updated_at" on_update="false" nullable="false" comment="Bookmark updated at"/> + <column xsi:type="datetime" name="created_at" on_update="false" nullable="false" default="CURRENT_TIMESTAMP" comment="Bookmark created at"/> + <column xsi:type="datetime" name="updated_at" on_update="true" nullable="false" default="CURRENT_TIMESTAMP" comment="Bookmark updated at"/> <constraint xsi:type="primary" referenceId="PRIMARY"> <column name="bookmark_id"/> </constraint> From a45fb74cac0e9efa8a5ce9c304a8b55f1ce6e393 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Mon, 15 Apr 2019 16:40:34 +0300 Subject: [PATCH 281/585] magento/magento2#21797: Static test fix. --- .../testsuite/Magento/Webapi/JoinDirectivesTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php index d00cfb831953e..8beb14e81be71 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php @@ -11,6 +11,9 @@ use Magento\Framework\Api\SortOrder; use Magento\Framework\Api\SortOrderBuilder; +/** + * Test join directives. + */ class JoinDirectivesTest extends \Magento\TestFramework\TestCase\WebapiAbstract { /** @@ -43,7 +46,8 @@ protected function setUp() } /** - * Rollback rules + * Rollback rules. + * * @magentoApiDataFixture Magento/SalesRule/_files/rules_rollback.php * @magentoApiDataFixture Magento/Sales/_files/quote.php */ From e1f8e52bdbad27695bb91fbd0e86eee9f2b88afc Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 15 Apr 2019 09:29:17 -0500 Subject: [PATCH 282/585] Issue-230: adding varnish - mark cacheable false the queries we can't cache yet --- app/code/Magento/CustomerGraphQl/etc/schema.graphqls | 2 +- app/code/Magento/DirectoryGraphQl/etc/schema.graphqls | 6 +++--- app/code/Magento/DownloadableGraphQl/etc/schema.graphqls | 2 +- app/code/Magento/EavGraphQl/etc/schema.graphqls | 2 +- app/code/Magento/SalesGraphQl/etc/schema.graphqls | 2 +- app/code/Magento/StoreGraphQl/etc/schema.graphqls | 2 +- app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls | 2 +- app/code/Magento/VaultGraphQl/etc/schema.graphqls | 2 +- app/code/Magento/WishlistGraphQl/etc/schema.graphqls | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/CustomerGraphQl/etc/schema.graphqls b/app/code/Magento/CustomerGraphQl/etc/schema.graphqls index 4e4fd1d0fa8ad..1238184075057 100644 --- a/app/code/Magento/CustomerGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CustomerGraphQl/etc/schema.graphqls @@ -2,7 +2,7 @@ # See COPYING.txt for license details. type Query { - customer: Customer @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\Customer") @doc(description: "The customer query returns information about a customer account") + customer: Customer @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\Customer") @doc(description: "The customer query returns information about a customer account") @cache(cacheable: false) isEmailAvailable ( email: String! @doc(description: "The new customer email") ): IsEmailAvailableOutput @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\IsEmailAvailable") diff --git a/app/code/Magento/DirectoryGraphQl/etc/schema.graphqls b/app/code/Magento/DirectoryGraphQl/etc/schema.graphqls index 8da1920f9a444..6daf13f567d4b 100644 --- a/app/code/Magento/DirectoryGraphQl/etc/schema.graphqls +++ b/app/code/Magento/DirectoryGraphQl/etc/schema.graphqls @@ -2,9 +2,9 @@ # See COPYING.txt for license details. type Query { - currency: Currency @resolver(class: "Magento\\DirectoryGraphQl\\Model\\Resolver\\Currency") @doc(description: "The currency query returns information about store currency.") - countries: [Country] @resolver(class: "Magento\\DirectoryGraphQl\\Model\\Resolver\\Countries") @doc(description: "The countries query provides information for all countries.") - country (id: String): Country @resolver(class: "Magento\\DirectoryGraphQl\\Model\\Resolver\\Country") @doc(description: "The countries query provides information for a single country.") + currency: Currency @resolver(class: "Magento\\DirectoryGraphQl\\Model\\Resolver\\Currency") @doc(description: "The currency query returns information about store currency.") @cache(cacheable: false) + countries: [Country] @resolver(class: "Magento\\DirectoryGraphQl\\Model\\Resolver\\Countries") @doc(description: "The countries query provides information for all countries.") @cache(cacheable: false) + country (id: String): Country @resolver(class: "Magento\\DirectoryGraphQl\\Model\\Resolver\\Country") @doc(description: "The countries query provides information for a single country.") @cache(cacheable: false) } type Currency { diff --git a/app/code/Magento/DownloadableGraphQl/etc/schema.graphqls b/app/code/Magento/DownloadableGraphQl/etc/schema.graphqls index e2cacdf7608d6..788a5fc601ee1 100644 --- a/app/code/Magento/DownloadableGraphQl/etc/schema.graphqls +++ b/app/code/Magento/DownloadableGraphQl/etc/schema.graphqls @@ -2,7 +2,7 @@ # See COPYING.txt for license details. type Query { - customerDownloadableProducts: CustomerDownloadableProducts @resolver(class: "Magento\\DownloadableGraphQl\\Model\\Resolver\\CustomerDownloadableProducts") @doc(description: "The query returns the contents of a customer's downloadable products") + customerDownloadableProducts: CustomerDownloadableProducts @resolver(class: "Magento\\DownloadableGraphQl\\Model\\Resolver\\CustomerDownloadableProducts") @doc(description: "The query returns the contents of a customer's downloadable products") @cache(cacheable: false) } type CustomerDownloadableProducts { diff --git a/app/code/Magento/EavGraphQl/etc/schema.graphqls b/app/code/Magento/EavGraphQl/etc/schema.graphqls index adada3030f501..0299067bd0523 100644 --- a/app/code/Magento/EavGraphQl/etc/schema.graphqls +++ b/app/code/Magento/EavGraphQl/etc/schema.graphqls @@ -2,7 +2,7 @@ # See COPYING.txt for license details. type Query { - customAttributeMetadata(attributes: [AttributeInput!]!): CustomAttributeMetadata @resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata") @doc(description: "The customAttributeMetadata query returns the attribute type, given an attribute code and entity type") + customAttributeMetadata(attributes: [AttributeInput!]!): CustomAttributeMetadata @resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata") @doc(description: "The customAttributeMetadata query returns the attribute type, given an attribute code and entity type") @cache(cacheable: false) } type CustomAttributeMetadata @doc(description: "CustomAttributeMetadata defines an array of attribute_codes and entity_types") { diff --git a/app/code/Magento/SalesGraphQl/etc/schema.graphqls b/app/code/Magento/SalesGraphQl/etc/schema.graphqls index 44f106532858f..06146f805c644 100644 --- a/app/code/Magento/SalesGraphQl/etc/schema.graphqls +++ b/app/code/Magento/SalesGraphQl/etc/schema.graphqls @@ -2,7 +2,7 @@ # See COPYING.txt for license details. type Query { - customerOrders: CustomerOrders @resolver(class: "Magento\\SalesGraphQl\\Model\\Resolver\\Orders") @doc(description: "List of customer orders") + customerOrders: CustomerOrders @resolver(class: "Magento\\SalesGraphQl\\Model\\Resolver\\Orders") @doc(description: "List of customer orders") @cache(cacheable: false) } type CustomerOrder @doc(description: "Order mapping fields") { diff --git a/app/code/Magento/StoreGraphQl/etc/schema.graphqls b/app/code/Magento/StoreGraphQl/etc/schema.graphqls index d9f7eaaaa294c..376635e5c8f75 100644 --- a/app/code/Magento/StoreGraphQl/etc/schema.graphqls +++ b/app/code/Magento/StoreGraphQl/etc/schema.graphqls @@ -1,7 +1,7 @@ # Copyright © Magento, Inc. All rights reserved. # See COPYING.txt for license details. type Query { - storeConfig : StoreConfig @resolver(class: "Magento\\StoreGraphQl\\Model\\Resolver\\StoreConfigResolver") @doc(description: "The store config query") + storeConfig : StoreConfig @resolver(class: "Magento\\StoreGraphQl\\Model\\Resolver\\StoreConfigResolver") @doc(description: "The store config query") @cache(cacheable: false) } type Website @doc(description: "The type contains information about a website") { diff --git a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls index 5aea482a0fe02..e9033880704ca 100644 --- a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls @@ -2,7 +2,7 @@ # See COPYING.txt for license details. type Query { - urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\EntityUrl") @doc(description: "The urlResolver query returns the relative URL for a specified product, category or CMS page") + urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\EntityUrl") @doc(description: "The urlResolver query returns the relative URL for a specified product, category or CMS page") @cache(cacheable: false) } type EntityUrl @doc(description: "EntityUrl is an output object containing the `id`, `relative_url`, and `type` attributes") { diff --git a/app/code/Magento/VaultGraphQl/etc/schema.graphqls b/app/code/Magento/VaultGraphQl/etc/schema.graphqls index cdaeced027f6f..64484fe9e814f 100644 --- a/app/code/Magento/VaultGraphQl/etc/schema.graphqls +++ b/app/code/Magento/VaultGraphQl/etc/schema.graphqls @@ -11,7 +11,7 @@ type DeletePaymentTokenOutput { } type Query { - customerPaymentTokens: CustomerPaymentTokens @doc(description: "Return a list of customer payment tokens") @resolver(class: "\\Magento\\VaultGraphQl\\Model\\Resolver\\PaymentTokens") + customerPaymentTokens: CustomerPaymentTokens @doc(description: "Return a list of customer payment tokens") @resolver(class: "\\Magento\\VaultGraphQl\\Model\\Resolver\\PaymentTokens") @cache(cacheable: false) } type CustomerPaymentTokens @resolver(class: "\\Magento\\VaultGraphQl\\Model\\Resolver\\PaymentTokens") { diff --git a/app/code/Magento/WishlistGraphQl/etc/schema.graphqls b/app/code/Magento/WishlistGraphQl/etc/schema.graphqls index f5b5034fb734f..2aa5f03a787d0 100644 --- a/app/code/Magento/WishlistGraphQl/etc/schema.graphqls +++ b/app/code/Magento/WishlistGraphQl/etc/schema.graphqls @@ -2,7 +2,7 @@ # See COPYING.txt for license details. type Query { - wishlist: WishlistOutput @resolver(class: "\\Magento\\WishlistGraphQl\\Model\\Resolver\\WishlistResolver") @doc(description: "The wishlist query returns the contents of a customer's wish list") + wishlist: WishlistOutput @resolver(class: "\\Magento\\WishlistGraphQl\\Model\\Resolver\\WishlistResolver") @doc(description: "The wishlist query returns the contents of a customer's wish list") @cache(cacheable: false) } type WishlistOutput { From 700a1535cb6f58224e8e302ad1b4556d8a118e01 Mon Sep 17 00:00:00 2001 From: Wirson <m.wirson@gmail.com> Date: Mon, 15 Apr 2019 16:48:20 +0200 Subject: [PATCH 283/585] #22249 configurable product images wrong sorting fix --- .../Magento/Swatches/view/frontend/web/js/swatch-renderer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js index 2571c0385dab7..cc77c07ad39e6 100644 --- a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js @@ -697,7 +697,7 @@ define([ */ _sortImages: function (images) { return _.sortBy(images, function (image) { - return image.position; + return parseInt(image.position, 10); }); }, From a04f5c3caa2e6c6bbee58d76f309b06c132cadac Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 15 Apr 2019 10:58:51 -0500 Subject: [PATCH 284/585] Issue-230: adding varnish - fix static test --- .../Model/Resolver/DataProvider/Page.php | 2 ++ .../HttpClient/CurlClientWithCookies.php | 4 ++- .../Catalog/ProductInMultipleStoresTest.php | 4 +++ .../GraphQl/PageCache/CacheTagTest.php | 34 ++++++++----------- .../Controller/GraphQlCacheControllerTest.php | 16 ++++----- 5 files changed, 32 insertions(+), 28 deletions(-) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index 001209ba79677..8e1e770b01e9d 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -40,6 +40,8 @@ public function __construct( } /** + * Get the page data + * * @param int $pageId * @return array * @throws NoSuchEntityException diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClientWithCookies.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClientWithCookies.php index 626e319e86687..1dd9d17f904b4 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClientWithCookies.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClientWithCookies.php @@ -36,6 +36,8 @@ public function __construct( } /** + * Compose the resource url + * * @param string $resourcePath Resource URL like /V1/Resource1/123 * @return string resource URL * @throws \Exception @@ -80,7 +82,7 @@ public function get($resourcePath, $data = [], $headers = []) * ], * ] * - * @param $headerBlock + * @param string $headerBlock * @return array */ private function cookieParse($headerBlock) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php index 9eb9bc76047a8..a63d417eaef13 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php @@ -10,10 +10,14 @@ use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Class ProductInMultipleStoresTest + */ class ProductInMultipleStoresTest extends GraphQlAbstract { /** + * Test a product from a specific and a default store * * @magentoApiDataFixture Magento/Store/_files/second_store.php * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index a01f31abb65d7..59cc83d6a5d6d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -7,10 +7,8 @@ namespace Magento\GraphQl\PageCache; - use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Product; -use Magento\Deploy\Model\Mode; use Magento\TestFramework\ObjectManager; use Magento\TestFramework\App\State; use Magento\TestFramework\Helper\Bootstrap; @@ -48,34 +46,33 @@ public function testCacheTagsAndCacheDebugHeaderFromResponse() /** cache-debug should be a MISS when product is queried for first time */ - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); - preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); - $this->assertEquals('MISS', rtrim($matchesMiss[1],"\r")); + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); + preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); + $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); /** cache-debug should be a HIT for the second round */ $responseHitHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHitHeaders, $matchesHit); - $this->assertEquals('HIT', rtrim($matchesHit[1],"\r")); + $this->assertEquals('HIT', rtrim($matchesHit[1], "\r")); /** @var ProductRepositoryInterface $productRepository */ $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); /** @var Product $product */ - $product =$productRepository->get($productSku,false,null, true); + $product =$productRepository->get($productSku, false, null, true); /** update the price attribute for the product in test */ $product->setPrice(15); $product->save(); /** Cache invalidation happens and cache-debug header value is a MISS after product update */ $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); - $this->assertEquals('MISS', rtrim($matchesMiss[1],"\r")); + $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); /** checks if cache tags for products are correctly displayed in the response header */ preg_match('/X-Magento-Tags: (.*?)\n/', $responseMissHeaders, $headerCacheTags); - $actualCacheTags = explode(',', rtrim($headerCacheTags[1],"\r")); + $actualCacheTags = explode(',', rtrim($headerCacheTags[1], "\r")); $expectedCacheTags=['cat_p','cat_p_' . $product->getId(),'FPC']; - foreach(array_keys($actualCacheTags) as $key){ - $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key] - ); + foreach (array_keys($actualCacheTags) as $key) { + $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); } } @@ -120,25 +117,24 @@ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() /** @var ProductRepositoryInterface $productRepository */ $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); /** @var Product $product */ - $product =$productRepository->get($productSku,false,null, true); + $product =$productRepository->get($productSku, false, null, true); /** cache-debug header value should be a MISS when category is loaded first time */ preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); - $this->assertEquals('MISS', rtrim($matchesMiss[1],"\r")); + $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); /** checks to see if the X-Magento-Tags for category is displayed correctly */ preg_match('/X-Magento-Tags: (.*?)\n/', $responseMissHeaders, $headerCacheTags); - $actualCacheTags = explode(',', rtrim($headerCacheTags[1],"\r")); + $actualCacheTags = explode(',', rtrim($headerCacheTags[1], "\r")); $expectedCacheTags=['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $product->getId(),'FPC']; - foreach(array_keys($actualCacheTags) as $key){ - $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key] - ); + foreach (array_keys($actualCacheTags) as $key) { + $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); } /** cache-debug header value should be MISS after updating child-product and reloading the category */ $product->setPrice(15); $product->save(); $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, $variables, '', []); preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); - $this->assertEquals('MISS', rtrim($matchesMiss[1],"\r")); + $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); } } diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php index 98965ff41e737..5ddbc4b029a42 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php @@ -46,6 +46,9 @@ class GraphQlCacheControllerTest extends \Magento\TestFramework\Indexer\TestCase private $response; + /** + * @inheritdoc + */ public static function setUpBeforeClass() { $db = Bootstrap::getInstance()->getBootstrap() @@ -59,6 +62,9 @@ public static function setUpBeforeClass() parent::setUpBeforeClass(); } + /** + * @inheritdoc + */ protected function setUp(): void { $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); @@ -67,7 +73,6 @@ protected function setUp(): void $this->metadataPool = $this->objectManager->get(MetadataPool::class); $this->request = $this->objectManager->get(Http::class); $this->response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - } /** @@ -103,20 +108,15 @@ public function testDispatchWithGetForCacheDebugHeadersAndCacheTags(): void $this->request->setQueryValue('query', $query); /** @var \Magento\Framework\Controller\Result\Json $result */ $result = $this->graphql->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); /** @var $registry \Magento\Framework\Registry */ $registry = $this->objectManager->get(\Magento\Framework\Registry::class); $registry->register('use_page_cache_plugin', true, true); - $result->renderResult($this->response); // + $result->renderResult($this->response); $this->assertEquals('MISS', $this->response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $this->response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; foreach (array_keys($actualCacheTags) as $key) { - $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key] - ); + $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); } } } - - From fecce53f4cc2ba2edb6f227c271be49ce179e753 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Mon, 15 Apr 2019 11:24:04 -0500 Subject: [PATCH 285/585] Fix for issue #21299. Change HEAD action mapping to GET action interface and add HEAD request handling --- .../Framework/App/Test/Unit/HttpTest.php | 117 ++++++++++++------ .../Test/Unit/Transfer/Adapter/HttpTest.php | 28 +++-- .../Framework/File/Transfer/Adapter/Http.php | 2 +- 3 files changed, 94 insertions(+), 53 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php index 48a1242a90d4f..23e58bd3df1e8 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php @@ -135,12 +135,17 @@ private function setUpLaunch() { $frontName = 'frontName'; $areaCode = 'areaCode'; - $this->requestMock->expects($this->once())->method('getFrontName')->will($this->returnValue($frontName)); + $this->requestMock->expects($this->once()) + ->method('getFrontName') + ->willReturn($frontName); $this->areaListMock->expects($this->once()) ->method('getCodeByFrontName') - ->with($frontName)->will($this->returnValue($areaCode)); + ->with($frontName) + ->willReturn($areaCode); $this->configLoaderMock->expects($this->once()) - ->method('load')->with($areaCode)->will($this->returnValue([])); + ->method('load') + ->with($areaCode) + ->willReturn([]); $this->objectManagerMock->expects($this->once())->method('configure')->with([]); $this->objectManagerMock->expects($this->once()) ->method('get') @@ -149,13 +154,15 @@ private function setUpLaunch() $this->frontControllerMock->expects($this->once()) ->method('dispatch') ->with($this->requestMock) - ->will($this->returnValue($this->responseMock)); + ->willReturn($this->responseMock); } public function testLaunchSuccess() { $this->setUpLaunch(); - $this->requestMock->expects($this->once())->method('isHead')->will($this->returnValue(false)); + $this->requestMock->expects($this->once()) + ->method('isHead') + ->willReturn(false); $this->eventManagerMock->expects($this->once()) ->method('dispatch') ->with( @@ -172,14 +179,16 @@ public function testLaunchSuccess() public function testLaunchException() { $this->setUpLaunch(); - $this->frontControllerMock->expects($this->once())->method('dispatch')->with($this->requestMock)->will( - $this->returnCallback( - function () { - // phpcs:ignore Magento2.Exceptions.DirectThrow - throw new \Exception('Message'); - } - ) - ); + $this->frontControllerMock->expects($this->once()) + ->method('dispatch') + ->with($this->requestMock)->will( + $this->returnCallback( + function () { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception('Message'); + } + ) + ); $this->http->launch(); } @@ -192,20 +201,22 @@ function () { public function testLaunchHeadRequest($body, $expectedLength) { $this->setUpLaunch(); - $this->requestMock->expects($this->once())->method('isHead')->will($this->returnValue(true)); + $this->requestMock->expects($this->once()) + ->method('isHead') + ->willReturn(true); $this->responseMock->expects($this->once()) ->method('getHttpResponseCode') - ->will($this->returnValue(200)); + ->willReturn(200); $this->responseMock->expects($this->once()) ->method('getContent') - ->will($this->returnValue($body)); + ->willReturn($body); $this->responseMock->expects($this->once()) ->method('clearBody') - ->will($this->returnValue($this->responseMock)); + ->willReturn($this->responseMock); $this->responseMock->expects($this->once()) ->method('setHeader') ->with('Content-Length', $expectedLength) - ->will($this->returnValue($this->responseMock)); + ->willReturn($this->responseMock); $this->eventManagerMock->expects($this->once()) ->method('dispatch') ->with( @@ -219,7 +230,7 @@ public function testLaunchHeadRequest($body, $expectedLength) * Different test content for responseMock with their expected lengths in bytes. * @return array */ - public function dataProviderForTestLaunchHeadRequest() + public function dataProviderForTestLaunchHeadRequest(): array { return [ [ @@ -244,20 +255,29 @@ public function dataProviderForTestLaunchHeadRequest() public function testHandleDeveloperModeNotInstalled() { $dir = $this->getMockForAbstractClass(\Magento\Framework\Filesystem\Directory\ReadInterface::class); - $dir->expects($this->once())->method('getAbsolutePath')->willReturn(__DIR__); + $dir->expects($this->once()) + ->method('getAbsolutePath') + ->willReturn(__DIR__); $this->filesystemMock->expects($this->once()) ->method('getDirectoryRead') ->with(DirectoryList::ROOT) ->willReturn($dir); - $this->responseMock->expects($this->once())->method('setRedirect')->with('/_files/'); - $this->responseMock->expects($this->once())->method('sendHeaders'); + $this->responseMock->expects($this->once()) + ->method('setRedirect') + ->with('/_files/'); + $this->responseMock->expects($this->once()) + ->method('sendHeaders'); $bootstrap = $this->getBootstrapNotInstalled(); - $bootstrap->expects($this->once())->method('getParams')->willReturn([ - 'SCRIPT_NAME' => '/index.php', - 'DOCUMENT_ROOT' => __DIR__, - 'SCRIPT_FILENAME' => __DIR__ . '/index.php', - SetupInfo::PARAM_NOT_INSTALLED_URL_PATH => '_files', - ]); + $bootstrap->expects($this->once()) + ->method('getParams') + ->willReturn( + [ + 'SCRIPT_NAME' => '/index.php', + 'DOCUMENT_ROOT' => __DIR__, + 'SCRIPT_FILENAME' => __DIR__ . '/index.php', + SetupInfo::PARAM_NOT_INSTALLED_URL_PATH => '_files', + ] + ); $this->assertTrue($this->http->catchException($bootstrap, new \Exception('Test Message'))); } @@ -266,24 +286,37 @@ public function testHandleDeveloperMode() $this->filesystemMock->expects($this->once()) ->method('getDirectoryRead') ->will($this->throwException(new \Exception('strange error'))); - $this->responseMock->expects($this->once())->method('setHttpResponseCode')->with(500); - $this->responseMock->expects($this->once())->method('setHeader')->with('Content-Type', 'text/plain'); + $this->responseMock->expects($this->once()) + ->method('setHttpResponseCode') + ->with(500); + $this->responseMock->expects($this->once()) + ->method('setHeader') + ->with('Content-Type', 'text/plain'); $constraint = new \PHPUnit\Framework\Constraint\StringStartsWith('1 exception(s):'); - $this->responseMock->expects($this->once())->method('setBody')->with($constraint); - $this->responseMock->expects($this->once())->method('sendResponse'); + $this->responseMock->expects($this->once()) + ->method('setBody') + ->with($constraint); + $this->responseMock->expects($this->once()) + ->method('sendResponse'); $bootstrap = $this->getBootstrapNotInstalled(); - $bootstrap->expects($this->once())->method('getParams')->willReturn( - ['DOCUMENT_ROOT' => 'something', 'SCRIPT_FILENAME' => 'something/else'] - ); + $bootstrap->expects($this->once()) + ->method('getParams') + ->willReturn( + ['DOCUMENT_ROOT' => 'something', 'SCRIPT_FILENAME' => 'something/else'] + ); $this->assertTrue($this->http->catchException($bootstrap, new \Exception('Test'))); } public function testCatchExceptionSessionException() { - $this->responseMock->expects($this->once())->method('setRedirect'); - $this->responseMock->expects($this->once())->method('sendHeaders'); + $this->responseMock->expects($this->once()) + ->method('setRedirect'); + $this->responseMock->expects($this->once()) + ->method('sendHeaders'); $bootstrap = $this->createMock(\Magento\Framework\App\Bootstrap::class); - $bootstrap->expects($this->once())->method('isDeveloperMode')->willReturn(false); + $bootstrap->expects($this->once()) + ->method('isDeveloperMode') + ->willReturn(false); $this->assertTrue($this->http->catchException( $bootstrap, new \Magento\Framework\Exception\SessionException(new \Magento\Framework\Phrase('Test')) @@ -298,8 +331,12 @@ public function testCatchExceptionSessionException() private function getBootstrapNotInstalled() { $bootstrap = $this->createMock(\Magento\Framework\App\Bootstrap::class); - $bootstrap->expects($this->once())->method('isDeveloperMode')->willReturn(true); - $bootstrap->expects($this->once())->method('getErrorCode')->willReturn(Bootstrap::ERR_IS_INSTALLED); + $bootstrap->expects($this->once()) + ->method('isDeveloperMode') + ->willReturn(true); + $bootstrap->expects($this->once()) + ->method('getErrorCode') + ->willReturn(Bootstrap::ERR_IS_INSTALLED); return $bootstrap; } } diff --git a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php index 92db004ae8e8e..8147ed4eb0005 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php @@ -6,7 +6,11 @@ namespace Magento\Framework\File\Test\Unit\Transfer\Adapter; -use \Magento\Framework\File\Transfer\Adapter\Http; +use Magento\Framework\File\Transfer\Adapter\Http; +use Magento\Framework\File\Mime; +use Magento\Framework\HTTP\PhpEnvironment\Response; +use Magento\Framework\App\Request\Http as RequestHttp; +use PHPUnit\Framework\MockObject\MockObject; /** * Tests http transfer adapter. @@ -14,22 +18,22 @@ class HttpTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + * @var RequestHttp|MockObject */ private $request; /** - * @var \Magento\Framework\HTTP\PhpEnvironment\Response|\PHPUnit_Framework_MockObject_MockObject + * @var Response|MockObject */ private $response; /** - * @var Http|\PHPUnit_Framework_MockObject_MockObject + * @var Http|MockObject */ private $object; /** - * @var \Magento\Framework\File\Mime|\PHPUnit_Framework_MockObject_MockObject + * @var Mime|MockObject */ private $mime; @@ -39,12 +43,12 @@ class HttpTest extends \PHPUnit\Framework\TestCase protected function setUp() { $this->response = $this->createPartialMock( - \Magento\Framework\HTTP\PhpEnvironment\Response::class, + Response::class, ['setHeader', 'sendHeaders', 'setHeaders'] ); - $this->mime = $this->createMock(\Magento\Framework\File\Mime::class); + $this->mime = $this->createMock(Mime::class); $this->request = $this->createPartialMock( - \Magento\Framework\App\Request\Http::class, + RequestHttp::class, ['isHead'] ); $this->object = new Http($this->response, $this->mime, $this->request); @@ -98,10 +102,10 @@ public function testSendWithOptions(): void $this->mime->expects($this->once()) ->method('getMimeType') ->with($file) - ->will($this->returnValue($contentType)); + ->willReturn($contentType); $this->request->expects($this->once()) ->method('isHead') - ->will($this->returnValue(false)); + ->willReturn(false); $this->expectOutputString(file_get_contents($file)); $this->object->send(['filepath' => $file, 'headers' => $headers]); @@ -145,10 +149,10 @@ public function testSendHeadRequest(): void $this->mime->expects($this->once()) ->method('getMimeType') ->with($file) - ->will($this->returnValue($contentType)); + ->willReturn($contentType); $this->request->expects($this->once()) ->method('isHead') - ->will($this->returnValue(true)); + ->willReturn(true); $this->object->send($file); $this->assertEquals(false, $this->hasOutput()); diff --git a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php index 7cafb826f766d..8c09fbdc45124 100644 --- a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php +++ b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php @@ -106,7 +106,7 @@ private function getFilePath($options): string * @param array $options * @param string $filepath */ - protected function prepareResponse($options, string $filepath): void + private function prepareResponse($options, string $filepath): void { $mimeType = $this->mime->getMimeType($filepath); if (is_array($options) && isset($options['headers']) && $options['headers'] instanceof \Zend\Http\Headers) { From 4cc11f56910cc005e426d5a32c4efc4df44f4423 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 15 Apr 2019 11:31:27 -0500 Subject: [PATCH 286/585] Issue-230: Implement cache tag generation for GraphQL queries - Add unit test for CacheableQueryHandler --- .../Unit/Model/CacheableQueryHandlerTest.php | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php diff --git a/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php b/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php new file mode 100644 index 0000000000000..c595881472e58 --- /dev/null +++ b/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Test\Unit\Model; + +use Magento\Framework\App\Request\Http; +use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Query\IdentityResolverInterface; +use Magento\GraphQlCache\Model\CacheableQueryHandler; +use Magento\GraphQlCache\Model\IdentityResolverPool; +use Magento\GraphQlCache\Model\CacheableQuery; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Test CacheableQueryHandler + */ +class CacheableQueryHandlerTest extends TestCase +{ + + private $cacheableQueryHandler; + + private $cacheableQueryMock; + + private $requestMock; + + private $identityResolverPoolMock; + + protected function setup(): void + { + $objectManager = new ObjectManager($this); + $this->cacheableQueryMock = $this->createMock(CacheableQuery::class); + $this->requestMock = $this->createMock(Http::class); + $this->identityResolverPoolMock = $this->createMock(IdentityResolverPool::class); + $this->cacheableQueryHandler = $objectManager->getObject( + CacheableQueryHandler::class, + [ + 'cacheableQuery' => $this->cacheableQueryMock, + 'request' => $this->requestMock, + 'identityResolverPool' => $this->identityResolverPoolMock + ] + ); + } + + /** + * @param array $resolvedData + * @param array $resolvedIdentities + * @dataProvider resolvedDataProvider + */ + public function testhandleCacheFromResolverResponse( + array $resolvedData, + array $resolvedIdentities, + array $expectedCacheTags + ): void { + $cacheData = [ + 'cacheIdentityResolver' => IdentityResolverInterface::class, + 'cacheTag' => 'cat_p' + ]; + $fieldMock = $this->createMock(Field::class); + $mockIdentityResolver = $this->getMockBuilder($cacheData['cacheIdentityResolver']) + ->setMethods(['getIdentifiers']) + ->getMockForAbstractClass(); + + $this->requestMock->expects($this->once())->method('isGet')->willReturn(true); + $this->identityResolverPoolMock->expects($this->once())->method('get')->willReturn($mockIdentityResolver); + $fieldMock->expects($this->once())->method('getCache')->willReturn($cacheData); + $mockIdentityResolver->expects($this->once()) + ->method('getIdentifiers') + ->with($resolvedData) + ->willReturn($resolvedIdentities); + $this->cacheableQueryMock->expects($this->once())->method('addCacheTags')->with($expectedCacheTags); + $this->cacheableQueryMock->expects($this->once())->method('isCacheable')->willReturn(true); + $this->cacheableQueryMock->expects($this->once())->method('setCacheValidity')->with(true); + + $this->cacheableQueryHandler->handleCacheFromResolverResponse($resolvedData, $fieldMock); + } + + /** + * @return array + */ + public function resolvedDataProvider(): array + { + return [ + [ + "resolvedData" => [ + "id" => 10, + "name" => "TesName", + "sku" => "TestSku" + ], + "resolvedIdentities" => [10], + "expectedCacheTags" => ["cat_p", "cat_p_10"] + ] + ]; + } +} From eaea57d3cde774f8249ee2e121472dd65840c8fb Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Mon, 15 Apr 2019 11:52:53 -0500 Subject: [PATCH 287/585] GraphQL-594: Test coverage for tag cache generation for cateogry - integration test coverage for category --- .../Controller/GraphQlCacheControllerTest.php | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php index 5ddbc4b029a42..400dea5dd12dd 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php @@ -72,7 +72,7 @@ protected function setUp(): void $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); $this->metadataPool = $this->objectManager->get(MetadataPool::class); $this->request = $this->objectManager->get(Http::class); - $this->response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + // $this->response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); } /** @@ -108,10 +108,12 @@ public function testDispatchWithGetForCacheDebugHeadersAndCacheTags(): void $this->request->setQueryValue('query', $query); /** @var \Magento\Framework\Controller\Result\Json $result */ $result = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); /** @var $registry \Magento\Framework\Registry */ $registry = $this->objectManager->get(\Magento\Framework\Registry::class); $registry->register('use_page_cache_plugin', true, true); - $result->renderResult($this->response); + $result->renderResult($response); $this->assertEquals('MISS', $this->response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $this->response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; @@ -119,4 +121,46 @@ public function testDispatchWithGetForCacheDebugHeadersAndCacheTags(): void $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); } } + + /** + * Test cache tags and debug header for category and querying only for category + * + * @magentoCache all enabled + * @magentoDataFixture Magento/Catalog/_files/category_product.php + * + */ + public function testDispatchForCacheDebugHeadersAndCacheTagsForCategory(): void + { + $categoryId ='333'; + $query + = <<<QUERY + { + category(id: $categoryId) { + id + name + url_key + description + product_count + } + } +QUERY; + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'FPC']; + foreach (array_keys($actualCacheTags) as $key) { + $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key] + ); + } + } } From 14de1708037321ec9481465dfe1ac6ffaf2fb4ee Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Mon, 15 Apr 2019 12:46:21 -0500 Subject: [PATCH 288/585] MAGETWO-99091: Name of categories in the Category tree on Product Edit page is not displayed according to the selected store view scope - Added strict types declaration - Added scalar type hints for new methods --- .../DataProvider/Product/Form/Modifier/Categories.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php index 8dc4b8100345e..db80d110e123a 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Ui\DataProvider\Product\Form\Modifier; use Magento\Catalog\Model\Locator\LocatorInterface; @@ -313,7 +315,7 @@ protected function customizeCategoriesField(array $meta) */ protected function getCategoriesTree($filter = null) { - $storeId = $this->locator->getStore()->getId(); + $storeId = (int) $this->locator->getStore()->getId(); $cachedCategoriesTree = $this->getCacheManager() ->load($this->getCategoriesTreeCacheId($storeId, (string) $filter)); @@ -345,7 +347,7 @@ protected function getCategoriesTree($filter = null) * @param string $filter * @return string */ - private function getCategoriesTreeCacheId($storeId, $filter = '') + private function getCategoriesTreeCacheId(int $storeId, string $filter = '') : string { return self::CATEGORY_TREE_ID . '_' . (string) $storeId @@ -360,7 +362,7 @@ private function getCategoriesTreeCacheId($storeId, $filter = '') * @return array * @throws LocalizedException */ - private function retrieveShownCategoriesIds($storeId, $filter = '') + private function retrieveShownCategoriesIds(int $storeId, string $filter = '') : array { /* @var $matchingNamesCollection \Magento\Catalog\Model\ResourceModel\Category\Collection */ $matchingNamesCollection = $this->categoryCollectionFactory->create(); @@ -396,7 +398,7 @@ private function retrieveShownCategoriesIds($storeId, $filter = '') * @return array * @throws LocalizedException */ - private function retrieveCategoriesTree($storeId, array $shownCategoriesIds = []) + private function retrieveCategoriesTree(int $storeId, array $shownCategoriesIds) : array { /* @var $collection \Magento\Catalog\Model\ResourceModel\Category\Collection */ $collection = $this->categoryCollectionFactory->create(); From 679d8a542dedf330ee899332fd46a7d701c44071 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Mon, 15 Apr 2019 15:47:19 -0500 Subject: [PATCH 289/585] MC-15785: Overall storefront improvements --- .../templates/product/list/items.phtml | 2 +- .../view/frontend/web/js/related-products.js | 2 +- .../CheckoutShippingGuestInfoSection.xml | 2 +- .../Mftf/Section/CheckoutShippingSection.xml | 2 +- .../templates/cart/item/default.phtml | 26 +++++------ .../frontend/web/template/authentication.html | 10 ++--- .../web/template/form/element/email.html | 4 +- .../web/template/summary/cart-items.html | 2 +- .../view/frontend/templates/subscribe.phtml | 20 ++++++--- .../view/frontend/templates/form.mini.phtml | 43 +++++++++++-------- .../Search/view/frontend/web/js/form-mini.js | 1 - .../frontend/templates/html/header/logo.phtml | 6 ++- .../form/element/helper/tooltip.html | 16 ++++--- .../css/source/module/checkout/_tooltip.less | 4 ++ .../layout/default_head_blocks.xml | 2 +- 15 files changed, 85 insertions(+), 57 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml index f434402346087..ecc9700802d27 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml @@ -169,7 +169,7 @@ switch ($type = $block->getType()) { <?php if ($type == 'related' && $canItemsAddToCart): ?> <div class="block-actions"> <?= /* @escapeNotVerified */ __('Check items to add to the cart or') ?> - <button type="button" class="action select" role="select-all"><span><?= /* @escapeNotVerified */ __('select all') ?></span></button> + <button type="button" class="action select" role="button"><span><?= /* @escapeNotVerified */ __('select all') ?></span></button> </div> <?php endif; ?> <div class="products wrapper grid products-grid products-<?= /* @escapeNotVerified */ $type ?>"> diff --git a/app/code/Magento/Catalog/view/frontend/web/js/related-products.js b/app/code/Magento/Catalog/view/frontend/web/js/related-products.js index 0c37f9ff4f007..66df48c28bfab 100644 --- a/app/code/Magento/Catalog/view/frontend/web/js/related-products.js +++ b/app/code/Magento/Catalog/view/frontend/web/js/related-products.js @@ -17,7 +17,7 @@ define([ relatedProductsField: '#related-products-field', // Hidden input field that stores related products. selectAllMessage: $.mage.__('select all'), unselectAllMessage: $.mage.__('unselect all'), - selectAllLink: '[role="select-all"]', + selectAllLink: '[role="button"]', elementsSelector: '.item.product' }, diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml index 6838824400b96..d446990b12660 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="CheckoutShippingGuestInfoSection"> - <element name="email" type="input" selector="#customer-email"/> + <element name="email" type="input" selector="#checkout-customer-email"/> <element name="firstName" type="input" selector="input[name=firstname]"/> <element name="lastName" type="input" selector="input[name=lastname]"/> <element name="street" type="input" selector="input[name='street[0]']"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml index d825e10395145..9676f16f3a5c6 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml @@ -15,7 +15,7 @@ <element name="editAddressButton" type="button" selector=".action-edit-address" timeout="30"/> <element name="addressDropdown" type="select" selector="[name=billing_address_id]"/> <element name="newAddressButton" type="button" selector=".action-show-popup" timeout="30"/> - <element name="email" type="input" selector="#customer-email"/> + <element name="email" type="input" selector="#checkout-customer-email"/> <element name="firstName" type="input" selector="input[name=firstname]"/> <element name="lastName" type="input" selector="input[name=lastname]"/> <element name="company" type="input" selector="input[name=company]"/> diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml index 454031279d882..d15794fb761bb 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml @@ -84,20 +84,20 @@ $canApplyMsrp = $helper->isShowBeforeOrderConfirm($product) && $helper->isMinima <?php endif; ?> <td class="col qty" data-th="<?= $block->escapeHtml(__('Qty')) ?>"> <div class="field qty"> - <label class="label" for="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty"> - <span><?= /* @escapeNotVerified */ __('Qty') ?></span> - </label> <div class="control qty"> - <input id="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty" - name="cart[<?= /* @escapeNotVerified */ $_item->getId() ?>][qty]" - data-cart-item-id="<?= $block->escapeHtml($_item->getSku()) ?>" - value="<?= /* @escapeNotVerified */ $block->getQty() ?>" - type="number" - size="4" - title="<?= $block->escapeHtml(__('Qty')) ?>" - class="input-text qty" - data-validate="{required:true,'validate-greater-than-zero':true}" - data-role="cart-item-qty"/> + <label for="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty"> + <span class="label"><?= /* @escapeNotVerified */ __('Qty') ?></span> + <input id="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty" + name="cart[<?= /* @escapeNotVerified */ $_item->getId() ?>][qty]" + data-cart-item-id="<?= $block->escapeHtml($_item->getSku()) ?>" + value="<?= /* @escapeNotVerified */ $block->getQty() ?>" + type="number" + size="4" + title="<?= $block->escapeHtml(__('Qty')) ?>" + class="input-text qty" + data-validate="{required:true,'validate-greater-than-zero':true}" + data-role="cart-item-qty"/> + </label> </div> </div> </td> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html index 406a7d899b67a..5b8dde81dd93e 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html @@ -31,15 +31,15 @@ <div class="block block-customer-login" data-bind="attr: {'data-label': $t('or')}"> <div class="block-title"> - <strong id="block-customer-login-heading" - role="heading" - aria-level="2" - data-bind="i18n: 'Sign In'"></strong> + <strong id="block-customer-login-heading-checkout" + role="heading" + aria-level="2" + data-bind="i18n: 'Sign In'"></strong> </div> <!-- ko foreach: getRegion('messages') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> - <div class="block-content" aria-labelledby="block-customer-login-heading"> + <div class="block-content" aria-labelledby="block-customer-login-heading-checkout"> <form data-role="login" data-bind="submit:login" method="post"> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html b/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html index 8d6142e07fcf0..6a784fa7a04c4 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html @@ -14,7 +14,7 @@ method="post"> <fieldset id="customer-email-fieldset" class="fieldset" data-bind="blockLoader: isLoading"> <div class="field required"> - <label class="label" for="customer-email"> + <label class="label" for="checkout-customer-email"> <span data-bind="i18n: 'Email Address'"></span> </label> <div class="control _with-tooltip"> @@ -26,7 +26,7 @@ mageInit: {'mage/trim-input':{}}" name="username" data-validate="{required:true, 'validate-email':true}" - id="customer-email" /> + id="checkout-customer-email" /> <!-- ko template: 'ui/form/element/helper/tooltip' --><!-- /ko --> <span class="note" data-bind="fadeVisible: isPasswordVisible() == false"><!-- ko i18n: 'You can create an account after checkout.'--><!-- /ko --></span> </div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html index 34ec91aa43c72..fc74a4691a2e7 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html @@ -6,7 +6,7 @@ --> <div class="block items-in-cart" data-bind="mageInit: {'collapsible':{'openedState': 'active', 'active': isItemsBlockExpanded()}}"> <div class="title" data-role="title"> - <strong role="heading"> + <strong role="heading" aria-level="1"> <translate args="maxCartItemsToDisplay" if="maxCartItemsToDisplay < getCartLineItemsCount()"/> <translate args="'of'" if="maxCartItemsToDisplay < getCartLineItemsCount()"/> <span data-bind="text: getCartLineItemsCount()"></span> diff --git a/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml b/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml index c1a526ee95148..554437095f36c 100644 --- a/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml +++ b/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml @@ -19,16 +19,24 @@ data-mage-init='{"validation": {"errorClass": "mage-error"}}' id="newsletter-validate-detail"> <div class="field newsletter"> - <label class="label" for="newsletter"><span><?= $block->escapeHtml(__('Sign Up for Our Newsletter:')) ?></span></label> <div class="control"> - <input name="email" type="email" id="newsletter" - placeholder="<?= $block->escapeHtml(__('Enter your email address')) ?>" - data-mage-init='{"mage/trim-input":{}}' - data-validate="{required:true, 'validate-email':true}"/> + <label for="newsletter"> + <span class="label"> + <?= $block->escapeHtml(__('Sign Up for Our Newsletter:')) ?> + </span> + <input name="email" type="email" id="newsletter" + placeholder="<?= $block->escapeHtml(__('Enter your email address')) ?>" + data-mage-init='{"mage/trim-input":{}}' + data-validate="{required:true, 'validate-email':true}" + /> + </label> </div> </div> <div class="actions"> - <button class="action subscribe primary" title="<?= $block->escapeHtmlAttr(__('Subscribe')) ?>" type="submit"> + <button class="action subscribe primary sr-only" + title="<?= $block->escapeHtmlAttr(__('Subscribe')) ?>" + type="submit" + aria-label="Subscribe"> <span><?= $block->escapeHtml(__('Subscribe')) ?></span> </button> </div> diff --git a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml index 2ea87be13d5e3..a98a70a90cede 100644 --- a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml +++ b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml @@ -16,34 +16,41 @@ $helper = $this->helper(\Magento\Search\Helper\Data::class); <div class="block block-content"> <form class="form minisearch" id="search_mini_form" action="<?= /* @escapeNotVerified */ $helper->getResultUrl() ?>" method="get"> <div class="field search"> - <label class="label" for="search" data-role="minisearch-label"> - <span><?= /* @escapeNotVerified */ __('Search') ?></span> - </label> <div class="control"> - <input id="search" - data-mage-init='{"quickSearch":{ + <label for="search" data-role="minisearch-label"> + <span class="label"> + <?= /* @escapeNotVerified */ __('Search') ?> + </span> + <input + aria-expanded="false" + id="search" + data-mage-init='{"quickSearch":{ "formSelector":"#search_mini_form", "url":"<?= /* @escapeNotVerified */ $helper->getSuggestUrl()?>", "destinationSelector":"#search_autocomplete"} - }' - type="text" - name="<?= /* @escapeNotVerified */ $helper->getQueryParamName() ?>" - value="<?= /* @escapeNotVerified */ $helper->getEscapedQueryText() ?>" - placeholder="<?= /* @escapeNotVerified */ __('Search entire store here...') ?>" - class="input-text" - maxlength="<?= /* @escapeNotVerified */ $helper->getMaxQueryLength() ?>" - role="combobox" - aria-haspopup="false" - aria-autocomplete="both" - autocomplete="off"/> + }' + type="text" + name="<?= /* @escapeNotVerified */ $helper->getQueryParamName() ?>" + value="<?= /* @escapeNotVerified */ $helper->getEscapedQueryText() ?>" + placeholder="<?= /* @escapeNotVerified */ __('Search entire store here...') ?>" + class="input-text" + maxlength="<?= /* @escapeNotVerified */ $helper->getMaxQueryLength() ?>" + role="combobox" + aria-haspopup="false" + aria-autocomplete="both" + autocomplete="off" + /> + </label> <div id="search_autocomplete" class="search-autocomplete"></div> <?= $block->getChildHtml() ?> </div> </div> <div class="actions"> <button type="submit" - title="<?= $block->escapeHtml(__('Search')) ?>" - class="action search"> + title="<?= $block->escapeHtml(__('Search')) ?>" + class="action search" + aria-label="Search" + > <span><?= /* @escapeNotVerified */ __('Search') ?></span> </button> </div> diff --git a/app/code/Magento/Search/view/frontend/web/js/form-mini.js b/app/code/Magento/Search/view/frontend/web/js/form-mini.js index 15bcf2e73393e..5331ba3b447ac 100644 --- a/app/code/Magento/Search/view/frontend/web/js/form-mini.js +++ b/app/code/Magento/Search/view/frontend/web/js/form-mini.js @@ -72,7 +72,6 @@ define([ }.bind(this), exit: function () { this.isExpandable = false; - this.element.removeAttr('aria-expanded'); }.bind(this) }); diff --git a/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml b/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml index f719f5dd78307..9c34dfea3218b 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml @@ -12,7 +12,11 @@ ?> <?php $storeName = $block->getThemeName() ? $block->getThemeName() : $block->getLogoAlt();?> <span data-action="toggle-nav" class="action nav-toggle"><span><?= /* @escapeNotVerified */ __('Toggle Nav') ?></span></span> -<a class="logo" href="<?= $block->getUrl('') ?>" title="<?= /* @escapeNotVerified */ $storeName ?>"> +<a + class="logo" + href="<?= $block->getUrl('') ?>" + title="<?= /* @escapeNotVerified */ $storeName ?>" + aria-label="store logo"> <img src="<?= /* @escapeNotVerified */ $block->getLogoSrc() ?>" title="<?= $block->escapeHtmlAttr($block->getLogoAlt()) ?>" alt="<?= $block->escapeHtmlAttr($block->getLogoAlt()) ?>" diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html index 3d4f9eefe5afa..fd4ee0ad88da9 100644 --- a/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html +++ b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html @@ -13,14 +13,20 @@ data-bind="attr: {href: tooltip.link}, mageInit: {'dropdown':{'activeClass': '_active'}}"></a> <!-- /ko --> + <span id="tooltip-label" class="label">Tooltip</span> <!-- ko if: (!tooltip.link)--> - <span class="field-tooltip-action action-help" - tabindex="0" - data-toggle="dropdown" - data-bind="mageInit: {'dropdown':{'activeClass': '_active'}}"></span> + <span + id="tooltip" + class="field-tooltip-action action-help" + tabindex="0" + data-toggle="dropdown" + data-bind="mageInit: {'dropdown':{'activeClass': '_active', 'parent': '.field-tooltip.toggle'}}" + aria-labelledby="tooltip-label" + > + </span> <!-- /ko --> - <div class="field-tooltip-content" + <div class="field-tooltip-content" data-target="dropdown" translate="tooltip.description"> </div> </div> diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less index 664726ddfd798..f958d7081f963 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less @@ -55,6 +55,10 @@ } } + .label { + .lib-visually-hidden(); + } + .field-tooltip-action { .lib-icon-font( @checkout-tooltip-icon__content, diff --git a/app/design/frontend/Magento/luma/Magento_Theme/layout/default_head_blocks.xml b/app/design/frontend/Magento/luma/Magento_Theme/layout/default_head_blocks.xml index 2dfb1d3ee6bf0..7e64e5f3f01cd 100644 --- a/app/design/frontend/Magento/luma/Magento_Theme/layout/default_head_blocks.xml +++ b/app/design/frontend/Magento/luma/Magento_Theme/layout/default_head_blocks.xml @@ -7,6 +7,6 @@ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <head> - <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"/> + <meta name="viewport" content="width=device-width, initial-scale=1"/> </head> </page> From 09488fc3369ccba16cd2ed1e4e8667df2b499a29 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Mon, 15 Apr 2019 17:10:18 -0500 Subject: [PATCH 290/585] GraphQL-594: Test coverage for tag cache generation for category - integration test coverage for category with products --- .../Controller/GraphQlCacheControllerTest.php | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php index 400dea5dd12dd..29aac2ffa378f 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php @@ -163,4 +163,74 @@ public function testDispatchForCacheDebugHeadersAndCacheTagsForCategory(): void ); } } + + /** + * Test cache tags and debug header for category with products querying for products and category + * + * @magentoCache all enabled + * @magentoDataFixture Magento/Catalog/_files/category_product.php + * + */ + public function testDispatchForCacheHeadersAndCacheTagsForCategoryWtihProducts(): void + { + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + /** @var ProductInterface $product */ + $product= $productRepository->get('simple333'); + $categoryId ='333'; + $query + = <<<QUERY +query GetCategoryWithProducts(\$id: Int!, \$pageSize: Int!, \$currentPage: Int!) { + category(id: \$id) { + id + description + name + product_count + products( + pageSize: \$pageSize, + currentPage: \$currentPage) { + items { + id + name + attribute_set_id + url_key + sku + type_id + updated_at + url_key + url_path + } + total_count + } + } + } +QUERY; + $variables =[ + 'id' => 333, + 'pageSize'=> 10, + 'currentPage' => 1 + ]; + $queryParams = [ + 'query' => $query, + 'variables' => json_encode($variables), + 'operationName' => 'GetCategoryWithProducts' + ]; + + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setParams($queryParams); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $product->getId(),'FPC']; + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + } } + From 16ee54e2ae405217efe9fe61e9b8c6d3f302cbef Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 15 Apr 2019 17:15:14 -0500 Subject: [PATCH 291/585] Issue-230: Implement cache tag generation for GraphQL queries --- .../CmsGraphQl/Model/Resolver/Block/IdentityResolver.php | 4 ++-- app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php index 4f5913c458d05..a393f6ab04f42 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php @@ -26,8 +26,8 @@ public function getIdentifiers(array $resolvedData): array $ids = []; $items = $resolvedData['items'] ?? []; foreach ($items as $item) { - if (is_array($item) && !empty($item[BlockInterface::IDENTIFIER])) { - $ids[] = $item[BlockInterface::IDENTIFIER ]; + if (is_array($item) && !empty($item[BlockInterface::BLOCK_ID])) { + $ids[] = $item[BlockInterface::BLOCK_ID]; } } diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php index bf57e8c9736ca..326c53b589911 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -64,11 +64,11 @@ public function handleCacheFromResolverResponse(array $resolvedValue, Field $fie $cacheTags = []; if ($cacheTag && $this->request->isGet()) { - $cacheTags[] = $cacheTag; if (!empty($cacheIdentityResolverClass)) { $cacheIdentityResolver = $this->identityResolverPool->get($cacheIdentityResolverClass); $cacheTagIds = $cacheIdentityResolver->getIdentifiers($resolvedValue); if (!empty($cacheTagIds)) { + $cacheTags[] = $cacheTag; foreach ($cacheTagIds as $cacheTagId) { $cacheTags[] = $cacheTag . '_' . $cacheTagId; } From d254922b90cb4b3ee90e34571f9caf2978d65f28 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Tue, 16 Apr 2019 10:52:17 +0530 Subject: [PATCH 292/585] code cleanup --- .../Magento/Customer/Model/ResourceModel/CustomerRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php index ddc0576cb0dae..038526053b872 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php +++ b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php @@ -343,7 +343,7 @@ public function getById($customerId) * Retrieve customers which match a specified criteria. * * This call returns an array of objects, but detailed information about each object’s attributes might not be - * included. See http://devdocs.magento.com/codelinks/attributes.html#CustomerRepositoryInterface to determine + * included. See https://devdocs.magento.com/codelinks/attributes.html#CustomerRepositoryInterface to determine * which call to use to get detailed information about all attributes for an object. * * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria From a396e2fcc65e2c7d030b6eaafab34c0cd9fcffcd Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Tue, 16 Apr 2019 10:58:29 +0530 Subject: [PATCH 293/585] Correct spelling --- .../Magento/Catalog/Model/ResourceModel/Product/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index 136c7e800bf08..a50864e908331 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -445,7 +445,7 @@ protected function _preparePriceExpressionParameters($select) */ public function getPriceExpression($select) { - //@todo: Add caching of price expresion + //@todo: Add caching of price expression $this->_preparePriceExpressionParameters($select); return $this->_priceExpression; } From 71463ddc1897200ded1cfd27100c824fe9ead5c2 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 16 Apr 2019 10:53:43 +0300 Subject: [PATCH 294/585] MC-11943: Cancel Created Order for Offline Payment Methods --- .../app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml index e45609bb90c83..fdb396bbbd052 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml @@ -18,7 +18,6 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> </variation> <variation name="CancelCreatedOrderTestVariationWithZeroSubtotalCheckout" summary="Cancel order with zero subtotal checkout payment method and check status on storefront"> - <data name="tag" xsi:type="string">stable:no</data> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/payment_auth_expiration/method" xsi:type="string">free</data> <data name="order/data/shipping_method" xsi:type="string">freeshipping_freeshipping</data> From d4972dcde417536ab676a5a26b2f507299aa289c Mon Sep 17 00:00:00 2001 From: niravkrish <nirav.patel@krishtechnolabs.com> Date: Tue, 16 Apr 2019 14:38:49 +0530 Subject: [PATCH 295/585] Fixed - Category API update Issue required name on update --- app/code/Magento/Catalog/Api/Data/CategoryInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Api/Data/CategoryInterface.php b/app/code/Magento/Catalog/Api/Data/CategoryInterface.php index b9a23e9d08ec3..c1ca89f51ea58 100644 --- a/app/code/Magento/Catalog/Api/Data/CategoryInterface.php +++ b/app/code/Magento/Catalog/Api/Data/CategoryInterface.php @@ -74,7 +74,7 @@ public function setParentId($parentId); /** * Get category name * - * @return string + * @return string|null */ public function getName(); From 96b11759a3fae5d264026adf8740ae6ed437dc83 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Tue, 16 Apr 2019 13:39:54 +0300 Subject: [PATCH 296/585] MC-12180: Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie --- .../Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml index dbe5ddcc366f1..87aab45bd8cb7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml @@ -9,8 +9,8 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontWidgetsSection"> - <element name="widgetRecentlyViewedProductsGrid" type="block" selector=".block.widget.block-viewed-products-grid" timeout="30"/> - <element name="widgetRecentlyComparedProductsGrid" type="block" selector=".block.widget.block-compared-products-grid" timeout="30"/> - <element name="widgetRecentlyOrderedProductsGrid" type="block" selector=".block.block-reorder" timeout="30"/> + <element name="widgetRecentlyViewedProductsGrid" type="block" selector=".block.widget.block-viewed-products-grid"/> + <element name="widgetRecentlyComparedProductsGrid" type="block" selector=".block.widget.block-compared-products-grid"/> + <element name="widgetRecentlyOrderedProductsGrid" type="block" selector=".block.block-reorder"/> </section> </sections> \ No newline at end of file From 251eab09b0e01f657b8d908fcc49588aa3d80d98 Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Tue, 16 Apr 2019 13:53:01 +0300 Subject: [PATCH 297/585] MC-11954: Admin Global Search --- .../Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml index dca6e1d15024f..6d9c50b4317c8 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml @@ -8,31 +8,26 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Backend\Test\TestCase\GlobalSearchEntityTest" summary="Global Search Backend " ticketId="MAGETWO-28457"> <variation name="GlobalSearchEntityTestVariation1"> - <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">search shows admin preview</data> <data name="search/data/query" xsi:type="string">Some search term</data> <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchPreview" /> </variation> <variation name="GlobalSearchEntityTestVariation2"> - <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">search with 2 sign return no results</data> <data name="search/data/query" xsi:type="string">:)</data> <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchNoRecordsFound" /> </variation> <variation name="GlobalSearchEntityTestVariation3"> - <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">search product by sku</data> <data name="search/data/query" xsi:type="string">orderInjectable::default::product::sku</data> <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchProductName" /> </variation> <variation name="GlobalSearchEntityTestVariation4"> - <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">search existed customer</data> <data name="search/data/query" xsi:type="string">customer::johndoe_unique::lastname</data> <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchCustomerName" /> </variation> <variation name="GlobalSearchEntityTestVariation5"> - <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">search order (by order id)</data> <data name="search/data/query" xsi:type="string">orderInjectable::default::id</data> <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchOrderId" /> From 266c55250024f2d874c37ad811e10c41a053e7a4 Mon Sep 17 00:00:00 2001 From: Mikalai Shostka <mikalai_shostka@epam.com> Date: Tue, 16 Apr 2019 14:20:14 +0300 Subject: [PATCH 298/585] MAGETWO-64260: [Optimize] Performance for grouped products with large # of options - Fix static test; --- app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php index c362474e3cf68..187fd27fa0554 100644 --- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php @@ -475,10 +475,12 @@ public function hasWeight() * @param \Magento\Catalog\Model\Product $product * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * phpcs:disable Magento2.CodeAnalysis.EmptyBlock */ public function deleteTypeSpecificData(\Magento\Catalog\Model\Product $product) { } + //phpcs:enable /** * @inheritdoc @@ -488,6 +490,7 @@ public function beforeSave($product) //clear cached associated links $product->unsetData($this->_keyAssociatedProducts); if ($product->hasData('product_options') && !empty($product->getData('product_options'))) { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Custom options for grouped product type are not supported'); } return parent::beforeSave($product); From 3c50c7ceed1728d3886131b29ea2e0d937a68b97 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 16:47:12 +0300 Subject: [PATCH 299/585] magento/magento2#21772: Static test fix. --- .../Adapter/Mysql/Filter/Preprocessor.php | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php index 51eb2077b80ea..c758e773f43c1 100644 --- a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php +++ b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php @@ -8,7 +8,9 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\ResourceModel\Eav\Attribute; +use Magento\CatalogSearch\Model\Search\FilterMapper\VisibilityFilter; use Magento\CatalogSearch\Model\Search\TableMapper; +use Magento\Customer\Model\Session; use Magento\Eav\Model\Config; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ObjectManager; @@ -20,10 +22,11 @@ use Magento\Framework\Search\Adapter\Mysql\Filter\PreprocessorInterface; use Magento\Framework\Search\Request\FilterInterface; use Magento\Store\Model\Store; -use Magento\Customer\Model\Session; -use Magento\CatalogSearch\Model\Search\FilterMapper\VisibilityFilter; /** + * ElasticSearch search filter pre-processor. + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @deprecated * @see \Magento\ElasticSearch @@ -128,7 +131,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function process(FilterInterface $filter, $isNegation, $query) { @@ -136,10 +139,13 @@ public function process(FilterInterface $filter, $isNegation, $query) } /** + * Process query with field. + * * @param FilterInterface $filter * @param bool $isNegation * @param string $query * @return string + * @throws \Magento\Framework\Exception\LocalizedException */ private function processQueryWithField(FilterInterface $filter, $isNegation, $query) { @@ -204,19 +210,23 @@ private function processQueryWithField(FilterInterface $filter, $isNegation, $qu ->where('main_table.store_id = ?', Store::DEFAULT_STORE_ID) ->having($query); - $resultQuery = 'search_index.entity_id IN ( - select entity_id from ' . $this->conditionManager->wrapBrackets($select) . ' as filter - )'; + $resultQuery = 'search_index.entity_id IN (' + . 'select entity_id from ' + . $this->conditionManager->wrapBrackets($select) + . ' as filter)'; } return $resultQuery; } /** + * Process range numeric. + * * @param FilterInterface $filter * @param string $query * @param Attribute $attribute * @return string + * @throws \Exception */ private function processRangeNumeric(FilterInterface $filter, $query, $attribute) { @@ -238,14 +248,17 @@ private function processRangeNumeric(FilterInterface $filter, $query, $attribute ->where('main_table.store_id = ?', $currentStoreId) ->having($query); - $resultQuery = 'search_index.entity_id IN ( - select entity_id from ' . $this->conditionManager->wrapBrackets($select) . ' as filter - )'; + $resultQuery = 'search_index.entity_id IN (' + . 'select entity_id from ' + . $this->conditionManager->wrapBrackets($select) + . ' as filter)'; return $resultQuery; } /** + * Process term select. + * * @param FilterInterface $filter * @param bool $isNegation * @return string From 0c954cd5275f04a3469a5ea907125c0ccb10a04a Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 16 Apr 2019 15:16:19 +0300 Subject: [PATCH 300/585] magento/magento2#22200: Static test fix. --- pub/health_check.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pub/health_check.php b/pub/health_check.php index 06c79baa2fd81..fc6d73daa2079 100644 --- a/pub/health_check.php +++ b/pub/health_check.php @@ -4,11 +4,17 @@ * See COPYING.txt for license details. */ +/** + * phpcs:disable PSR1.Files.SideEffects + * phpcs:disable Squiz.Functions.GlobalFunction + */ use Magento\Framework\Config\ConfigOptionsListConstants; +// phpcs:ignore Magento2.Functions.DiscouragedFunction register_shutdown_function("fatalErrorHandler"); try { + // phpcs:ignore Magento2.Security.IncludeFile require __DIR__ . '/../app/bootstrap.php'; /** @var \Magento\Framework\App\ObjectManagerFactory $objectManagerFactory */ $objectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, []); @@ -20,6 +26,7 @@ $logger = $objectManager->get(\Psr\Log\LoggerInterface::class); } catch (\Exception $e) { http_response_code(500); + // phpcs:ignore Magento2.Security.LanguageConstruct exit(1); } @@ -35,6 +42,7 @@ } catch (\Exception $e) { http_response_code(500); $logger->error("MySQL connection failed: " . $e->getMessage()); + // phpcs:ignore Magento2.Security.LanguageConstruct exit(1); } } @@ -47,6 +55,7 @@ !isset($cacheConfig[ConfigOptionsListConstants::CONFIG_PATH_BACKEND_OPTIONS])) { http_response_code(500); $logger->error("Cache configuration is invalid"); + // phpcs:ignore Magento2.Security.LanguageConstruct exit(1); } $cacheBackendClass = $cacheConfig[ConfigOptionsListConstants::CONFIG_PATH_BACKEND]; @@ -57,6 +66,7 @@ } catch (\Exception $e) { http_response_code(500); $logger->error("Cache storage is not accessible"); + // phpcs:ignore Magento2.Security.LanguageConstruct exit(1); } } From 1a1eda6a26301b10d97b6b33ab5e3a195e212f94 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 16 Apr 2019 15:58:25 +0300 Subject: [PATCH 301/585] magento/magento2#22318: Static test fix. --- .../Catalog/Model/Indexer/Product/Flat/TableBuilder.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php index 0865c311e7094..2c32a74eb0f1d 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php @@ -304,9 +304,12 @@ protected function _fillTemporaryTable( /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ foreach ($columnsList as $columnName => $attribute) { - $countTableName = 't' . $iterationNum++; + $countTableName = 't' . ($iterationNum++); $joinCondition = sprintf( - 'e.%3$s = %1$s.%3$s AND %1$s.attribute_id = %2$d AND (%1$s.store_id = %4$d OR %1$s.store_id = 0)', + 'e.%3$s = %1$s.%3$s' . + ' AND %1$s.attribute_id = %2$d' . + ' AND (%1$s.store_id = %4$d' . + ' OR %1$s.store_id = 0)', $countTableName, $attribute->getId(), $metadata->getLinkField(), From 0453184879c5957d7ec4c903b9148c8ea35e43c1 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 16 Apr 2019 16:18:59 +0300 Subject: [PATCH 302/585] magento/magento2#22291: Static test fix. --- .../Product/Downloads/Collection.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php index aeb0448f8e05a..2009cd3ff9d92 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php @@ -4,16 +4,16 @@ * See COPYING.txt for license details. */ +namespace Magento\Reports\Model\ResourceModel\Product\Downloads; + /** * Product Downloads Report collection * * @author Magento Core Team <core@magentocommerce.com> - */ -namespace Magento\Reports\Model\ResourceModel\Product\Downloads; - -/** + * * @api * @since 100.0.2 + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection { @@ -97,13 +97,11 @@ public function addFieldToFilter($field, $condition = null) } return $this; } - + /** - * Get SQL for get record count without left JOINs and group - * - * @return \Magento\Framework\DB\Select + * @inheritDoc */ - public function getSelectCountSql() + public function getSelectCountSql() { $countSelect = parent::getSelectCountSql(); $countSelect->reset(\Zend\Db\Sql\Select::GROUP); From f266f4bfe56415c3c225ac2fccf658dda59e5667 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Tue, 16 Apr 2019 16:59:54 +0300 Subject: [PATCH 303/585] Gix static tests. --- .../Adminhtml/System/Design/Theme/UploadJs.php | 6 +++++- app/code/Magento/Theme/Model/Design/Backend/File.php | 5 ++--- .../Model/Design/Config/FileUploader/FileProcessor.php | 2 ++ app/code/Magento/Theme/Model/Wysiwyg/Storage.php | 9 ++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php index ce88315b6225b..89636ad3de50e 100644 --- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php +++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php @@ -4,13 +4,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Controller\Adminhtml\System\Design\Theme; +use Magento\Framework\App\Action\HttpGetActionInterface; + /** * Class UploadJs * @deprecated */ -class UploadJs extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme +class UploadJs extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme implements HttpGetActionInterface { /** * Upload js file @@ -49,6 +52,7 @@ public function execute() \Magento\Framework\View\Design\Theme\Customization\File\Js::TYPE ); $result = ['error' => false, 'files' => $customization->generateFileInfo($customJsFiles)]; + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (\Magento\Framework\Exception\LocalizedException $e) { $result = ['error' => true, 'message' => $e->getMessage()]; } catch (\Exception $e) { diff --git a/app/code/Magento/Theme/Model/Design/Backend/File.php b/app/code/Magento/Theme/Model/Design/Backend/File.php index 72ca9295ad12f..8d1884671c3fb 100644 --- a/app/code/Magento/Theme/Model/Design/Backend/File.php +++ b/app/code/Magento/Theme/Model/Design/Backend/File.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Model\Design\Backend; use Magento\Config\Model\Config\Backend\File\RequestData\RequestDataInterface; @@ -109,9 +110,7 @@ public function beforeSave() } /** - * @return $this - * - * @throws LocalizedException + * @inheritDoc */ public function afterLoad() { diff --git a/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php b/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php index 6da7cb74e6741..901dbf7d88f3d 100644 --- a/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php +++ b/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php @@ -18,6 +18,8 @@ use Magento\Store\Model\StoreManagerInterface; /** + * Design file processor. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class FileProcessor diff --git a/app/code/Magento/Theme/Model/Wysiwyg/Storage.php b/app/code/Magento/Theme/Model/Wysiwyg/Storage.php index f1a4b1ffc8d65..0519460c02423 100644 --- a/app/code/Magento/Theme/Model/Wysiwyg/Storage.php +++ b/app/code/Magento/Theme/Model/Wysiwyg/Storage.php @@ -4,17 +4,12 @@ * See COPYING.txt for license details. */ -/** - * Theme wysiwyg storage model - */ namespace Magento\Theme\Model\Wysiwyg; use Magento\Framework\App\Filesystem\DirectoryList; /** - * Class Storage - * - * @package Magento\Theme\Model\Wysiwyg + * Theme wysiwyg storage model */ class Storage { @@ -271,7 +266,7 @@ public function getFilesCollection() if (self::TYPE_IMAGE == $storageType) { $requestParams['file'] = $fileName; $file['thumbnailParams'] = $requestParams; - + //phpcs:ignore Generic.PHP.NoSilencedErrors $size = @getimagesize($path); if (is_array($size)) { $file['width'] = $size[0]; From fa5cf907e0bd9f0fda4431a551e798a911dfe875 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Tue, 16 Apr 2019 17:24:30 +0300 Subject: [PATCH 304/585] Fix static tests. --- .../Magento/Quote/Model/QuoteRepository.php | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Quote/Model/QuoteRepository.php b/app/code/Magento/Quote/Model/QuoteRepository.php index fa6ab18136688..30931821ddc7d 100644 --- a/app/code/Magento/Quote/Model/QuoteRepository.php +++ b/app/code/Magento/Quote/Model/QuoteRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model; use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; @@ -24,6 +25,8 @@ use Magento\Store\Model\StoreManagerInterface; /** + * Quote repository. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class QuoteRepository implements CartRepositoryInterface @@ -125,7 +128,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function get($cartId, array $sharedStoreIds = []) { @@ -138,7 +141,7 @@ public function get($cartId, array $sharedStoreIds = []) } /** - * {@inheritdoc} + * @inheritdoc */ public function getForCustomer($customerId, array $sharedStoreIds = []) { @@ -152,7 +155,7 @@ public function getForCustomer($customerId, array $sharedStoreIds = []) } /** - * {@inheritdoc} + * @inheritdoc */ public function getActive($cartId, array $sharedStoreIds = []) { @@ -164,7 +167,7 @@ public function getActive($cartId, array $sharedStoreIds = []) } /** - * {@inheritdoc} + * @inheritdoc */ public function getActiveForCustomer($customerId, array $sharedStoreIds = []) { @@ -176,7 +179,7 @@ public function getActiveForCustomer($customerId, array $sharedStoreIds = []) } /** - * {@inheritdoc} + * @inheritdoc */ public function save(CartInterface $quote) { @@ -196,7 +199,7 @@ public function save(CartInterface $quote) } /** - * {@inheritdoc} + * @inheritdoc */ public function delete(CartInterface $quote) { @@ -232,7 +235,7 @@ protected function loadQuote($loadMethod, $loadField, $identifier, array $shared } /** - * {@inheritdoc} + * @inheritdoc */ public function getList(SearchCriteriaInterface $searchCriteria) { @@ -277,6 +280,7 @@ protected function addFilterGroupToCollection(FilterGroup $filterGroup, QuoteCol /** * Get new SaveHandler dependency for application code. + * * @return SaveHandler * @deprecated 100.1.0 */ @@ -289,6 +293,8 @@ private function getSaveHandler() } /** + * Get load handler instance. + * * @return LoadHandler * @deprecated 100.1.0 */ From fcb544f5a001701cf966b181d6b6871e1c628c2c Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 16 Apr 2019 17:30:49 +0300 Subject: [PATCH 305/585] MC-5270: Assign Products at the Category Level --- .../Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml index ea6808ee2a7f5..223aa57335b13 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml @@ -146,7 +146,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage" /> </variation> <variation name="CreateCategoryEntityTestVariation8_WithProducts" summary="Assign Products at the Category Level" ticketId="MAGETWO-16351"> - <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test, stable:no</data> + <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test</data> <data name="addCategory" xsi:type="string">addSubcategory</data> <data name="category/data/parent_id/dataset" xsi:type="string">default_category</data> <data name="category/data/is_active" xsi:type="string">Yes</data> From 85319f0ca56cd22911e3e46fdd6e4d86de352238 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 16 Apr 2019 17:32:18 +0300 Subject: [PATCH 306/585] magento/magento2#22133: Static test fix. --- .../Eav/Model/ResourceModel/Entity/Attribute/Collection.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php index d70e2e0e06e96..6fce6bd2dc44e 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\ResourceModel\Entity\Attribute; use Magento\Eav\Model\Entity\Type; @@ -183,6 +184,7 @@ public function setAttributeSetFilterBySetName($attributeSetName, $entityTypeCod /** * Specify multiple attribute sets filter + * * Result will be ordered by sort_order * * @param array $setIds @@ -225,7 +227,6 @@ public function setInAllAttributeSetsFilter(array $setIds) ->having(new \Zend_Db_Expr('COUNT(*)') . ' = ' . count($setIds)); } - //$this->getSelect()->distinct(true); $this->setOrder('is_user_defined', self::SORT_ORDER_ASC); return $this; @@ -475,7 +476,7 @@ public function addStoreLabel($storeId) } /** - * {@inheritdoc} + * @inheritdoc */ public function getSelectCountSql() { From 3d7a714756be70640fc0267fe17dfdd76ff173ed Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 16 Apr 2019 09:34:20 -0500 Subject: [PATCH 307/585] MQE-1478: Fix all existing deprecation warnings in 2.3-develop --- .../Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml | 2 ++ .../Test/AdminGridPageNumberAfterSaveAndCloseActionTest.xml | 1 + .../Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml | 1 + 3 files changed, 4 insertions(+) diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml index 4c39cbc4ab0a4..532af1ea76dca 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml @@ -13,8 +13,10 @@ <features value="Bundle"/> <stories value="View bundle products"/> <title value="Check tier prices for bundle options"/> + <description value="Check tier prices for bundle options"/> <testCaseId value="MAGETWO-98968"/> <useCaseId value="MAGETWO-98603"/> + <severity value="AVERAGE"/> <group value="catalog"/> <group value="bundle"/> </annotations> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminGridPageNumberAfterSaveAndCloseActionTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminGridPageNumberAfterSaveAndCloseActionTest.xml index b24ed7f9c9a81..053f165c8745c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminGridPageNumberAfterSaveAndCloseActionTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminGridPageNumberAfterSaveAndCloseActionTest.xml @@ -11,6 +11,7 @@ <test name="AdminGridPageNumberAfterSaveAndCloseActionTest"> <annotations> <features value="Catalog"/> + <stories value="Catalog grid"/> <title value="Checking Catalog grid page number after Save and Close action"/> <description value="Checking Catalog grid page number after Save and Close action"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml index f39394ef312e4..11a6fbff8a405 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml @@ -9,6 +9,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AllowedCountriesRestrictionApplyOnBackendTest"> <annotations> + <stories value="Country filter"/> <title value="Country filter on Customers page when allowed countries restriction for a default website is applied"/> <description value="Country filter on Customers page when allowed countries restriction for a default website is applied"/> <features value="Customer"/> From bb185021332e9b3f714f2cd26a0b854deb51a29b Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Tue, 16 Apr 2019 10:16:02 -0500 Subject: [PATCH 308/585] MC-15785: Overall storefront improvements --- .../frontend/web/templates/form/element/helper/tooltip.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html index fd4ee0ad88da9..f8d1cbbcad5c1 100644 --- a/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html +++ b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html @@ -13,7 +13,7 @@ data-bind="attr: {href: tooltip.link}, mageInit: {'dropdown':{'activeClass': '_active'}}"></a> <!-- /ko --> - <span id="tooltip-label" class="label">Tooltip</span> + <span id="tooltip-label" class="label"><!-- ko i18n: 'Tooltip' --><!-- /ko --></span> <!-- ko if: (!tooltip.link)--> <span id="tooltip" From 03cb300cb527e82bfcc411ccde99a39d5af2c8e9 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 16 Apr 2019 11:45:24 -0500 Subject: [PATCH 309/585] MAGETWO-98853: reporting_system_updates table exceptionally large (4gb) --- .../NewRelicReporting/Model/Module/Collect.php | 4 +++- .../NewRelicReporting/Model/Module/CollectTest.php | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php index ac7e4df9331c3..fe5389e258aa5 100644 --- a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php +++ b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php @@ -11,6 +11,9 @@ use Magento\NewRelicReporting\Model\Config; use Magento\NewRelicReporting\Model\Module; +/** + * Class for collecting data for the report + */ class Collect { /** @@ -92,7 +95,6 @@ protected function getAllModules() * @param string $active * @param string $setupVersion * @param string $state - * * @return array */ protected function getNewModuleChanges($moduleName, $active, $setupVersion, $state) diff --git a/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php index 4243ca7ab626d..58759d35337bd 100644 --- a/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php +++ b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php @@ -8,6 +8,11 @@ use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; +/*** + * Class CollectTest + * + * @covers Collect + */ class CollectTest extends TestCase { /** @@ -15,11 +20,17 @@ class CollectTest extends TestCase */ private $collect; + /** + * @inheritDoc + */ protected function setUp() { $this->collect = Bootstrap::getObjectManager()->create(Collect::class); } + /** + * @return void + */ public function testReport() { $this->collect->getModuleData(); From e995c1ba60c6eef45c3523fb0ca14d0bf57ef2f0 Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Tue, 16 Apr 2019 12:50:51 -0500 Subject: [PATCH 310/585] 596: Category with Products with...(deep nesting) (Integration Test for Tag Cache Generation) - Added integration test --- .../Controller/GraphQlCacheControllerTest.php | 97 ++++++++++++++++++- 1 file changed, 95 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php index 400dea5dd12dd..c6df4f6135a0b 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php @@ -13,6 +13,8 @@ use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Serialize\SerializerInterface; use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use Magento\Catalog\Api\CategoryRepositoryInterface; /** * Tests cache debug headers and cache tag validation for a simple product query @@ -45,7 +47,6 @@ class GraphQlCacheControllerTest extends \Magento\TestFramework\Indexer\TestCase /** @var \Magento\Framework\App\Response\Http */ private $response; - /** * @inheritdoc */ @@ -159,8 +160,100 @@ public function testDispatchForCacheDebugHeadersAndCacheTagsForCategory(): void $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'FPC']; foreach (array_keys($actualCacheTags) as $key) { - $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key] + $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); + } + } + + /** + * Test cache tags and debug header for deep nested queries involving category and products + * + * @magentoCache all enabled + * @magentoDataFixture Magento/Catalog/_files/product_in_multiple_categories.php + * + */ + public function testDispatchForCacheHeadersOnDeepNestedQueries(): void + { + $categoryId ='333'; + $query + = <<<QUERY + { + category(id: $categoryId) { + products { + items { + attribute_set_id + country_of_manufacture + created_at + description { + html + } + gift_message_available + id + categories { + name + url_path + available_sort_by + level + products { + items { + name + id + } + } + } + } + } + } +} +QUERY; + /** @var CategoryRepositoryInterface $categoryRepository */ + $categoryRepository = ObjectManager::getInstance()->get(CategoryRepositoryInterface::class); + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + $categoryIds = []; + $category = $categoryRepository->get('333'); + + $productIdsFromCategory = $category->getProductCollection()->getAllIds(); + foreach ($productIdsFromCategory as $productId) { + $categoryIds = array_merge($categoryIds, $productRepository->getById($productId)->getCategoryIds()); + } + + $categoryIds = array_merge($categoryIds, ['333']); + foreach ($categoryIds as $categoryId) { + $category = $categoryRepository->get($categoryId); + $productIdsFromCategory= array_merge( + $productIdsFromCategory, + $category->getProductCollection()->getAllIds() ); } + + $uniqueProductIds = array_unique($productIdsFromCategory); + $uniqueCategoryIds = array_unique($categoryIds); + $expectedCacheTags = ['cat_c', 'cat_p', 'FPC']; + foreach ($uniqueProductIds as $productId) { + $expectedCacheTags = array_merge($expectedCacheTags, ['cat_p_'.$productId]); + } + foreach ($uniqueCategoryIds as $categoryId) { + $expectedCacheTags = array_merge($expectedCacheTags, ['cat_c_'.$categoryId]); + } + + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $this->assertEmpty( + array_merge( + array_diff($expectedCacheTags, $actualCacheTags), + array_diff($actualCacheTags, $expectedCacheTags) + ) + ); } } From c7895084798868169914d9dd046f866979a686e5 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Tue, 16 Apr 2019 13:10:31 -0500 Subject: [PATCH 311/585] MC-15785: Overall storefront improvements --- .../tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml index 71115e402880c..0973b968cba95 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml @@ -8,7 +8,7 @@ <mapping strict="0"> <fields> <email> - <selector>#customer-email</selector> + <selector>#checkout-customer-email</selector> </email> <firstname /> <lastname /> From ea9abdb22d5530e10e8150c8c30ec91a2e61b89b Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 16 Apr 2019 13:16:28 -0500 Subject: [PATCH 312/585] MAGETWO-98853: reporting_system_updates table exceptionally large (4gb) --- .../Magento/NewRelicReporting/Model/Module/CollectTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php index 58759d35337bd..5e5051163cc1f 100644 --- a/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php +++ b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php @@ -10,8 +10,6 @@ /*** * Class CollectTest - * - * @covers Collect */ class CollectTest extends TestCase { From 78349ac9a823386feadccd8f55d05414a24d5831 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Tue, 16 Apr 2019 13:40:20 -0500 Subject: [PATCH 313/585] MC-15779: Create coupon test functionality for our benchmark --- setup/performance-toolkit/benchmark.jmx | 638 +++++++++++++++++++++++- 1 file changed, 637 insertions(+), 1 deletion(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 696b1964101a5..50fdd7462b254 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -374,6 +374,11 @@ <stringProp name="Argument.value">${__P(graphqlAddSimpleProductToCartPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> + <elementProp name="graphqlCatalogBrowsingByGuestPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlCatalogBrowsingByGuestPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlCatalogBrowsingByGuestPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> <elementProp name="graphqlCheckoutByGuestPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlCheckoutByGuestPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlCheckoutByGuestPercentage,0)}</stringProp> @@ -781,6 +786,7 @@ props.remove("customer_emails_list"); props.remove("categories"); props.remove("cms_pages"); props.remove("cms_blocks"); +props.remove("coupon_codes"); /* This is only used when admin is enabled. */ props.put("activeAdminThread", ""); @@ -2220,6 +2226,59 @@ adminCategoryIdsList.add(vars.get("category_id"));</stringProp> <hashTree/> </hashTree> </hashTree> + + <TestFragmentController guiclass="TestFragmentControllerGui" testclass="TestFragmentController" testname="Extract coupon codes" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/setup/extract_coupon_codes.jmx</stringProp> + </TestFragmentController> + <hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - API Get coupon codes" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="searchCriteria[pageSize]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">10</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">searchCriteria[pageSize]</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/coupons/search</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <JSR223PostProcessor guiclass="TestBeanGUI" testclass="JSR223PostProcessor" testname="PostProcessor" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">var data = JSON.parse(prev.getResponseDataAsString()); + +var couponCodes = []; + +for (var i in data.items) { + var coupon = data.items[i]; + couponCodes.push({"coupon_id":coupon.coupon_id, "rule_id":coupon.rule_id, "code": coupon.code}); + } + +props.put("coupon_codes", couponCodes); +</stringProp> + </JSR223PostProcessor> + <hashTree/> + </hashTree> + </hashTree> </hashTree> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: Validate properties and count users" enabled="true"> @@ -39930,7 +39989,7 @@ vars.putObject("category", categories[number]); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"query productSearch($inputText: String!, $categoryId: String) {\n products(search: $inputText, filter: { category_id: { eq: $categoryId } }) {\n items {\n id\n name\n small_image {\n label\n url\n }\n url_key\n price {\n regularPrice {\n amount {\n value\n currency\n }\n }\n }\n }\n total_count\n filters {\n name\n filter_items_count\n request_var\n filter_items {\n label\n value_string\n }\n }\n }\n}","variables":{"inputText":"Product","categoryId":"${category_id}"},"operationName":"productSearch"}</stringProp> + <stringProp name="Argument.value">{"query":"query productSearch($inputText: String!, $categoryId: String) {\n products(\n pageSize:12\n search: $inputText, filter: { category_id: { eq: $categoryId } }) {\n items {\n id\n name\n small_image {\n label\n url\n }\n url_key\n price {\n regularPrice {\n amount {\n value\n currency\n }\n }\n }\n }\n total_count\n filters {\n name\n filter_items_count\n request_var\n filter_items {\n label\n value_string\n }\n }\n }\n}","variables":{"inputText":"Product","categoryId":"${category_id}"},"operationName":"productSearch"}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42662,6 +42721,583 @@ vars.put("product_sku", product.get("sku")); </hashTree> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Catalog Browsing By Guest" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlCatalogBrowsingByGuestPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "GraphQL Catalog Browsing By Guest"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="SetUp - Prepare Category Data" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">random = vars.getObject("randomIntGenerator"); + +var categories = props.get("categories"); +number = random.nextInt(categories.length); + +vars.put("category_url_key", categories[number].url_key); +vars.put("category_name", categories[number].name); +vars.put("category_id", categories[number].id); +vars.putObject("category", categories[number]); + </stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/extract_category_setup.jmx</stringProp></JSR223Sampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Category List by category_id" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"> + {"query":"query categoryList($id: Int!) {\n category(id: $id) {\n id\n children {\n id\n name\n url_key\n url_path\n children_count\n path\n image\n productImagePreview: products(pageSize: 1) {\n items {\n small_image {\n label\n url\n }\n }\n }\n }\n }\n}","variables":{"id":${category_id}},"operationName":"categoryList"} + </stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_category_list_by_category_id.jmx</stringProp></HTTPSamplerProxy> + <hashTree> + <JSR223Assertion guiclass="TestBeanGUI" testclass="JSR223Assertion" testname="Assert found categories" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">var category = vars.getObject("category"); +var response = JSON.parse(prev.getResponseDataAsString()); + +assertCategoryId(category, response); +assertCategoryChildren(category, response); + +function assertCategoryId(category, response) { + if (response.data == undefined || response.data.category == undefined || response.data.category.id != category.id) { + AssertionResult.setFailureMessage("Cannot find category with id \"" + category.id + "\""); + AssertionResult.setFailure(true); + } +} + +function assertCategoryChildren(category, response) { + foundCategory = response.data && response.data.category ? response.data.category : null; + if (foundCategory) { + var childrenFound = foundCategory.children.map(function (c) {return parseInt(c.id)}); + var children = category.children.map(function (c) {return parseInt(c)}); + if (JSON.stringify(children.sort()) != JSON.stringify(childrenFound.sort())) { + AssertionResult.setFailureMessage("Cannot math children categories \"" + JSON.stringify(children) + "\" for to found one: \"" + JSON.stringify(childrenFound) + "\""); + AssertionResult.setFailure(true); + } + } + +} + +</stringProp> + </JSR223Assertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Navigation Menu by category_id" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query navigationMenu($id: Int!) {\n category(id: $id) {\n id\n name\n product_count\n path\n children {\n id\n name\n position\n level\n url_key\n url_path\n product_count\n children_count\n path\n productImagePreview: products(pageSize: 1) {\n items {\n small_image {\n label\n url\n }\n }\n }\n }\n }\n}","variables":{"id":${category_id}},"operationName":"navigationMenu"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_navigation_menu_by_category_id.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"id":${category_id},"name":"${category_name}","product_count"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Product Search by text and category_id" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productSearch($inputText: String!, $categoryId: String) {\n products(\n pageSize:12\n search: $inputText, filter: { category_id: { eq: $categoryId } }) {\n items {\n id\n name\n small_image {\n label\n url\n }\n url_key\n price {\n regularPrice {\n amount {\n value\n currency\n }\n }\n }\n }\n total_count\n filters {\n name\n filter_items_count\n request_var\n filter_items {\n label\n value_string\n }\n }\n }\n}","variables":{"inputText":"Product","categoryId":"${category_id}"},"operationName":"productSearch"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_product_search_by_text_and_category_id.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract total_count" enabled="true"> + <stringProp name="VAR">graphql_search_products_query_total_count</stringProp> + <stringProp name="JSONPATH">$.data.products.total_count</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <BeanShellAssertion guiclass="BeanShellAssertionGui" testclass="BeanShellAssertion" testname="Assert total count > 0" enabled="true"> + <stringProp name="BeanShellAssertion.query">String totalCount=vars.get("graphql_search_products_query_total_count"); + +if (totalCount == null) { + Failure = true; + FailureMessage = "Not Expected \"totalCount\" to be null"; +} else { + if (Integer.parseInt(totalCount) < 1) { + Failure = true; + FailureMessage = "Expected \"totalCount\" to be greater than zero, Actual: " + totalCount; + } else { + Failure = false; + } +} + + +</stringProp> + <stringProp name="BeanShellAssertion.filename"/> + <stringProp name="BeanShellAssertion.parameters"/> + <boolProp name="BeanShellAssertion.resetInterpreter">false</boolProp> + </BeanShellAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Url Info by url_key" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"> + {"query":"query resolveUrl($urlKey: String!) {\n urlResolver(url: $urlKey) {\n type\n id\n }\n}","variables":{"urlKey":"${category_url_key}${url_suffix}"},"operationName":"resolveUrl"} + </stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_url_info_by_url_key.jmx</stringProp></HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1062388959">{"type":"CATEGORY","id":${category_id}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get List of Products by category_id" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query category($id: Int!, $currentPage: Int, $pageSize: Int) {\n category(id: $id) {\n product_count\n description\n url_key\n name\n id\n breadcrumbs {\n category_name\n category_url_key\n __typename\n }\n products(pageSize: $pageSize, currentPage: $currentPage) {\n total_count\n items {\n id\n name\n # small_image\n # short_description\n url_key\n special_price\n special_from_date\n special_to_date\n price {\n regularPrice {\n amount {\n value\n currency\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n}\n","variables":{"id":${category_id},"currentPage":1,"pageSize":12},"operationName":"category"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_list_of_products_by_category_id.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"name":"${category_name}","id":${category_id},</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by product_url_key" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetail($urlKey: String, $onServer: Boolean!) {\n productDetail: products(filter: { url_key: { eq: $urlKey } }) {\n items {\n sku\n name\n price {\n regularPrice {\n amount {\n currency\n value\n }\n }\n }\n description {html}\n media_gallery_entries {\n label\n position\n disabled\n file\n }\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n # Yes, Products have `meta_keyword` and\n # everything else has `meta_keywords`.\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"urlKey":"${product_url_key}","onServer":false},"operationName":"productDetail"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_product_url_key.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Simple Product Details by name" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetail($name: String, $onServer: Boolean!) {\n productDetail: products(filter: { name: { eq: $name } }) {\n items {\n sku\n name\n price {\n regularPrice {\n amount {\n currency\n value\n }\n }\n }\n description {html}\n media_gallery_entries {\n label\n position\n disabled\n file\n }\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n # Yes, Products have `meta_keyword` and\n # everything else has `meta_keywords`.\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetail"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_simple_product_details_by_name.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Simple Product Details by product_url_key" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetail($urlKey: String, $onServer: Boolean!) {\n productDetail: products(filter: { url_key: { eq: $urlKey } }) {\n items {\n sku\n name\n price {\n regularPrice {\n amount {\n currency\n value\n }\n }\n }\n description {html}\n media_gallery_entries {\n label\n position\n disabled\n file\n }\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n # Yes, Products have `meta_keyword` and\n # everything else has `meta_keywords`.\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"urlKey":"${product_url_key}","onServer":false},"operationName":"productDetail"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_simple_product_details_by_product_url_key.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="SetUp - Prepare CMS Page" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">random = vars.getObject("randomIntGenerator"); + +var cmsPages = props.get("cms_pages"); +var number = random.nextInt(cmsPages.length); + +vars.put("cms_page_id", cmsPages[number].id); + </stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/setup/prepare_cms_page.jmx</stringProp></JSR223Sampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cms Page by id" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"> + {"query":"query getCmsPage($id: Int!, $onServer: Boolean!) {\n cmsPage(id: $id) {\n url_key\n content\n content_heading\n title\n page_layout\n meta_title @include(if: $onServer)\n meta_keywords @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n}","variables":{"id":${cms_page_id},"onServer":false},"operationName":"getCmsPage"} + </stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_get_cms_page_by_id.jmx</stringProp></HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.gui.JSONPathAssertionGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion" testname="jp@gc - JSON Path Assertion" enabled="true"> + <stringProp name="JSON_PATH">$.data.cmsPage.url_key</stringProp> + <stringProp name="EXPECTED_VALUE">${cms_page_id}</stringProp> + <boolProp name="JSONVALIDATION">false</boolProp> + <boolProp name="EXPECT_NULL">false</boolProp> + <boolProp name="INVERT">false</boolProp> + <boolProp name="ISREGEX">false</boolProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion> + <hashTree/> + </hashTree> + </hashTree> + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Checkout By Guest" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> From 737ee93c49d1dbeabab36185ea51d918d3c01dad Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Tue, 16 Apr 2019 14:02:51 -0500 Subject: [PATCH 314/585] MC-15779: Create coupon test functionality for our benchmark --- setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php index 31e5ab9ebd575..d68d936aa3af6 100644 --- a/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php +++ b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php @@ -20,7 +20,7 @@ class CouponCodesFixture extends Fixture /** * @var int */ - protected $priority = 130; + protected $priority = 129; /** * @var int From f88b9e339553dda75d2119cb412119912e760ed7 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Tue, 16 Apr 2019 14:40:59 -0500 Subject: [PATCH 315/585] MC-15779: Create coupon test functionality for our benchmark --- .../src/Magento/Setup/Fixtures/CouponCodesFixture.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php index d68d936aa3af6..e60a2c9f30765 100644 --- a/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php +++ b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php @@ -57,7 +57,8 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc + * * @SuppressWarnings(PHPMD) */ public function execute() @@ -101,9 +102,12 @@ public function execute() } /** + * Generate Coupon Codes + * * @param \Magento\SalesRule\Model\RuleFactory $ruleFactory * @param \Magento\SalesRule\Model\CouponFactory $couponCodeFactory * @param array $categoriesArray + * * @return void */ public function generateCouponCodes($ruleFactory, $couponCodeFactory, $categoriesArray) @@ -145,7 +149,7 @@ public function generateCouponCodes($ruleFactory, $couponCodeFactory, $categorie } /** - * {@inheritdoc} + * @inheritdoc */ public function getActionTitle() { @@ -153,7 +157,7 @@ public function getActionTitle() } /** - * {@inheritdoc} + * @inheritdoc */ public function introduceParamLabels() { From ee6c054ac3de1036a7fd14f5503d6fd8b3657f25 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Tue, 16 Apr 2019 15:34:31 -0500 Subject: [PATCH 316/585] GraphQL-594: Test coverage for tag cache generation for category - fixing minor issues with test --- .../GraphQl/Controller/GraphQlCacheControllerTest.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php index 29aac2ffa378f..822946cd7c36c 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php @@ -18,9 +18,8 @@ * Tests cache debug headers and cache tag validation for a simple product query * * @magentoAppArea graphql - * - * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php * @magentoDbIsolation disabled + * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class GraphQlCacheControllerTest extends \Magento\TestFramework\Indexer\TestCase @@ -81,7 +80,7 @@ protected function setUp(): void * @magentoCache all enabled * @return void */ - public function testDispatchWithGetForCacheDebugHeadersAndCacheTags(): void + public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForProducts(): void { /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); @@ -98,6 +97,7 @@ public function testDispatchWithGetForCacheDebugHeadersAndCacheTags(): void id name sku + description } } } @@ -117,9 +117,7 @@ public function testDispatchWithGetForCacheDebugHeadersAndCacheTags(): void $this->assertEquals('MISS', $this->response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $this->response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; - foreach (array_keys($actualCacheTags) as $key) { - $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); - } + $this->assertEquals($expectedCacheTags, $actualCacheTags); } /** From f41b4fb16e16d847f925baaa0878987157bb7279 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Tue, 16 Apr 2019 15:45:29 -0500 Subject: [PATCH 317/585] MC-15785: Overall storefront improvements --- .../tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php index 0bf9b37c75e12..1013404f42df1 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php @@ -102,7 +102,7 @@ class Shipping extends Form * * @var string */ - private $emailError = '#customer-email-error'; + private $emailError = '#checkout-customer-email-error'; /** * Get email error. From 417894cb136acba3405cff4350f459406fb1defe Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Tue, 16 Apr 2019 16:28:25 -0500 Subject: [PATCH 318/585] GraphQL-594: Test coverage for tag cache generation for category - fix product query --- .../GraphQl/Controller/GraphQlCacheControllerTest.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php index 822946cd7c36c..cf5b95e4d2690 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php @@ -97,7 +97,9 @@ public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForProducts() id name sku - description + description { + html + } } } } @@ -114,8 +116,8 @@ public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForProducts() $registry = $this->objectManager->get(\Magento\Framework\Registry::class); $registry->register('use_page_cache_plugin', true, true); $result->renderResult($response); - $this->assertEquals('MISS', $this->response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); - $actualCacheTags = explode(',', $this->response->getHeader('X-Magento-Tags')->getFieldValue()); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; $this->assertEquals($expectedCacheTags, $actualCacheTags); } @@ -169,7 +171,7 @@ public function testDispatchForCacheDebugHeadersAndCacheTagsForCategory(): void * @magentoDataFixture Magento/Catalog/_files/category_product.php * */ - public function testDispatchForCacheHeadersAndCacheTagsForCategoryWtihProducts(): void + public function testDispatchForCacheHeadersAndCacheTagsForCategoryWithProducts(): void { /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); @@ -231,4 +233,3 @@ public function testDispatchForCacheHeadersAndCacheTagsForCategoryWtihProducts() $this->assertEquals($expectedCacheTags, $actualCacheTags); } } - From caa0618618f8171e5ca780aeeb5d908b44325428 Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Tue, 16 Apr 2019 16:46:48 -0500 Subject: [PATCH 319/585] 230: Implement cache tag generation for GraphQL queries - Refactored Integration test to GraphQlCacheModule --- .../CategoriesWithProductsDispatchTest.php | 143 +++++++++++++++ .../Catalog/CategoryDispatchTest.php | 112 ++++++++++++ .../DeepNestedCategoriesAndProductsTest.php | 168 ++++++++++++++++++ 3 files changed, 423 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php new file mode 100644 index 0000000000000..385fb4c66d1d7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php @@ -0,0 +1,143 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller\Catalog; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\App\Request\Http; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Tests cache debug headers and cache tag validation for a simple product query + * + * @magentoAppArea graphql + * @magentoDbIsolation disabled + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class CategoriesWithProductsDispatchTest extends \Magento\TestFramework\Indexer\TestCase +{ + const CONTENT_TYPE = 'application/json'; + + /** @var \Magento\Framework\ObjectManagerInterface */ + private $objectManager; + + /** @var GraphQl */ + private $graphql; + + /** @var SerializerInterface */ + private $jsonSerializer; + + /** @var MetadataPool */ + private $metadataPool; + + /** @var Http */ + private $request; + + /** @var \Magento\Framework\App\Response\Http */ + private $response; + + /** + * @inheritdoc + */ + public static function setUpBeforeClass() + { + $db = Bootstrap::getInstance()->getBootstrap() + ->getApplication() + ->getDbInstance(); + if (!$db->isDbDumpExists()) { + throw new \LogicException('DB dump does not exist.'); + } + $db->restoreFromDbDump(); + + parent::setUpBeforeClass(); + } + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); + $this->metadataPool = $this->objectManager->get(MetadataPool::class); + $this->request = $this->objectManager->get(Http::class); + } + + /** + * Test cache tags and debug header for category with products querying for products and category + * + * @magentoCache all enabled + * @magentoDataFixture Magento/Catalog/_files/category_product.php + * + */ + public function testDispatchForCacheHeadersAndCacheTagsForCategoryWtihProducts(): void + { + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + /** @var ProductInterface $product */ + $product= $productRepository->get('simple333'); + $categoryId ='333'; + $query + = <<<QUERY +query GetCategoryWithProducts(\$id: Int!, \$pageSize: Int!, \$currentPage: Int!) { + category(id: \$id) { + id + description + name + product_count + products( + pageSize: \$pageSize, + currentPage: \$currentPage) { + items { + id + name + attribute_set_id + url_key + sku + type_id + updated_at + url_key + url_path + } + total_count + } + } + } +QUERY; + $variables =[ + 'id' => 333, + 'pageSize'=> 10, + 'currentPage' => 1 + ]; + $queryParams = [ + 'query' => $query, + 'variables' => json_encode($variables), + 'operationName' => 'GetCategoryWithProducts' + ]; + + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setParams($queryParams); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $product->getId(),'FPC']; + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + } +} + diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php new file mode 100644 index 0000000000000..1f51f5b129605 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php @@ -0,0 +1,112 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller\Catalog; + +use Magento\Framework\App\Request\Http; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Tests cache debug headers and cache tag validation for a simple product query + * + * @magentoAppArea graphql + * @magentoDbIsolation disabled + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class CategoryDispatchTest extends \Magento\TestFramework\Indexer\TestCase +{ + const CONTENT_TYPE = 'application/json'; + + /** @var \Magento\Framework\ObjectManagerInterface */ + private $objectManager; + + /** @var GraphQl */ + private $graphql; + + /** @var SerializerInterface */ + private $jsonSerializer; + + /** @var MetadataPool */ + private $metadataPool; + + /** @var Http */ + private $request; + + /** @var \Magento\Framework\App\Response\Http */ + private $response; + + /** + * @inheritdoc + */ + public static function setUpBeforeClass() + { + $db = Bootstrap::getInstance()->getBootstrap() + ->getApplication() + ->getDbInstance(); + if (!$db->isDbDumpExists()) { + throw new \LogicException('DB dump does not exist.'); + } + $db->restoreFromDbDump(); + + parent::setUpBeforeClass(); + } + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); + $this->metadataPool = $this->objectManager->get(MetadataPool::class); + $this->request = $this->objectManager->get(Http::class); + } + + /** + * Test cache tags and debug header for category and querying only for category + * + * @magentoCache all enabled + * @magentoDataFixture Magento/Catalog/_files/category_product.php + * + */ + public function testDispatchForCacheDebugHeadersAndCacheTagsForCategory(): void + { + $categoryId ='333'; + $query + = <<<QUERY + { + category(id: $categoryId) { + id + name + url_key + description + product_count + } + } +QUERY; + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'FPC']; + foreach (array_keys($actualCacheTags) as $key) { + $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); + } + } +} + diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php new file mode 100644 index 0000000000000..c8c2893e7c4d2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php @@ -0,0 +1,168 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller\Catalog; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Framework\App\Request\Http; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; + +/** + * Tests cache debug headers and cache tag validation for a simple product query + * + * @magentoAppArea graphql + * @magentoDbIsolation disabled + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class DeepNestedCategoriesAndProductsTest extends \Magento\TestFramework\Indexer\TestCase +{ + const CONTENT_TYPE = 'application/json'; + + /** @var \Magento\Framework\ObjectManagerInterface */ + private $objectManager; + + /** @var GraphQl */ + private $graphql; + + /** @var SerializerInterface */ + private $jsonSerializer; + + /** @var MetadataPool */ + private $metadataPool; + + /** @var Http */ + private $request; + + /** @var \Magento\Framework\App\Response\Http */ + private $response; + + /** + * @inheritdoc + */ + public static function setUpBeforeClass() + { + $db = Bootstrap::getInstance()->getBootstrap() + ->getApplication() + ->getDbInstance(); + if (!$db->isDbDumpExists()) { + throw new \LogicException('DB dump does not exist.'); + } + $db->restoreFromDbDump(); + + parent::setUpBeforeClass(); + } + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); + $this->metadataPool = $this->objectManager->get(MetadataPool::class); + $this->request = $this->objectManager->get(Http::class); + } + + /** + * Test cache tags and debug header for deep nested queries involving category and products + * + * @magentoCache all enabled + * @magentoDataFixture Magento/Catalog/_files/product_in_multiple_categories.php + * + */ + public function testDispatchForCacheHeadersOnDeepNestedQueries(): void + { + $categoryId ='333'; + $query + = <<<QUERY + { + category(id: $categoryId) { + products { + items { + attribute_set_id + country_of_manufacture + created_at + description { + html + } + gift_message_available + id + categories { + name + url_path + available_sort_by + level + products { + items { + name + id + } + } + } + } + } + } +} +QUERY; + /** @var CategoryRepositoryInterface $categoryRepository */ + $categoryRepository = ObjectManager::getInstance()->get(CategoryRepositoryInterface::class); + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + $categoryIds = []; + $category = $categoryRepository->get('333'); + + $productIdsFromCategory = $category->getProductCollection()->getAllIds(); + foreach ($productIdsFromCategory as $productId) { + $categoryIds = array_merge($categoryIds, $productRepository->getById($productId)->getCategoryIds()); + } + + $categoryIds = array_merge($categoryIds, ['333']); + foreach ($categoryIds as $categoryId) { + $category = $categoryRepository->get($categoryId); + $productIdsFromCategory= array_merge( + $productIdsFromCategory, + $category->getProductCollection()->getAllIds() + ); + } + + $uniqueProductIds = array_unique($productIdsFromCategory); + $uniqueCategoryIds = array_unique($categoryIds); + $expectedCacheTags = ['cat_c', 'cat_p', 'FPC']; + foreach ($uniqueProductIds as $productId) { + $expectedCacheTags = array_merge($expectedCacheTags, ['cat_p_'.$productId]); + } + foreach ($uniqueCategoryIds as $categoryId) { + $expectedCacheTags = array_merge($expectedCacheTags, ['cat_c_'.$categoryId]); + } + + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $this->assertEmpty( + array_merge( + array_diff($expectedCacheTags, $actualCacheTags), + array_diff($actualCacheTags, $expectedCacheTags) + ) + ); + } +} + From b67192ad4e211f9eaea156a4a71b5fb174fe3040 Mon Sep 17 00:00:00 2001 From: "Leandro F. L" <lfluvisotto@gmail.com> Date: Tue, 16 Apr 2019 18:53:41 -0300 Subject: [PATCH 320/585] Remove all marketing get params on Varnish to minimize the cache objects (added bronto parameter) --- app/code/Magento/PageCache/etc/varnish4.vcl | 4 ++-- app/code/Magento/PageCache/etc/varnish5.vcl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/PageCache/etc/varnish4.vcl b/app/code/Magento/PageCache/etc/varnish4.vcl index 198b2f6796e69..801e6cb475d8a 100644 --- a/app/code/Magento/PageCache/etc/varnish4.vcl +++ b/app/code/Magento/PageCache/etc/varnish4.vcl @@ -92,8 +92,8 @@ sub vcl_recv { } # Remove all marketing get parameters to minimize the cache objects - if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=") { - set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); + if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=") { + set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); set req.url = regsub(req.url, "[?|&]+$", ""); } diff --git a/app/code/Magento/PageCache/etc/varnish5.vcl b/app/code/Magento/PageCache/etc/varnish5.vcl index eac724ea7d0a5..76c5ffee5f14f 100644 --- a/app/code/Magento/PageCache/etc/varnish5.vcl +++ b/app/code/Magento/PageCache/etc/varnish5.vcl @@ -93,8 +93,8 @@ sub vcl_recv { } # Remove all marketing get parameters to minimize the cache objects - if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=") { - set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); + if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=") { + set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); set req.url = regsub(req.url, "[?|&]+$", ""); } From 53ce80a50b3113037b8de78a8fb80c3590da8d0b Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Tue, 16 Apr 2019 16:54:56 -0500 Subject: [PATCH 321/585] Issue-230: Implement cache tag generation for GraphQL queries - add tests for caching cms blocks --- .../Model/Resolver/Block/IdentityResolver.php | 1 + .../GraphQl/PageCache/Cms/BlockCacheTest.php | 152 ++++++++++++++++++ .../Controller/Cms/BlockCacheTest.php | 120 ++++++++++++++ 3 files changed, 273 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php index a393f6ab04f42..5f18bce21f378 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php @@ -28,6 +28,7 @@ public function getIdentifiers(array $resolvedData): array foreach ($items as $item) { if (is_array($item) && !empty($item[BlockInterface::BLOCK_ID])) { $ids[] = $item[BlockInterface::BLOCK_ID]; + $ids[] = $item[BlockInterface::IDENTIFIER]; } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php new file mode 100644 index 0000000000000..54a96ef2d9493 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php @@ -0,0 +1,152 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\PageCache\Cms; + +use Magento\Cms\Model\Block; +use Magento\Cms\Model\BlockRepository; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test the caching works properly for CMS Blocks + */ +class BlockCacheTest extends GraphQlAbstract +{ + /** + * Test that X-Magento-Tags are correct + * + * @magentoApiDataFixture Magento/Cms/_files/block.php + */ + public function testCacheTagsHaveExpectedValue() + { + $blockIdentifier = 'fixture_block'; + $blockRepository = Bootstrap::getObjectManager()->get(BlockRepository::class); + $block = $blockRepository->getById($blockIdentifier); + $blockId = $block->getId(); + $query = $this->getBlockQuery([$blockIdentifier]); + + //cache-debug should be a MISS on first request + $responseHeaders = $this->graphQlQueryForHttpHeaders($query); + preg_match('/X-Magento-Tags: (.*)/', $responseHeaders, $matches); + $this->assertNotEmpty($matches[1]); + $actualTags = explode(',', $matches[1]); + $expectedTags = ["cms_b_{$blockIdentifier}", "cms_b_{$blockId}"]; + foreach ($expectedTags as $expectedTag) { + $this->assertContains($expectedTag, $actualTags); + } + } + + /** + * Test the second request for the same block will return a cached result + * + * @magentoApiDataFixture Magento/Cms/_files/block.php + */ + public function testCacheIsUsedOnSecondRequest() + { + $blockIdentifier = 'fixture_block'; + $query = $this->getBlockQuery([$blockIdentifier]); + + //cache-debug should be a MISS on first request + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); + + //cache-debug should be a HIT on second request + $responseHitHeaders = $this->graphQlQueryForHttpHeaders($query); + $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHitHeaders); + + //cached data should be correct + $blockQueryData = $this->graphQlQuery($query); + $blocks = $blockQueryData['cmsBlocks']['items']; + $this->assertArrayNotHasKey('errors', $blockQueryData); + $this->assertEquals($blockIdentifier, $blocks[0]['identifier']); + $this->assertEquals('CMS Block Title', $blocks[0]['title']); + } + + /** + * Test that cache is invalidated when block is updated + * + * @magentoApiDataFixture Magento/Cms/_files/blocks.php + * @magentoApiDataFixture Magento/Cms/_files/block.php + */ + public function testCacheIsInvalidatedOnBlockUpdate() + { + $fixtureBlockIdentifier = 'fixture_block'; + $enabledBlockIdentifier = 'enabled_block'; + $fixtureBlockQuery = $this->getBlockQuery([$fixtureBlockIdentifier]); + $enabledBlockQuery = $this->getBlockQuery([$enabledBlockIdentifier]); + + //cache-debug should be a MISS on first request + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($fixtureBlockQuery); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($enabledBlockQuery); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); + + //cache-debug should be a HIT on second request + $responseHitHeaders = $this->graphQlQueryForHttpHeaders($fixtureBlockQuery); + $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHitHeaders); + $responseHitHeaders = $this->graphQlQueryForHttpHeaders($enabledBlockQuery); + $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHitHeaders); + + $newBlockContent = 'New block content!!!'; + $this->updateBlockContent($fixtureBlockIdentifier, $newBlockContent); + + //cache-debug should be a MISS after update the block + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($fixtureBlockQuery); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); + $responseHitHeaders = $this->graphQlQueryForHttpHeaders($enabledBlockQuery); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHitHeaders); + + //updated block data should be correct + $blockQueryData = $this->graphQlQuery($fixtureBlockQuery); + $blocks = $blockQueryData['cmsBlocks']['items']; + $this->assertArrayNotHasKey('errors', $blockQueryData); + $this->assertEquals($fixtureBlockIdentifier, $blocks[0]['identifier']); + $this->assertEquals('CMS Block Title', $blocks[0]['title']); + $this->assertEquals($newBlockContent, $blocks[0]['content']); + } + + /** + * Update the content of a CMS block + * + * @param $identifier + * @param $newContent + * @return Block + */ + private function updateBlockContent($identifier, $newContent): Block + { + $blockRepository = Bootstrap::getObjectManager()->get(BlockRepository::class); + $block = $blockRepository->getById($identifier); + $block->setContent($newContent); + $blockRepository->save($block); + + return $block; + } + + /** + * Get cmsBlocks query + * + * @param array $identifiers + * @return string + */ + private function getBlockQuery(array $identifiers): string + { + $identifiersString = implode(',', $identifiers); + $query = <<<QUERY + { + cmsBlocks(identifiers: ["$identifiersString"]) { + items { + title + identifier + content + } + } + } +QUERY; + return $query; + } +} diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php new file mode 100644 index 0000000000000..fe90a42c9f7c6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php @@ -0,0 +1,120 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller\Cms; + +use Magento\Cms\Model\BlockRepository; +use Magento\Framework\App\Request\Http; +use Magento\GraphQl\Controller\GraphQl; +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Test caching works for CMS blocks + * + * @magentoAppArea graphql + * @magentoDbIsolation disabled + */ +class BlockCacheTest extends \Magento\TestFramework\Indexer\TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var GraphQl + */ + private $graphqlController; + + /** + * @var Http + */ + private $request; + + /** + * @inheritdoc + */ + public static function setUpBeforeClass() + { + $db = Bootstrap::getInstance()->getBootstrap() + ->getApplication() + ->getDbInstance(); + if (!$db->isDbDumpExists()) { + throw new \LogicException('DB dump does not exist.'); + } + $db->restoreFromDbDump(); + + parent::setUpBeforeClass(); + } + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->request = $this->objectManager->create(Http::class); + $this->enableFullPageCache(); + } + + /** + * Test that the correct cache tags get added to request for cmsBlocks + * + * @magentoDataFixture Magento/Cms/_files/block.php + */ + public function testCmsBlocksRequestHasCorrectTags(): void + { + $blockIdentifier = 'fixture_block'; + $blockRepository = $this->objectManager->get(BlockRepository::class); + $block = $blockRepository->getById($blockIdentifier); + + $query + = <<<QUERY + { + cmsBlocks(identifiers: ["$blockIdentifier"]) { + items { + title + identifier + content + } + } +} +QUERY; + + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphqlController->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cms_b', 'cms_b_' . $block->getId(), 'cms_b_' . $block->getIdentifier(), 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + foreach ($expectedCacheTags as $expectedCacheTag) { + $this->assertContains($expectedCacheTag, $actualCacheTags); + } + } + + /** + * Enable full page cache so plugins are called + */ + private function enableFullPageCache() + { + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); + + /** @var \Magento\Framework\App\Cache\StateInterface $cacheState */ + $cacheState = $this->objectManager->get(\Magento\Framework\App\Cache\StateInterface::class); + $cacheState->setEnabled(\Magento\PageCache\Model\Cache\Type::TYPE_IDENTIFIER, true); + } +} From 05660302d304ac695c407aef19fe532a64aa5155 Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Tue, 16 Apr 2019 16:59:20 -0500 Subject: [PATCH 322/585] 596: Category with Products with...(deep nesting) (Integration Test for Tag Cache Generation) - Added integration test and refactored to new structure --- .../Controller/GraphQlCacheControllerTest.php | 328 ------------------ .../CategoriesWithProductsDispatchTest.php | 2 +- .../Catalog/CategoryDispatchTest.php | 3 +- .../DeepNestedCategoriesAndProductsTest.php | 2 +- .../Catalog/ProductsDispatchTest.php | 122 +++++++ 5 files changed, 126 insertions(+), 331 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php deleted file mode 100644 index f0450aa0369d5..0000000000000 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlCacheControllerTest.php +++ /dev/null @@ -1,328 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQl\Controller; - -use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\App\Request\Http; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Serialize\SerializerInterface; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\ObjectManager; -use Magento\Catalog\Api\CategoryRepositoryInterface; - -/** - * Tests cache debug headers and cache tag validation for a simple product query - * - * @magentoAppArea graphql - * @magentoDbIsolation disabled - * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class GraphQlCacheControllerTest extends \Magento\TestFramework\Indexer\TestCase -{ - const CONTENT_TYPE = 'application/json'; - - /** @var \Magento\Framework\ObjectManagerInterface */ - private $objectManager; - - /** @var GraphQl */ - private $graphql; - - /** @var SerializerInterface */ - private $jsonSerializer; - - /** @var MetadataPool */ - private $metadataPool; - - /** @var Http */ - private $request; - - /** @var \Magento\Framework\App\Response\Http */ - private $response; - - /** - * @inheritdoc - */ - public static function setUpBeforeClass() - { - $db = Bootstrap::getInstance()->getBootstrap() - ->getApplication() - ->getDbInstance(); - if (!$db->isDbDumpExists()) { - throw new \LogicException('DB dump does not exist.'); - } - $db->restoreFromDbDump(); - - parent::setUpBeforeClass(); - } - - /** - * @inheritdoc - */ - protected function setUp(): void - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); - $this->metadataPool = $this->objectManager->get(MetadataPool::class); - $this->request = $this->objectManager->get(Http::class); - // $this->response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - } - - /** - * Test request is dispatched and response is checked for debug headers and cache tags - * - * @magentoCache all enabled - * @return void - */ - public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForProducts(): void - { - /** @var ProductRepositoryInterface $productRepository */ - $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); - - /** @var ProductInterface $product */ - $product = $productRepository->get('simple1'); - - $query - = <<<QUERY - { - products(filter: {sku: {eq: "simple1"}}) - { - items { - id - name - sku - description { - html - } - } - } - } -QUERY; - - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('GET'); - $this->request->setQueryValue('query', $query); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); - $result->renderResult($response); - $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); - $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); - $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; - $this->assertEquals($expectedCacheTags, $actualCacheTags); - } - - /** - * Test cache tags and debug header for category and querying only for category - * - * @magentoCache all enabled - * @magentoDataFixture Magento/Catalog/_files/category_product.php - * - */ - public function testDispatchForCacheDebugHeadersAndCacheTagsForCategory(): void - { - $categoryId ='333'; - $query - = <<<QUERY - { - category(id: $categoryId) { - id - name - url_key - description - product_count - } - } -QUERY; - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('GET'); - $this->request->setQueryValue('query', $query); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); - $result->renderResult($response); - $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); - $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); - $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'FPC']; - foreach (array_keys($actualCacheTags) as $key) { - $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); - } - } - - /** - * Test cache tags and debug header for deep nested queries involving category and products - * - * @magentoCache all enabled - * @magentoDataFixture Magento/Catalog/_files/product_in_multiple_categories.php - * - */ - public function testDispatchForCacheHeadersOnDeepNestedQueries(): void - { - $categoryId ='333'; - $query - = <<<QUERY - { - category(id: $categoryId) { - products { - items { - attribute_set_id - country_of_manufacture - created_at - description { - html - } - gift_message_available - id - categories { - name - url_path - available_sort_by - level - products { - items { - name - id - } - } - } - } - } - } -} -QUERY; - /** @var CategoryRepositoryInterface $categoryRepository */ - $categoryRepository = ObjectManager::getInstance()->get(CategoryRepositoryInterface::class); - /** @var ProductRepositoryInterface $productRepository */ - $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); - $categoryIds = []; - $category = $categoryRepository->get('333'); - - $productIdsFromCategory = $category->getProductCollection()->getAllIds(); - foreach ($productIdsFromCategory as $productId) { - $categoryIds = array_merge($categoryIds, $productRepository->getById($productId)->getCategoryIds()); - } - - $categoryIds = array_merge($categoryIds, ['333']); - foreach ($categoryIds as $categoryId) { - $category = $categoryRepository->get($categoryId); - $productIdsFromCategory= array_merge( - $productIdsFromCategory, - $category->getProductCollection()->getAllIds() - ); - } - - $uniqueProductIds = array_unique($productIdsFromCategory); - $uniqueCategoryIds = array_unique($categoryIds); - $expectedCacheTags = ['cat_c', 'cat_p', 'FPC']; - foreach ($uniqueProductIds as $productId) { - $expectedCacheTags = array_merge($expectedCacheTags, ['cat_p_'.$productId]); - } - foreach ($uniqueCategoryIds as $categoryId) { - $expectedCacheTags = array_merge($expectedCacheTags, ['cat_c_'.$categoryId]); - } - - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('GET'); - $this->request->setQueryValue('query', $query); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); - $result->renderResult($response); - $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); - $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); - $this->assertEmpty( - array_merge( - array_diff($expectedCacheTags, $actualCacheTags), - array_diff($actualCacheTags, $expectedCacheTags) - ) - ); - } - - /** - * Test cache tags and debug header for category with products querying for products and category - * - * @magentoCache all enabled - * @magentoDataFixture Magento/Catalog/_files/category_product.php - * - */ - public function testDispatchForCacheHeadersAndCacheTagsForCategoryWithProducts(): void - { - /** @var ProductRepositoryInterface $productRepository */ - $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); - /** @var ProductInterface $product */ - $product= $productRepository->get('simple333'); - $categoryId ='333'; - $query - = <<<QUERY -query GetCategoryWithProducts(\$id: Int!, \$pageSize: Int!, \$currentPage: Int!) { - category(id: \$id) { - id - description - name - product_count - products( - pageSize: \$pageSize, - currentPage: \$currentPage) { - items { - id - name - attribute_set_id - url_key - sku - type_id - updated_at - url_key - url_path - } - total_count - } - } - } -QUERY; - $variables =[ - 'id' => 333, - 'pageSize'=> 10, - 'currentPage' => 1 - ]; - $queryParams = [ - 'query' => $query, - 'variables' => json_encode($variables), - 'operationName' => 'GetCategoryWithProducts' - ]; - - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('GET'); - $this->request->setParams($queryParams); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); - $result->renderResult($response); - $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); - $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $product->getId(),'FPC']; - $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); - $this->assertEquals($expectedCacheTags, $actualCacheTags); - } -} diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php index 385fb4c66d1d7..ed8809d354406 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php @@ -15,7 +15,7 @@ use Magento\TestFramework\Helper\Bootstrap; /** - * Tests cache debug headers and cache tag validation for a simple product query + * Tests cache debug headers and cache tag validation for a category with product query * * @magentoAppArea graphql * @magentoDbIsolation disabled diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php index 1f51f5b129605..454bbabc1b7ec 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php @@ -13,7 +13,7 @@ use Magento\TestFramework\Helper\Bootstrap; /** - * Tests cache debug headers and cache tag validation for a simple product query + * Tests cache debug headers and cache tag validation for a simple category query * * @magentoAppArea graphql * @magentoDbIsolation disabled @@ -100,6 +100,7 @@ public function testDispatchForCacheDebugHeadersAndCacheTagsForCategory(): void $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); /** @var $registry \Magento\Framework\Registry */ $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); $result->renderResult($response); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php index c8c2893e7c4d2..082c8815a7376 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php @@ -16,7 +16,7 @@ use Magento\TestFramework\ObjectManager; /** - * Tests cache debug headers and cache tag validation for a simple product query + * Tests cache debug headers and cache tag validation for a deep nested category and product query * * @magentoAppArea graphql * @magentoDbIsolation disabled diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php new file mode 100644 index 0000000000000..b8eb471956914 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php @@ -0,0 +1,122 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller\Catalog; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\App\Request\Http; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Tests cache debug headers and cache tag validation for a simple product query + * + * @magentoAppArea graphql + * @magentoDbIsolation disabled + * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ProductsDispatchTest extends \Magento\TestFramework\Indexer\TestCase +{ + const CONTENT_TYPE = 'application/json'; + + /** @var \Magento\Framework\ObjectManagerInterface */ + private $objectManager; + + /** @var GraphQl */ + private $graphql; + + /** @var SerializerInterface */ + private $jsonSerializer; + + /** @var MetadataPool */ + private $metadataPool; + + /** @var Http */ + private $request; + + /** @var \Magento\Framework\App\Response\Http */ + private $response; + + /** + * @inheritdoc + */ + public static function setUpBeforeClass() + { + $db = Bootstrap::getInstance()->getBootstrap() + ->getApplication() + ->getDbInstance(); + if (!$db->isDbDumpExists()) { + throw new \LogicException('DB dump does not exist.'); + } + $db->restoreFromDbDump(); + + parent::setUpBeforeClass(); + } + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); + $this->metadataPool = $this->objectManager->get(MetadataPool::class); + $this->request = $this->objectManager->get(Http::class); + } + + /** + * Test request is dispatched and response is checked for debug headers and cache tags + * + * @magentoCache all enabled + * @return void + */ + public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForProducts(): void + { + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + + /** @var ProductInterface $product */ + $product = $productRepository->get('simple1'); + + $query + = <<<QUERY + { + products(filter: {sku: {eq: "simple1"}}) + { + items { + id + name + sku + description { + html + } + } + } + } +QUERY; + + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; + $this->assertEquals($expectedCacheTags, $actualCacheTags); + } +} + From 862937aad682ff19065c9cb1c392eaaa6bd5f201 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Tue, 16 Apr 2019 17:02:36 -0500 Subject: [PATCH 323/585] Issue-230: Implement cache tag generation for GraphQL queries - Skip api functional tests due to cicd limitation --- .../Magento/GraphQl/PageCache/Cms/BlockCacheTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php index 54a96ef2d9493..aed568b0d5d7c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php @@ -17,6 +17,16 @@ */ class BlockCacheTest extends GraphQlAbstract { + /** + * @inheritdoc + */ + protected function setUp() + { + $this->markTestSkipped( + 'This test will stay skipped until DEVOPS-4924 is resolved' + ); + } + /** * Test that X-Magento-Tags are correct * From a87e52e2731c9d61ab46f4a55bcb85bd66eeafce Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Tue, 16 Apr 2019 17:14:07 -0500 Subject: [PATCH 324/585] Issue-230: adding varnish - fixing currency validator and processor for default, non specific and specific cached or non cached --- app/code/Magento/Directory/i18n/en_US.csv | 1 + .../HttpHeaderProcessor/CurrencyProcessor.php | 27 +++++++++++++------ .../CurrencyValidator.php | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Directory/i18n/en_US.csv b/app/code/Magento/Directory/i18n/en_US.csv index 3dcd2ceebf134..79a99eb97fec3 100644 --- a/app/code/Magento/Directory/i18n/en_US.csv +++ b/app/code/Magento/Directory/i18n/en_US.csv @@ -52,3 +52,4 @@ Service,Service "The """%1"" is not allowed as base currency for your subscription plan.","The """%1"" is not allowed as base currency for your subscription plan." "An invalid base currency has been entered.","An invalid base currency has been entered." "Currency rates can't be retrieved.","Currency rates can't be retrieved." +"Currency not allowed for store %1","Currency not allowed for store %1" \ No newline at end of file diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php index 7aa5f032ad4d1..bcff22467b900 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php @@ -65,24 +65,35 @@ public function __construct( public function processHeaderValue(string $headerValue) : void { try { - /** @var \Magento\Store\Model\Store $defaultStore */ - $defaultStore = $this->storeManager->getWebsite()->getDefaultStore(); - /** @var \Magento\Store\Model\Store $currentStore */ - $currentStore = $this->storeManager->getStore(); - if (!empty($headerValue)) { $headerCurrency = strtoupper(ltrim(rtrim($headerValue))); - if (in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes())) { + /** @var \Magento\Store\Model\Store $currentStore */ + $currentStore = $this->storeManager->getStore(); + if (in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes(true))) { $currentStore->setCurrentCurrencyCode($headerCurrency); + } else { + /** @var \Magento\Store\Model\Store $store */ + $store = $this->storeManager->getStore() ?? $this->storeManager->getDefaultStoreView(); + //skip store not found exception as it will be handled in graphql validation + $this->logger->warning(__('Currency not allowed for store %1', [$store->getCode()])); + $this->httpContext->setValue( + HttpContext::CONTEXT_CURRENCY, + $headerCurrency, + $store->getCurrentCurrency()->getCode() + ); } } else { if ($this->session->getCurrencyCode()) { + /** @var \Magento\Store\Model\Store $currentStore */ + $currentStore = $this->storeManager->getStore() ?? $this->storeManager->getDefaultStoreView(); $currentStore->setCurrentCurrencyCode($this->session->getCurrencyCode()); } else { + /** @var \Magento\Store\Model\Store $store */ + $store = $this->storeManager->getStore() ?? $this->storeManager->getDefaultStoreView(); $this->httpContext->setValue( HttpContext::CONTEXT_CURRENCY, - $defaultStore->getCurrentCurrencyCode(), - $defaultStore->getDefaultCurrencyCode() + $store->getCurrentCurrency()->getCode(), + $store->getCurrentCurrency()->getCode() ); } } diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php index 7ecff5d1f3f66..6c0d4ec2e7be6 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php @@ -46,7 +46,7 @@ public function validate(HttpRequestInterface $request): void $headerCurrency = strtoupper(ltrim(rtrim($headerValue))); /** @var \Magento\Store\Model\Store $currentStore */ $currentStore = $this->storeManager->getStore(); - if (!in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes())) { + if (!in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes(true))) { throw new GraphQlInputException( __('Currency not allowed for store %1', [$currentStore->getCode()]) ); From 1dec67693b7244953e544623f06d4653cc7fdec4 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Tue, 16 Apr 2019 17:22:32 -0500 Subject: [PATCH 325/585] Issue-230: adding varnish - fixing default currency --- .../Controller/HttpHeaderProcessor/CurrencyProcessor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php index bcff22467b900..b076b6fe9e768 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpHeaderProcessor/CurrencyProcessor.php @@ -79,7 +79,7 @@ public function processHeaderValue(string $headerValue) : void $this->httpContext->setValue( HttpContext::CONTEXT_CURRENCY, $headerCurrency, - $store->getCurrentCurrency()->getCode() + $store->getDefaultCurrency()->getCode() ); } } else { @@ -93,7 +93,7 @@ public function processHeaderValue(string $headerValue) : void $this->httpContext->setValue( HttpContext::CONTEXT_CURRENCY, $store->getCurrentCurrency()->getCode(), - $store->getCurrentCurrency()->getCode() + $store->getDefaultCurrency()->getCode() ); } } From 924dac8485a1072c92de99261472055bd79fd790 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Tue, 16 Apr 2019 17:28:52 -0500 Subject: [PATCH 326/585] Issue-230: adding varnish - adding currency api test - fixing static --- .../Catalog/ProductInMultipleStoresTest.php | 1 - .../GraphQl/PageCache/CacheTagTest.php | 1 - .../ProductInMultipleStoresCacheTest.php | 240 ++++++++++++++++++ 3 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php index a63d417eaef13..d49eef8a887e7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php @@ -15,7 +15,6 @@ */ class ProductInMultipleStoresTest extends GraphQlAbstract { - /** * Test a product from a specific and a default store * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index 59cc83d6a5d6d..cbdd1ebc13bc2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -44,7 +44,6 @@ public function testCacheTagsAndCacheDebugHeaderFromResponse() } QUERY; - /** cache-debug should be a MISS when product is queried for first time */ $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php new file mode 100644 index 0000000000000..916a25ea5acda --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php @@ -0,0 +1,240 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\PageCache; + +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * This test considers FPC caching but it can't check the headers since we don't guarantee that test if in dev mode. + * + * @magentoAppIsolation enabled + */ +class ProductInMultipleStoresCacheTest extends GraphQlAbstract +{ + /** + * Test a non existing or non allowed currency + * + * @magentoApiDataFixture Magento/Store/_files/second_website_with_second_currency.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testProductFromSpecificAndDefaultStoreWithMultiCurrencyNotAllowed() + { + $productSku = 'simple'; + + $query = <<<QUERY +{ + products(filter: {sku: {eq: "{$productSku}"}}) + { + items { + attribute_set_id + created_at + id + name + price { + minimalPrice { + amount { + value + currency + } + } + } + sku + type_id + updated_at + ... on PhysicalProductInterface { + weight + } + } + } +} +QUERY; + + $storeCodeFromFixture = 'fixture_second_store'; + + //test non existing currency + $headerMap = ['Store' => 'default', 'Content-Currency' => 'someNonExistentCurrency']; + $this->expectExceptionMessage('Currency someNonExistentCurrency not allowed for store default'); + $this->graphQlQuery($query, [], '', $headerMap); + + //test not allowed existing currency + $headerMap = ['Store' => $storeCodeFromFixture, 'Content-Currency' => 'CAD']; + $this->expectExceptionMessage('Currency not allowed for store ' . $storeCodeFromFixture); + $this->graphQlQuery($query, [], '', $headerMap); + } + + /** + * Test a product from a custom and default store, with cache with repeating queries asserting different results. + * + * @magentoApiDataFixture Magento/Store/_files/second_website_with_second_currency.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testProductFromSpecificAndDefaultStoreWithMultiCurrency() + { + $productSku = 'simple'; + + $query = <<<QUERY +{ + products(filter: {sku: {eq: "{$productSku}"}}) + { + items { + attribute_set_id + created_at + id + name + price { + minimalPrice { + amount { + value + currency + } + } + } + sku + type_id + updated_at + ... on PhysicalProductInterface { + weight + } + } + } +} +QUERY; + + /** @var \Magento\Store\Model\Store $store */ + $store = ObjectManager::getInstance()->get(\Magento\Store\Model\Store::class); + $storeCodeFromFixture = 'fixture_second_store'; + $storeId = $store->load($storeCodeFromFixture)->getStoreId(); + + $configResource = ObjectManager::getInstance()->get(\Magento\Config\Model\ResourceModel\Config::class); + + $configResource->saveConfig( + \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_DEFAULT, + 'EUR', + \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES, + $store->load($storeCodeFromFixture)->getWebsiteId() + ); + + // allow USD & EUR currency + $configResource->saveConfig( + \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_ALLOW, + 'EUR,USD', + \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES, + $store->load($storeCodeFromFixture)->getWebsiteId() + ); + + /** @var \Magento\Config\App\Config\Type\System $config */ + $config = ObjectManager::getInstance()->get(\Magento\Config\App\Config\Type\System::class); + // configuration cache clean is required to reload currency setting + $config->clean(); + + /** @var \Magento\Catalog\Model\Product $product */ + $product = ObjectManager::getInstance()->get(\Magento\Catalog\Model\Product::class); + $product->load($product->getIdBySku($productSku)); + + $website = ObjectManager::getInstance()->get(\Magento\Store\Model\Website::class); + /** @var $website \Magento\Store\Model\Website */ + $website->load('test', 'code'); + $product->setWebsiteIds([1, $website->getId()]); + + // change product name for custom store + $productNameInFixtureStore = 'Product\'s Name in Fixture Store'; + $product->setName($productNameInFixtureStore)->setStoreId($storeId)->save(); + + // test store header only, query is cached at this point in EUR + $headerMap = ['Store' => $storeCodeFromFixture]; + $response = $this->graphQlQuery($query, [], '', $headerMap); + $this->assertEquals( + $productNameInFixtureStore, + $response['products']['items'][0]['name'], + 'Product name in fixture store is invalid.' + ); + $this->assertEquals( + 'EUR', + $response['products']['items'][0]['price']['minimalPrice']['amount']['currency'], + 'Currency code EUR in fixture ' . $storeCodeFromFixture . ' is unexpected' + ); + + // test cached store + currency header in Euros + $headerMap = ['Store' => $storeCodeFromFixture, 'Content-Currency' => 'EUR']; + $response = $this->graphQlQuery($query, [], '', $headerMap); + $this->assertEquals( + $productNameInFixtureStore, + $response['products']['items'][0]['name'], + 'Product name in fixture ' . $storeCodeFromFixture . ' is invalid.' + ); + $this->assertEquals( + 'EUR', + $response['products']['items'][0]['price']['minimalPrice']['amount']['currency'], + 'Currency code EUR in fixture ' . $storeCodeFromFixture . ' is unexpected' + ); + + // test non cached store + currency header in USD + $headerMap = ['Store' => $storeCodeFromFixture, 'Content-Currency' => 'USD']; + $response = $this->graphQlQuery($query, [], '', $headerMap); + $this->assertEquals( + $productNameInFixtureStore, + $response['products']['items'][0]['name'], + 'Product name in fixture store is invalid.' + ); + $this->assertEquals( + 'USD', + $response['products']['items'][0]['price']['minimalPrice']['amount']['currency'], + 'Currency code USD in fixture ' . $storeCodeFromFixture . ' is unexpected' + ); + + // test non cached store + currency header in USD not cached + $headerMap = ['Store' => 'default', 'Content-Currency' => 'USD']; + $response = $this->graphQlQuery($query, [], '', $headerMap); + $this->assertEquals( + 'Simple Product', + $response['products']['items'][0]['name'], + 'Product name in fixture store is invalid.' + ); + $this->assertEquals( + 'USD', + $response['products']['items'][0]['price']['minimalPrice']['amount']['currency'], + 'Currency code USD in fixture store default is unexpected' + ); + + // test non cached store + currency header in USD not cached + $headerMap = ['Store' => 'default', 'Content-Currency' => 'EUR']; + $response = $this->graphQlQuery($query, [], '', $headerMap); + $this->assertEquals( + 'Simple Product', + $response['products']['items'][0]['name'], + 'Product name in fixture store is invalid.' + ); + $this->assertEquals( + 'EUR', + $response['products']['items'][0]['price']['minimalPrice']['amount']['currency'], + 'Currency code EUR in fixture store default is unexpected' + ); + + // test non cached store + currency header in USD cached + $headerMap = ['Store' => 'default']; + $response = $this->graphQlQuery($query, [], '', $headerMap); + $this->assertEquals( + 'Simple Product', + $response['products']['items'][0]['name'], + 'Product name in fixture store is invalid.' + ); + $this->assertEquals( + 'USD', + $response['products']['items'][0]['price']['minimalPrice']['amount']['currency'], + 'Currency code USD in fixture store default is unexpected' + ); + + // test cached response store + currency header with non existing currency, and no valid response, no cache + $headerMap = ['Store' => $storeCodeFromFixture, 'Content-Currency' => 'SOMECURRENCY']; + $this->expectExceptionMessage('Currency not allowed for store ' . $storeCodeFromFixture); + $this->graphQlQuery($query, [], '', $headerMap); + } +} From cd7935f4709b85b27d5e54de08fc3bcb10cb0717 Mon Sep 17 00:00:00 2001 From: avattam <> Date: Tue, 16 Apr 2019 17:54:29 -0500 Subject: [PATCH 327/585] GraphQL-598: CMS Page Integration Test for Tag Cache Generation --- .../testsuite/Magento/Cms/_files/pages.php | 9 ++ .../Controller/Cms/CmsPageCacheTest.php | 114 ++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php diff --git a/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php b/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php index a0b7b99a877a2..5edb2a79b148f 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php +++ b/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php @@ -11,15 +11,24 @@ ->setStores([0]) ->setIsActive(1) ->setContent('<h1>Cms Page 100 Title</h1>') + ->setContentHeading('<h2>Cms Page 100 Title</h2>') + ->setMetaTitle('Cms Meta title for page100') + ->setMetaKeywords('Cms Meta Keywords for page100') + ->setsetMetaDescription('Cms Meta Description for page100') ->setPageLayout('1column') ->save(); + $page = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Cms\Model\Page::class); $page->setTitle('Cms Page Design Blank') ->setIdentifier('page_design_blank') ->setStores([0]) ->setIsActive(1) ->setContent('<h1>Cms Page Design Blank Title</h1>') + ->setContentHeading('<h2>Cms Page Blank Title</h2>') + ->setMetaTitle('Cms Meta title for Blank page') + ->setMetaKeywords('Cms Meta Keywords for Blank page') + ->setsetMetaDescription('Cms Meta Description for Blank page') ->setPageLayout('1column') ->setCustomTheme('Magento/blank') ->save(); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php new file mode 100644 index 0000000000000..510df327df366 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller\Cms; + +use Magento\Cms\Model\GetPageByIdentifier; +use Magento\Framework\App\Request\Http; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\GraphQl\Controller\GraphQl; + +/** + * Test caching works for CMS page + * + * @magentoAppArea graphql + * @magentoDbIsolation disabled + */ +class CmsPageCacheTest extends \Magento\TestFramework\Indexer\TestCase +{ + const CONTENT_TYPE = 'application/json'; + + /** @var \Magento\Framework\ObjectManagerInterface */ + private $objectManager; + + /** @var GraphQl */ + private $graphql; + + /** @var SerializerInterface */ + private $jsonSerializer; + + /** @var MetadataPool */ + private $metadataPool; + + /** @var Http */ + private $request; + + /** @var \Magento\Framework\App\Response\Http */ + private $response; + + /** + * @inheritdoc + */ + public static function setUpBeforeClass() + { + $db = Bootstrap::getInstance()->getBootstrap() + ->getApplication() + ->getDbInstance(); + if (!$db->isDbDumpExists()) { + throw new \LogicException('DB dump does not exist.'); + } + $db->restoreFromDbDump(); + + parent::setUpBeforeClass(); + } + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); + $this->metadataPool = $this->objectManager->get(MetadataPool::class); + $this->request = $this->objectManager->get(Http::class); + } + /** + * Test cache tags and debug header for category and querying only cms page + * + * @magentoCache all enabled + * @magentoDataFixture Magento/Cms/_files/pages.php + */ + public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForCmsPage(): void + { + $cmsPage = $this->objectManager->get(GetPageByIdentifier::class)->execute('page100', 0); + $pageId = $cmsPage->getId(); + + $query = + <<<QUERY + { + cmsPage(id: $pageId) { + url_key + title + content + content_heading + page_layout + meta_title + meta_description + meta_keywords + } + } +QUERY; + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphql->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId , 'FPC']; + $this->assertEquals($expectedCacheTags, $actualCacheTags); + } +} From 4fb0be0e00ef6fca6e94689d3b176097e76b82fb Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Wed, 17 Apr 2019 11:33:07 +0530 Subject: [PATCH 328/585] Qty box visibility issue in whishlist when product is out of stock --- .../Wishlist/view/frontend/templates/item/column/cart.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml index 848c6a76393f8..c85f41bbf0775 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml @@ -18,7 +18,7 @@ $allowedQty = $block->getMinMaxQty(); <?php endforeach;?> <div class="box-tocart"> <fieldset class="fieldset"> - <?php if ($item->canHaveQty() && $product->isVisibleInSiteVisibility()): ?> + <?php if ($item->canHaveQty() && $product->isVisibleInSiteVisibility() && $product->isSaleable()): ?> <div class="field qty"> <label class="label" for="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]"><span><?= $block->escapeHtml(__('Qty')) ?></span></label> <div class="control"> From 9cd00fa8d80e085719d5a23491d9235e21da327f Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Tue, 16 Apr 2019 15:55:20 +0300 Subject: [PATCH 329/585] Fix static tests. --- .../NewRelicReporting/Plugin/CommandPlugin.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php b/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php index 065455e2a27c3..04ad3d0504d34 100644 --- a/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php +++ b/app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php @@ -3,11 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\NewRelicReporting\Plugin; use Magento\NewRelicReporting\Model\Config; use Magento\NewRelicReporting\Model\NewRelicWrapper; +use Symfony\Component\Console\Command\Command; +/** + * Describe NewRelic commands plugin. + */ class CommandPlugin { /** @@ -32,7 +37,14 @@ public function __construct( $this->newRelicWrapper = $newRelicWrapper; } - public function beforeRun(\Symfony\Component\Console\Command\Command $command, ...$args) + /** + * Set NewRelic Transaction name before running command. + * + * @param Command $command + * @param array $args + * @return array + */ + public function beforeRun(Command $command, ...$args) { $this->newRelicWrapper->setTransactionName( sprintf('CLI %s', $command->getName()) From e340978f1ef25bb39d5e03939ddad30b0c927eab Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Wed, 17 Apr 2019 11:37:02 +0300 Subject: [PATCH 330/585] Fix static test. --- .../Magento/Config/Model/Config/Backend/Admin/Usecustom.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php b/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php index d12569eebe5b2..f5d568f2f36be 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php +++ b/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php @@ -10,6 +10,8 @@ namespace Magento\Config\Model\Config\Backend\Admin; /** + * Process custom admin url during configuration value save process. + * * @api * @since 100.0.2 */ From 4d37719fcd446584aca5c1f77c56e24870c77d9f Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 16 Apr 2019 10:41:09 +0300 Subject: [PATCH 331/585] magento/magento2#21756: Static test fix. --- .../View/Asset/MergeStrategy/Direct.php | 19 +++++++++-------- .../Unit/Asset/MergeStrategy/DirectTest.php | 21 ++++++++++++------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php index e6ff58efe071a..315c3ee204864 100644 --- a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php +++ b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php @@ -6,6 +6,8 @@ namespace Magento\Framework\View\Asset\MergeStrategy; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Math\Random; use Magento\Framework\View\Asset; /** @@ -31,27 +33,27 @@ class Direct implements \Magento\Framework\View\Asset\MergeStrategyInterface private $cssUrlResolver; /** - * @var \Magento\Framework\Math\Random + * @var Random */ private $mathRandom; /** * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\Url\CssResolver $cssUrlResolver - * @param \Magento\Framework\Math\Random|null $mathRandom + * @param Random|null $mathRandom */ public function __construct( \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\Url\CssResolver $cssUrlResolver, - \Magento\Framework\Math\Random $mathRandom = null + Random $mathRandom = null ) { $this->filesystem = $filesystem; $this->cssUrlResolver = $cssUrlResolver; - $this->mathRandom = $mathRandom ?: \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Framework\Math\Random::class);; + $this->mathRandom = $mathRandom ?: ObjectManager::getInstance()->get(Random::class); } /** - * {@inheritdoc} + * @inheritdoc */ public function merge(array $assetsToMerge, Asset\LocalInterface $resultAsset) { @@ -67,10 +69,9 @@ public function merge(array $assetsToMerge, Asset\LocalInterface $resultAsset) /** * Merge files together and modify content if needed * - * @param \Magento\Framework\View\Asset\MergeableInterface[] $assetsToMerge - * @param \Magento\ Framework\View\Asset\LocalInterface $resultAsset - * @return string - * @throws \Magento\Framework\Exception\LocalizedException + * @param array $assetsToMerge + * @param Asset\LocalInterface $resultAsset + * @return array|string */ private function composeMergedContent(array $assetsToMerge, Asset\LocalInterface $resultAsset) { diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php index 19b17b4b52596..c23f13745c79f 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php @@ -5,11 +5,13 @@ */ namespace Magento\Framework\View\Test\Unit\Asset\MergeStrategy; -use Magento\Framework\Filesystem\Directory\WriteInterface; -use \Magento\Framework\View\Asset\MergeStrategy\Direct; - use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem\Directory\WriteInterface; +use Magento\Framework\View\Asset\MergeStrategy\Direct; +/** + * Test for Magento\Framework\View\Asset\MergeStrategy\Direct. + */ class DirectTest extends \PHPUnit\Framework\TestCase { /** @@ -69,7 +71,8 @@ public function testMergeNoAssets() ->method('getUniqueHash') ->willReturn($uniqId); $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, ''); - $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); + $this->tmpDir->expects($this->once())->method('renameFile') + ->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); $this->object->merge([], $this->resultAsset); } @@ -83,7 +86,8 @@ public function testMergeGeneric() ->method('getUniqueHash') ->willReturn($uniqId); $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, 'onetwo'); - $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); + $this->tmpDir->expects($this->once())->method('renameFile') + ->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); $this->object->merge($assets, $this->resultAsset); } @@ -92,7 +96,7 @@ public function testMergeCss() $uniqId = '_f929c374767e00712449660ea673f2f5'; $this->resultAsset->expects($this->exactly(3)) ->method('getPath') - ->will($this->returnValue('foo/result')); + ->willReturn('foo/result'); $this->resultAsset->expects($this->any())->method('getContentType')->will($this->returnValue('css')); $assets = $this->prepareAssetsToMerge(['one', 'two']); $this->cssUrlResolver->expects($this->exactly(2)) @@ -101,13 +105,14 @@ public function testMergeCss() $this->cssUrlResolver->expects($this->once()) ->method('aggregateImportDirectives') ->with('12') - ->will($this->returnValue('1020')); + ->willReturn('1020'); $this->mathRandomMock->expects($this->once()) ->method('getUniqueHash') ->willReturn($uniqId); $this->staticDir->expects($this->never())->method('writeFile'); $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, '1020'); - $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); + $this->tmpDir->expects($this->once())->method('renameFile') + ->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); $this->object->merge($assets, $this->resultAsset); } From 6beb286340905840df531d37f9cc18b71ab9aeb4 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 17 Apr 2019 12:30:17 +0300 Subject: [PATCH 332/585] magento/magento2#18336: Static test fix. --- lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php index fa58bdb5a5ebb..4d84be1ba4fc1 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\Config\Test\Unit; +/** + * Test for \Magento\Framework\Config\Dom class. + */ class DomTest extends \PHPUnit\Framework\TestCase { /** From 7ba832e243036b43ee15dab6f8a5183a31dba7ae Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Wed, 17 Apr 2019 13:19:17 +0300 Subject: [PATCH 333/585] MC-11945: Update Configurable Product --- .../Test/TestCase/UpdateConfigurableProductEntityTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/UpdateConfigurableProductEntityTest.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/UpdateConfigurableProductEntityTest.php index c7d66781738b7..bb88bc854f756 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/UpdateConfigurableProductEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/UpdateConfigurableProductEntityTest.php @@ -32,7 +32,6 @@ class UpdateConfigurableProductEntityTest extends Scenario { /* tags */ const MVP = 'yes'; - const TO_MAINTAIN = 'yes'; /* end tags */ /** From 0348d7da7806633ff031274c942dc25937eb6b1b Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 17 Apr 2019 14:24:58 +0300 Subject: [PATCH 334/585] graphQl-533: added additional data to payment methods, added tests --- .../Model/Resolver/SetPaymentMethodOnCart.php | 3 +- .../Magento/QuoteGraphQl/etc/schema.graphqls | 8 + .../SetOfflinePaymentMethodOnCartTest.php | 166 ++++++++++++++++++ .../Customer/SetPaymentMethodOnCartTest.php | 38 ---- .../SetOfflinePaymentMethodOnCartTest.php | 144 +++++++++++++++ .../Guest/SetPaymentMethodOnCartTest.php | 37 ---- 6 files changed, 320 insertions(+), 76 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php index 7d8933975779d..7b81964f111c6 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php @@ -70,13 +70,14 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $paymentMethodCode = $args['input']['payment_method']['code']; $poNumber = $args['input']['payment_method']['purchase_order_number'] ?? null; + $additionalData = $args['input']['payment_method']['additional_data'] ?? []; $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); $payment = $this->paymentFactory->create([ 'data' => [ PaymentInterface::KEY_METHOD => $paymentMethodCode, PaymentInterface::KEY_PO_NUMBER => $poNumber, - PaymentInterface::KEY_ADDITIONAL_DATA => [], + PaymentInterface::KEY_ADDITIONAL_DATA => $additionalData, ] ]); diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 9ec3492f64531..76bc51b007576 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -126,9 +126,13 @@ input SetPaymentMethodOnCartInput { input PaymentMethodInput { code: String! @doc(description:"Payment method code") + additional_data: PaymentMethodAdditionalDataInput @doc(description:"Additional payment data") purchase_order_number: String @doc(description:"Purchase order number") } +input PaymentMethodAdditionalDataInput { +} + type SetPaymentMethodOnCartOutput { cart: Cart! } @@ -222,9 +226,13 @@ type AvailablePaymentMethod { type SelectedPaymentMethod { code: String @doc(description: "The payment method code") + additional_data: SelectedPaymentMethodAdditionalData @doc(description: "Additional payment data") purchase_order_number: String @doc(description: "The purchase order number.") } +type SelectedPaymentMethodAdditionalData { +} + enum AdressTypeEnum { SHIPPING BILLING diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php new file mode 100644 index 0000000000000..36189db4094e9 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php @@ -0,0 +1,166 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Exception; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\OfflinePayments\Model\Purchaseorder; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for setting offline payment methods on cart by customer + */ +class SetOfflinePaymentMethodOnCartTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + */ + public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() + { + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $purchaseOrderNumber = '123456'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "$maskedQuoteId" + payment_method: { + code: "$methodCode" + purchase_order_number: "$purchaseOrderNumber" + } + }) { + cart { + selected_payment_method { + code + purchase_order_number + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + self::assertEquals($purchaseOrderNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * + * @expectedException Exception + * @expectedExceptionMessage Purchase order number is a required field. + */ + public function testSetPurchaseOrderPaymentMethodOnCartWithoutPurchaseOrderNumber() + { + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "$maskedQuoteId" + payment_method: { + code: "$methodCode" + } + }) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * + * @expectedException Exception + * @expectedExceptionMessage The requested Payment Method is not available. + */ + public function testSetDisabledPurchaseOrderPaymentMethodOnCart() + { + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $purchaseOrderNumber = '123456'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "$maskedQuoteId" + payment_method: { + code: "$methodCode" + purchase_order_number: "$purchaseOrderNumber" + } + }) { + cart { + selected_payment_method { + code + purchase_order_number + } + } + } +} +QUERY; + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @param string $username + * @param string $password + * @return array + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 8241debc8b09c..73feefe2b094b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -60,44 +60,6 @@ public function testSetPaymentOnCartWithSimpleProduct() self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); } - /** - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php - */ - public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() - { - $methodCode = Checkmo::PAYMENT_METHOD_CHECKMO_CODE; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - - $query = <<<QUERY -mutation { - setPaymentMethodOnCart(input: { - cart_id: "$maskedQuoteId" - payment_method: { - code: "$methodCode", - purchase_order_number: "123456" - } - }) { - cart { - selected_payment_method { - code - } - } - } -} -QUERY; - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - - self::assertArrayHasKey('setPaymentMethodOnCart', $response); - self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); - self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); - self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); - } - /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php new file mode 100644 index 0000000000000..bbc7fc9df839d --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php @@ -0,0 +1,144 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Exception; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\OfflinePayments\Model\Purchaseorder; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for setting offline payment methods on cart by guest + */ +class SetOfflinePaymentMethodOnCartTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + */ + public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() + { + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $purchaseOrderNumber = '123456'; + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "$maskedQuoteId" + payment_method: { + code: "$methodCode" + purchase_order_number: "$purchaseOrderNumber" + } + }) { + cart { + selected_payment_method { + code + purchase_order_number + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + self::assertEquals($purchaseOrderNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * + * @expectedException Exception + * @expectedExceptionMessage Purchase order number is a required field. + */ + public function testSetPurchaseOrderPaymentMethodOnCartWithoutPurchaseOrderNumber() + { + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "$maskedQuoteId" + payment_method: { + code: "$methodCode" + } + }) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * + * @expectedException Exception + * @expectedExceptionMessage The requested Payment Method is not available. + */ + public function testSetDisabledPurchaseOrderPaymentMethodOnCart() + { + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $purchaseOrderNumber = '123456'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "$maskedQuoteId" + payment_method: { + code: "$methodCode" + purchase_order_number: "$purchaseOrderNumber" + } + }) { + cart { + selected_payment_method { + code + purchase_order_number + } + } + } +} +QUERY; + $this->graphQlQuery($query); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php index 9dfb6b4c15a61..062dd2863b787 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php @@ -53,43 +53,6 @@ public function testSetPaymentOnCartWithSimpleProduct() self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); } - /** - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php - */ - public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() - { - $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - - $query = <<<QUERY -mutation { - setPaymentMethodOnCart(input: { - cart_id: "{$maskedQuoteId}", - payment_method: { - code: "{$methodCode}", - purchase_order_number: "123456" - } - }) { - cart { - selected_payment_method { - code - } - } - } -} -QUERY; - $response = $this->graphQlQuery($query); - - self::assertArrayHasKey('setPaymentMethodOnCart', $response); - self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); - self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); - self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); - } - /** * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php From 753f8230315337f2cc19cd2c9cc70f5d7dd2126d Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 17 Apr 2019 14:29:31 +0300 Subject: [PATCH 335/585] graphQl-533: removed redundant import --- .../Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php index 062dd2863b787..879d0fd917291 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php @@ -10,7 +10,6 @@ use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\OfflinePayments\Model\Cashondelivery; use Magento\OfflinePayments\Model\Checkmo; -use Magento\OfflinePayments\Model\Purchaseorder; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; From eea6126c03b6bb807569b73b7141d74257883729 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Wed, 17 Apr 2019 15:37:47 +0300 Subject: [PATCH 336/585] Fix static tests. --- .../Magento/Eav/Model/Entity/Collection/AbstractCollection.php | 1 - .../Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php | 1 + lib/internal/Magento/Framework/Data/Collection.php | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 247ee2d5423cd..51bb45c61a585 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -1719,5 +1719,4 @@ public function removeAllFieldsFromSelect() { return $this->removeAttributeToSelect(); } - } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php index 396d3b60e4f20..3ade17d90fe99 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Block\Adminhtml\Edit\Tab\View; use Magento\Customer\Controller\RegistryConstants; diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index 306737f4b5877..e0781a25de146 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Data; use Magento\Framework\Data\Collection\EntityFactoryInterface; @@ -401,6 +402,7 @@ public function addItem(\Magento\Framework\DataObject $item) if ($itemId !== null) { if (isset($this->_items[$itemId])) { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception( 'Item (' . get_class($item) . ') with the same ID "' . $item->getId() . '" already exists.' ); From 86c84a403d904b8fd503ed4738c694f61b64ccea Mon Sep 17 00:00:00 2001 From: Rafael Kassner <kassner@gmail.com> Date: Tue, 16 Apr 2019 13:10:09 +0200 Subject: [PATCH 337/585] Fix buttonId for credit memo button on admin invoice view --- app/code/Magento/Sales/Block/Adminhtml/Order/Invoice/View.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Invoice/View.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Invoice/View.php index fd6e5f403f2de..074aa99a5e791 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Invoice/View.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Invoice/View.php @@ -113,8 +113,8 @@ protected function _construct() $orderPayment->canRefund() && !$this->getInvoice()->getIsUsedForRefund() ) { $this->buttonList->add( - 'capture', - [ // capture? + 'credit-memo', + [ 'label' => __('Credit Memo'), 'class' => 'credit-memo', 'onclick' => 'setLocation(\'' . $this->getCreditMemoUrl() . '\')' From 4fcf7ed65838eb060e4a18f674d5e0498b02103b Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Wed, 17 Apr 2019 16:02:16 +0300 Subject: [PATCH 338/585] Added test coverage for Adding simple product to cart functionality --- .../Customer/AddSimpleProductToCartTest.php | 177 ++++++++++++++++++ .../Guest/AddSimpleProductToCartTest.php | 48 ++++- 2 files changed, 219 insertions(+), 6 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php new file mode 100644 index 0000000000000..0ff96c03e0990 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -0,0 +1,177 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\Framework\Exception\AuthenticationException; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test adding simple product to Cart + */ +class AddSimpleProductToCartTest extends GraphQlAbstract +{ + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testAddSimpleProductToCart() + { + $sku = 'simple_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); + self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + */ + public function testAddProductToNonExistentCart() + { + $sku = 'simple_product'; + $qty = 2; + $nonExistentMaskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($nonExistentMaskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a cart with ID \"$nonExistentMaskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testNonExistentProductToCart() + { + $sku = 'simple_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a product with SKU \"simple_product\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testAddSimpleProductToGuestCart() + { + $sku = 'simple_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testAddSimpleProductToAnotherCustomerCart() + { + $sku = 'simple_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + } + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + { + return <<<QUERY +mutation { + addSimpleProductsToCart(input: { + cart_id: "{$maskedQuoteId}", + cartItems: [ + { + data: { + qty: $qty + sku: "$sku" + } + } + ] + }) { + cart { + items { + id + qty + product { + sku + } + } + } + } +} +QUERY; + } + + /** + * Retrieve customer authorization headers + * + * @param string $username + * @param string $password + * @return array + * @throws AuthenticationException + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index 25221b628e7fb..f4345c9ab4826 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -31,14 +31,14 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/products.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php */ public function testAddSimpleProductToCart() { - $sku = 'simple'; + $sku = 'simple_product'; $qty = 2; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $sku, $qty); $response = $this->graphQlMutation($query); @@ -49,14 +49,14 @@ public function testAddSimpleProductToCart() } /** - * @magentoApiDataFixture Magento/Catalog/_files/products.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * * @expectedException \Exception * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ public function testAddProductToNonExistentCart() { - $sku = 'simple'; + $sku = 'simple_product'; $qty = 1; $maskedQuoteId = 'non_existent_masked_id'; @@ -64,6 +64,42 @@ public function testAddProductToNonExistentCart() $this->graphQlMutation($query); } + /** + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testNonExistentProductToCart() + { + $sku = 'simple_product'; + $qty = 1; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a product with SKU \"simple_product\"" + ); + + $this->graphQlMutation($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testAddSimpleProductToCustomerCart() + { + $sku = 'simple_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query); + } + /** * @param string $maskedQuoteId * @param string $sku From e2854aadc76f56d5ac21e2f8ab648c3f34e3a2af Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Wed, 17 Apr 2019 17:10:49 +0300 Subject: [PATCH 339/585] Added test coverage for Add virtual product to cart functionality --- .../Customer/AddVirtualProductToCartTest.php | 177 ++++++++++++++++++ .../Guest/AddVirtualProductToCartTest.php | 139 ++++++++++++++ .../Catalog/_files/virtual_product.php | 45 +++++ .../_files/virtual_product_rollback.php | 31 +++ 4 files changed, 392 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product_rollback.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php new file mode 100644 index 0000000000000..f2beef7aa93c8 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -0,0 +1,177 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\Framework\Exception\AuthenticationException; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test adding virtual product to Cart + */ +class AddVirtualProductToCartTest extends GraphQlAbstract +{ + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testAddVirtualProductToCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); + self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + */ + public function testAddVirtualToNonExistentCart() + { + $sku = 'virtual_product'; + $qty = 2; + $nonExistentMaskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($nonExistentMaskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a cart with ID \"$nonExistentMaskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testNonExistentProductToCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a product with SKU \"virtual_product\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testAddVirtualProductToGuestCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testAddVirtualProductToAnotherCustomerCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + } + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + { + return <<<QUERY +mutation { + addVirtualProductsToCart(input: { + cart_id: "{$maskedQuoteId}", + cartItems: [ + { + data: { + qty: $qty + sku: "$sku" + } + } + ] + }) { + cart { + items { + id + qty + product { + sku + } + } + } + } +} +QUERY; + } + + /** + * Retrieve customer authorization headers + * + * @param string $username + * @param string $password + * @return array + * @throws AuthenticationException + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php new file mode 100644 index 0000000000000..20d7ee031a044 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -0,0 +1,139 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Add virtual product to cart testcases + */ +class AddVirtualProductToCartTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testAddVirtualProductToCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $response = $this->graphQlMutation($query); + + self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); + self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + */ + public function testAddVirtualToNonExistentCart() + { + $sku = 'virtual_product'; + $qty = 1; + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a cart with ID \"non_existent_masked_id\"" + ); + + $this->graphQlMutation($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testNonExistentProductToCart() + { + $sku = 'virtual_product'; + $qty = 1; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a product with SKU \"virtual_product\"" + ); + + $this->graphQlMutation($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testAddVirtualProductToCustomerCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query); + } + + /** + * @param string $maskedQuoteId + * @param string $sku + * @param int $qty + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + { + return <<<QUERY +mutation { + addVirtualProductsToCart( + input: { + cart_id: "{$maskedQuoteId}" + cartItems: [ + { + data: { + qty: $qty + sku: "$sku" + } + } + ] + } + ) { + cart { + items { + qty + product { + sku + } + } + } + } +} +QUERY; + } +} diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product.php b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product.php new file mode 100644 index 0000000000000..e4472464e17ae --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\Data\ProductInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Framework\Api\DataObjectHelper; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var DataObjectHelper $dataObjectHelper */ +$dataObjectHelper = Bootstrap::getObjectManager()->get(DataObjectHelper::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +$product = $productFactory->create(); +$productData = [ + ProductInterface::TYPE_ID => Type::TYPE_VIRTUAL, + ProductInterface::ATTRIBUTE_SET_ID => 4, + ProductInterface::SKU => 'virtual_product', + ProductInterface::NAME => 'Virtual Product', + ProductInterface::PRICE => 10, + ProductInterface::VISIBILITY => Visibility::VISIBILITY_BOTH, + ProductInterface::STATUS => Status::STATUS_ENABLED, +]; +$dataObjectHelper->populateWithArray($product, $productData, ProductInterface::class); +/** Out of interface */ +$product + ->setWebsiteIds([1]) + ->setStockData([ + 'qty' => 85.5, + 'is_in_stock' => true, + 'manage_stock' => true, + 'is_qty_decimal' => true + ]); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product_rollback.php new file mode 100644 index 0000000000000..f8d329f574626 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product_rollback.php @@ -0,0 +1,31 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$currentArea = $registry->registry('isSecureArea'); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $productRepository->deleteById('virtual_product'); +} catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + /** + * Tests which are wrapped with MySQL transaction clear all data by transaction rollback. + */ +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', $currentArea); From 2ccf78b11ce40bba8bd02c9569207648aa53fe35 Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Wed, 17 Apr 2019 17:14:34 +0300 Subject: [PATCH 340/585] MC-5831: Apply cross border taxes, product with category --- .../app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.php b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.php index 0f163933d260c..40d3401a207a4 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.php @@ -37,7 +37,6 @@ class TaxWithCrossBorderTest extends Injectable { /* tags */ const MVP = 'yes'; - const STABLE = 'no'; /* end tags */ /** From d598262302bc6852cd05020c5013dd38281bfc03 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 17 Apr 2019 17:21:10 +0300 Subject: [PATCH 341/585] magento/magento2#19806: Web-Api test fix. --- .../Magento/Downloadable/Api/ProductRepositoryTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php index 4608b255459b6..d0cace993a24a 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php @@ -472,6 +472,10 @@ public function testUpdateDownloadableProductSamplesWithNewFile() 'title' => 'sample2_updated', 'sort_order' => 2, 'sample_type' => 'file', + 'sample_file_content' => [ + 'name' => 'sample2.jpg', + 'file_data' => base64_encode(file_get_contents($this->testImagePath)), + ], ]; $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"] = @@ -606,7 +610,7 @@ protected function deleteProductBySku($productSku) protected function saveProduct($product) { if (isset($product['custom_attributes'])) { - for ($i=0; $i<sizeof($product['custom_attributes']); $i++) { + for ($i = 0, $iMax = count($product['custom_attributes']); $i < $iMax; $i++) { if ($product['custom_attributes'][$i]['attribute_code'] == 'category_ids' && !is_array($product['custom_attributes'][$i]['value']) ) { From 6193247a12b63fd824c8d3f0dfed061fad3175bd Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Wed, 17 Apr 2019 09:27:09 -0500 Subject: [PATCH 342/585] MC-5588: When using MysqlMQ messages are always set to complete even if exception occurs - Fix static tests --- app/code/Magento/MysqlMq/Model/Driver/Queue.php | 2 ++ .../Framework/MessageQueue/_files/valid_queue_input.php | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/MysqlMq/Model/Driver/Queue.php b/app/code/Magento/MysqlMq/Model/Driver/Queue.php index cc9ab2bf30d6c..cbc2e951782f2 100644 --- a/app/code/Magento/MysqlMq/Model/Driver/Queue.php +++ b/app/code/Magento/MysqlMq/Model/Driver/Queue.php @@ -110,11 +110,13 @@ public function subscribe($callback) while (true) { while ($envelope = $this->dequeue()) { try { + // phpcs:ignore Magento2.Functions.DiscouragedFunction call_user_func($callback, $envelope); } catch (\Exception $e) { $this->reject($envelope); } } + // phpcs:ignore Magento2.Functions.DiscouragedFunction sleep($this->interval); } } diff --git a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php index e3d9a8a4eb197..46b3ba3414c8a 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php +++ b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php @@ -23,11 +23,11 @@ "name" => "publisher5.topic", "schema" => [ "schema_type" => "object", - "schema_value" => "Magento\\TestModuleMysqlMq\\Model\\DataObject" + "schema_value" => Magento\TestModuleMysqlMq\Model\DataObject::class ], "response_schema" => [ "schema_type" => "object", - "schema_value" => "Magento\\Customer\\Api\\Data\\CustomerInterface" + "schema_value" => \Magento\Customer\Api\Data\CustomerInterface::class ], "publisher" => "test-publisher-5" ] From cda62bff652d6d7fc10e2a5b332001aaeea036a7 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Wed, 17 Apr 2019 09:32:05 -0500 Subject: [PATCH 343/585] Issue-230: adding varnish - fixing static on tests --- app/code/Magento/GraphQl/Controller/GraphQl.php | 1 + .../Magento/TestFramework/TestCase/GraphQlAbstract.php | 2 +- .../testsuite/Magento/GraphQl/PageCache/CacheTagTest.php | 3 +++ .../Magento/Framework/GraphQl/Config/GraphQlReaderTest.php | 3 +++ .../Controller/Catalog/CategoriesWithProductsDispatchTest.php | 4 ---- .../GraphQlCache/Controller/Catalog/CategoryDispatchTest.php | 4 ---- .../Catalog/DeepNestedCategoriesAndProductsTest.php | 4 ---- .../GraphQlCache/Controller/Catalog/ProductsDispatchTest.php | 4 ---- 8 files changed, 8 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index ed66c92c3bfb4..f31492f8389f6 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -25,6 +25,7 @@ * Front controller for web API GraphQL area. * * @api + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class GraphQl implements FrontControllerInterface { diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php index 44ce9aeca8b69..f8aa950619264 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php @@ -92,7 +92,7 @@ public function graphQlQueryForHttpHeaders( string $operationName = '', array $headers = [] ) { - return $response = $this->getGraphQlClient()->getQueryResponseHeaders( + return $this->getGraphQlClient()->getQueryResponseHeaders( $query, $variables, $operationName, diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index cbdd1ebc13bc2..0a0ca960d5acd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -14,6 +14,9 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Class CacheTagTest + */ class CacheTagTest extends GraphQlAbstract { /** diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php index 61cbd556ea235..f6994931562c2 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php @@ -35,6 +35,9 @@ class GraphQlReaderTest extends \PHPUnit\Framework\TestCase /** @var SerializerInterface */ private $jsonSerializer; + /** + * @inheritdoc + */ protected function setUp() { $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php index ed8809d354406..c999c75307dd2 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php @@ -40,9 +40,6 @@ class CategoriesWithProductsDispatchTest extends \Magento\TestFramework\Indexer\ /** @var Http */ private $request; - /** @var \Magento\Framework\App\Response\Http */ - private $response; - /** * @inheritdoc */ @@ -140,4 +137,3 @@ public function testDispatchForCacheHeadersAndCacheTagsForCategoryWtihProducts() $this->assertEquals($expectedCacheTags, $actualCacheTags); } } - diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php index 454bbabc1b7ec..c6c523aff3d05 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php @@ -38,9 +38,6 @@ class CategoryDispatchTest extends \Magento\TestFramework\Indexer\TestCase /** @var Http */ private $request; - /** @var \Magento\Framework\App\Response\Http */ - private $response; - /** * @inheritdoc */ @@ -110,4 +107,3 @@ public function testDispatchForCacheDebugHeadersAndCacheTagsForCategory(): void } } } - diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php index 082c8815a7376..f6628be18ff5c 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php @@ -41,9 +41,6 @@ class DeepNestedCategoriesAndProductsTest extends \Magento\TestFramework\Indexer /** @var Http */ private $request; - /** @var \Magento\Framework\App\Response\Http */ - private $response; - /** * @inheritdoc */ @@ -165,4 +162,3 @@ public function testDispatchForCacheHeadersOnDeepNestedQueries(): void ); } } - diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php index b8eb471956914..53b8e2123063a 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php @@ -40,9 +40,6 @@ class ProductsDispatchTest extends \Magento\TestFramework\Indexer\TestCase /** @var Http */ private $request; - /** @var \Magento\Framework\App\Response\Http */ - private $response; - /** * @inheritdoc */ @@ -119,4 +116,3 @@ public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForProducts() $this->assertEquals($expectedCacheTags, $actualCacheTags); } } - From ed5dd4d3f47ea7534bb8fe1018b0d6718cb5f99a Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Tue, 16 Apr 2019 23:55:19 -0400 Subject: [PATCH 344/585] Add end to end checkout tests Tests checkout flow for customer and guest. --- .../Quote/Customer/EndToEndCheckoutTest.php | 623 ++++++++++++++++++ 1 file changed, 623 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php new file mode 100644 index 0000000000000..0354356d6927c --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php @@ -0,0 +1,623 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * End to checkout tests for customers and guests + */ +class EndToEndCheckoutTest extends GraphQlAbstract +{ + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutAsCustomer() + { + $email = 'e2e_1@example.com'; + + $this->graphQlMutation($this->buildCreateCustomerMutation($email)); + $authHeader = $this->createAuthHeader($email); + + $cartId = $this->createEmptyCart($authHeader); + $cart = $this->configureQuote($cartId, $authHeader); + + $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId), [], '', $authHeader); + $orderId = $placeOrderResult['placeOrder']['order']['order_id']; + $this->assertNotEmpty($orderId); + + $order = $this->getOrderFromHistory($orderId, $authHeader); + $this->assertEquals($cart['prices']['grand_total']['value'], $order['grand_total']); + //TODO: Make additional assertions when order properties are added + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutAsGuest() + { + $email = 'e2e_2@example.com'; + $cartId = $this->createEmptyCart(); + $this->graphQlMutation($this->buildSetGuestEmailOnCartMutation($cartId, $email)); + $this->configureQuote($cartId); + + $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId)); + $orderId = $placeOrderResult['placeOrder']['order']['order_id']; + + $this->assertNotEmpty($orderId); + } + + /** + * Configures cart with order placement requirements + * + * @param string $cartId + * @param array $headers + * @return array + */ + private function configureQuote(string $cartId, array $headers = []): array + { + $expectedTotal = 5.99; + $expectedQty = 1; + + $sku = $this->getSku($headers); + $addToCartResult = $this->graphQlMutation($this->buildAddToCartMutation($cartId, $expectedQty, $sku), [], '', $headers); + $cart = $addToCartResult['addSimpleProductsToCart']['cart']; + $this->assertGrandTotal($expectedTotal, $cart); + + $address = $this->setShippingAddress($cartId, $headers); + $shippingMethod = $this->extractFirstAvailableShippingMethod($address); + + $cart = $this->setShippingMethod($cartId, $shippingMethod, $address, $headers); + $expectedTotal += $shippingMethod['amount']; + $this->assertGrandTotal($expectedTotal, $cart); + $this->assertSelectedShippingMethod($shippingMethod, $cart); + + $setBillingAddressResult = $this->graphQlMutation($this->buildSetNewBillingAddressMutation($cartId), [], '', $headers); + $cart = $setBillingAddressResult['setBillingAddressOnCart']['cart']; + $paymentMethod = $this->extractFirstAvailablePaymentMethod($cart); + + $setPaymentResult = $this->graphQlMutation($this->buildSetPaymentMethodMutation($cartId, $paymentMethod), [], '', $headers); + $cart = $setPaymentResult['setPaymentMethodOnCart']['cart']; + $this->assertPaymentMethod($paymentMethod, $cart); + $this->assertGrandTotal($expectedTotal, $cart); + + return $cart; + } + + /** + * Generates customer authentication header for restricted requests + * + * @param string $email + * @return array + */ + private function createAuthHeader(string $email): array + { + $result = $this->graphQlMutation($this->buildLoginMutation($email)); + $token = $result['generateCustomerToken']['token']; + + return ['Authorization' => 'Bearer ' . $token]; + } + + /** + * Creates empty cart for customer or guest + * + * @param array $auth + * @return string + */ + private function createEmptyCart(array $auth = []): string + { + $query = <<<QUERY +mutation { + createEmptyCart +} +QUERY; + + $result = $this->graphQlMutation($query, [], '', $auth); + + return $result['createEmptyCart']; + } + + /** + * Get first SKU returned by catalog search + * + * @param array $auth + * @return string + */ + private function getSku(array $auth): string + { + $result = $this->graphQlQuery($this->buildProductSearchQuery('simple'), [], '', $auth); + $items = $result['products']['items']; + $item = current($items); + + return $item['sku']; + } + + /** + * Set cart shipping address + * + * @param string $cartId + * @param array $auth + * @return array + */ + private function setShippingAddress(string $cartId, array $auth): array + { + $result = $this->graphQlMutation($this->buildSetNewShippingAddressMutation($cartId), [], '', $auth); + $addresses = $result['setShippingAddressesOnCart']['cart']['shipping_addresses']; + + return current($addresses); + } + + /** + * Set cart shipping method + * + * @param string $cartId + * @param array $method + * @param array $address + * @param array $auth + * @return array + */ + private function setShippingMethod(string $cartId, array $method, array $address, array $auth): array + { + $result = $this->graphQlMutation($this->buildSetShippingMethodMutation($cartId, $method, $address), [], '', $auth); + + return $result['setShippingMethodsOnCart']['cart']; + } + + /** + * Get order from history by increment id + * + * @param string $orderId + * @param array $auth + * @return array + */ + private function getOrderFromHistory(string $orderId, array $auth): array + { + $query = <<<QUERY +{ + customerOrders { + items { + increment_id + grand_total + } + } +} +QUERY; + + $result = $this->graphQlQuery($query, [], '', $auth); + $orders = $result['customerOrders']['items']; + + foreach ($orders as $order) { + if ($order['increment_id'] === $orderId) { + return $order; + } + } + + $this->fail(sprintf('No order with increment_id: %s', $orderId)); + } + + /** + * Get first shipping method available from address + * @param array $address + * @return array + */ + private function extractFirstAvailableShippingMethod(array $address): array + { + $methods = $address['available_shipping_methods']; + + return current($methods); + } + + /** + * Get first payment method available from cart + * + * @param array $cart + * @return array + */ + private function extractFirstAvailablePaymentMethod(array $cart): array + { + $methods = $cart['available_payment_methods']; + + return current($methods); + } + + /** + * Assert cart grand total + * + * @param float $expected + * @param array $cart + */ + private function assertGrandTotal(float $expected, array $cart): void + { + $this->assertEquals($expected, $cart['prices']['grand_total']['value']); + } + + /** + * Assert cart payment method + * @param array $method + * @param array $cart + */ + private function assertPaymentMethod(array $method, array $cart): void + { + $this->assertEquals($method['code'], $cart['selected_payment_method']['code']); + } + + /** + * Assert cart shipping method + * + * @param array $expectedMethod + * @param array $cart + */ + private function assertSelectedShippingMethod(array $expectedMethod, array $cart): void + { + $address = current($cart['shipping_addresses']); + $selectedMethod = $address['selected_shipping_method']; + + $this->assertEquals($expectedMethod['carrier_code'], $selectedMethod['carrier_code']); + $this->assertEquals($expectedMethod['method_code'], $selectedMethod['method_code']); + } + + /** + * Build createCustomer mutation + * + * @param string $email + * @return string + */ + private function buildCreateCustomerMutation(string $email): string + { + return <<<QUERY +mutation { + createCustomer( + input: { + firstname: "endto" + lastname: "endtester" + email: "{$email}" + password: "123123Qr" + } + ) { + customer { + id + firstname + lastname + email + } + } +} +QUERY; + } + + /** + * Build generateCustomerToken mutation + * + * @param string $email + * @return string + */ + private function buildLoginMutation(string $email): string + { + return <<<QUERY +mutation { + generateCustomerToken( + email: "{$email}" + password: "123123Qr" + ){ + token + } +} +QUERY; + } + + /** + * Build product search mutation + * + * @param string $term + * @return string + */ + private function buildProductSearchQuery(string $term): string + { + return <<<QUERY +{ + products ( + filter: { + sku: { + like:"{$term}%" + } + } + pageSize: 20 + currentPage: 1 + ) { + items { + sku + } + } +} +QUERY; + } + + /** + * Build addSimpleProductsToCart mutation + * + * @param string $cartId + * @param float $qty + * @param string $sku + * @return string + */ + private function buildAddToCartMutation(string $cartId, float $qty, string $sku): string + { + return <<<QUERY +mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$cartId}" + cartItems: [ + { + data: { + qty: {$qty} + sku: "{$sku}" + } + } + ] + } + ) { + cart { + items { + qty + product { + sku + } + } + prices { + grand_total { + value, + currency + } + } + } + } +} +QUERY; + } + + /** + * Build setShippingAddressesOnCart mutation + * + * @param string $cartId + * @param bool $save + * @return string + */ + private function buildSetNewShippingAddressMutation(string $cartId, bool $save = false): string + { + $save = json_encode($save); + return <<<QUERY +mutation { + setShippingAddressesOnCart( + input: { + cart_id: "$cartId" + shipping_addresses: [ + { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + region: "TX" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: {$save} + } + } + ] + } + ) { + cart { + shipping_addresses { + address_id + available_shipping_methods { + carrier_code + method_code + amount + } + } + } + } +} +QUERY; + } + + /** + * Build setShippingMethodsOnCart mutation + * + * @param string $cartId + * @param array $method + * @param array $address + * @return string + */ + private function buildSetShippingMethodMutation(string $cartId, array $method, array $address): string + { + return <<<QUERY +mutation { + setShippingMethodsOnCart(input: { + cart_id: "{$cartId}", + shipping_methods: [ + { + cart_address_id: {$address['address_id']} + carrier_code: "{$method['carrier_code']}" + method_code: "{$method['method_code']}" + } + ] + }) { + cart { + prices { + grand_total { + value, + currency + } + } + shipping_addresses { + selected_shipping_method { + carrier_code + method_code + } + } + } + } +} +QUERY; + + } + + /** + * Build setBillingAddressOnCart mutation + * + * @param string $cartId + * @param bool $save + * @return string + */ + private function buildSetNewBillingAddressMutation(string $cartId, bool $save = false): string + { + $save = json_encode($save); + return <<<QUERY +mutation { + setBillingAddressOnCart( + input: { + cart_id: "{$cartId}" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + street: ["test street 1", "test street 2"] + city: "test city" + region: "TX" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: {$save} + } + } + } + ) { + cart { + available_payment_methods { + code + title + } + billing_address { + firstname + lastname + company + street + city + postcode + telephone + country { + code + label + } + address_type + } + } + } +} +QUERY; + } + + /** + * Build setPaymentMethodOnCart mutation + * + * @param string $cartId + * @param array $payment + * @return string + */ + private function buildSetPaymentMethodMutation(string $cartId, array $payment): string + { + return <<<QUERY +mutation { + setPaymentMethodOnCart( + input: { + cart_id: "{$cartId}" + payment_method: { + code: "{$payment['code']}" + } + } + ) { + cart { + items { + qty + product { + sku + } + } + shipping_addresses { + selected_shipping_method { + carrier_code + method_code + } + } + selected_payment_method { + code + } + prices { + grand_total { + value + currency + } + } + } + } +} +QUERY; + } + + /** + * Build setGuestEmailOnCart mutation + * + * @param string $cartId + * @param string $email + * @return string + */ + private function buildSetGuestEmailOnCartMutation(string $cartId, string $email): string + { + return <<<QUERY +mutation { + setGuestEmailOnCart( + input: { + cart_id: "{$cartId}" + email: "{$email}" + } + ) { + cart { + email + } + } +} +QUERY; + } + + /** + * Build placeOrder mutation + * + * @param string $cartId + * @return string + */ + private function buildPlaceOrderMutation(string $cartId): string + { + return <<<QUERY +mutation { + placeOrder( + input: { + cart_id: "{$cartId}" + } + ) { + order { + order_id + } + } +} +QUERY; + } +} From e046edef2f6749f2f22466c8c36a0c371eee21de Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Wed, 17 Apr 2019 09:42:33 -0500 Subject: [PATCH 345/585] MC-15511: Search by default displays incorrect information --- .../Fulltext/Collection/SearchCriteriaResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php b/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php index 255c7885e84b9..32cb85ff750c4 100644 --- a/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php +++ b/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php @@ -79,7 +79,7 @@ public function resolve(): SearchCriteria $this->builder->setPageSize($this->size); $searchCriteria = $this->builder->create(); $searchCriteria->setRequestName($this->searchRequestName); - $searchCriteria->setSortOrders($this->orders); + $searchCriteria->setSortOrders(array_merge(['relevance' => 'DESC'], $this->orders)); $searchCriteria->setCurrentPage($this->currentPage - 1); return $searchCriteria; From 9da8adbdf6b4bd834f88cfe150735e96d017c19b Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Wed, 17 Apr 2019 09:53:20 -0500 Subject: [PATCH 346/585] MQE-1519: Deliver weekly MTF conversion PR Fixed failing test MC-14063: Apply catalog rule for configurable product with assigned simple products --- ...leForConfigurableProductWithAssignedSimpleProductsTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml index 7363fe7b3a96b..5bb45f58bcd27 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml @@ -178,8 +178,8 @@ <actionGroup ref="newCatalogPriceRuleByUI" stepKey="createPriceRule"> <argument name="catalogRule" value="CatalogRuleToFixed"/> </actionGroup> - <actionGroup ref="SelectNewCustomerGroupActionGroup" stepKey="addCustomerGroup"> - <argument name="customerGroup" value="$$customerGroup.code$$"/> + <actionGroup ref="CatalogSelectCustomerGroupActionGroup" stepKey="addCustomerGroup"> + <argument name="customerGroupName" value="$$customerGroup.code$$"/> </actionGroup> <!-- Save price rule --> From e4560fdc298e100f2a9e101797727b42922cce0c Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Wed, 17 Apr 2019 09:55:52 -0500 Subject: [PATCH 347/585] MC-5588: When using MysqlMQ messages are always set to complete even if exception occurs - Fix static tests --- .../Magento/Framework/MessageQueue/_files/valid_queue_input.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php index 46b3ba3414c8a..ed6e13cfe9fae 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php +++ b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php @@ -23,7 +23,7 @@ "name" => "publisher5.topic", "schema" => [ "schema_type" => "object", - "schema_value" => Magento\TestModuleMysqlMq\Model\DataObject::class + "schema_value" => \Magento\TestModuleMysqlMq\Model\DataObject::class ], "response_schema" => [ "schema_type" => "object", From 44297daf43cfe21a9267f5a4a063aabc9665ad61 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Wed, 17 Apr 2019 10:15:05 -0500 Subject: [PATCH 348/585] MQE-1519: Deliver weekly MTF conversion PR Fixed failing test MC-14063: Apply catalog rule for configurable product with assigned simple products --- .../SelectNewCustomerGroupActionGroup.xml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SelectNewCustomerGroupActionGroup.xml diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SelectNewCustomerGroupActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SelectNewCustomerGroupActionGroup.xml deleted file mode 100644 index debaad705b64f..0000000000000 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SelectNewCustomerGroupActionGroup.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="SelectNewCustomerGroupActionGroup"> - <arguments> - <argument name="customerGroup" type="entity"/> - </arguments> - <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="{{customerGroup}}" stepKey="selectCustomerGroup"/> - </actionGroup> -</actionGroups> From 653e57cabef1939ff78b1d6ba6aa6b97504ab259 Mon Sep 17 00:00:00 2001 From: avattam <> Date: Wed, 17 Apr 2019 10:32:48 -0500 Subject: [PATCH 349/585] changes to CmsPageCaheTest --- .../Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index 510df327df366..61b16a3387dfa 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -39,9 +39,6 @@ class CmsPageCacheTest extends \Magento\TestFramework\Indexer\TestCase /** @var Http */ private $request; - /** @var \Magento\Framework\App\Response\Http */ - private $response; - /** * @inheritdoc */ From 8afaf8097883e4a07a547d5f135f308576a62cff Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Wed, 17 Apr 2019 18:40:07 +0300 Subject: [PATCH 350/585] refactoring: changed variable long name --- .../GraphQl/Quote/Customer/AddSimpleProductToCartTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index 0ff96c03e0990..7b9df8c623c28 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -54,11 +54,11 @@ public function testAddProductToNonExistentCart() { $sku = 'simple_product'; $qty = 2; - $nonExistentMaskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($nonExistentMaskedQuoteId, $sku, $qty); + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->expectExceptionMessage( - "Could not find a cart with ID \"$nonExistentMaskedQuoteId\"" + "Could not find a cart with ID \"$maskedQuoteId\"" ); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); From 9137eeb919f5dd9239c3a305ead687c3a8d2a06b Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Wed, 17 Apr 2019 10:45:47 -0500 Subject: [PATCH 351/585] MQE-1519: Deliver weekly MTF conversion PR - Add mftf_migrated tag to MTF tests --- .../GridFilteringDeletedEntityTest.xml | 2 +- .../TestCase/ApplyCatalogPriceRulesTest.xml | 3 +++ .../CreateCatalogPriceRuleEntityTest.xml | 1 + ...nfigurableProductCatalogPriceRulesTest.xml | 2 ++ .../SuggestSearchingResultEntityTest.xml | 4 ++++ .../AddProductsToShoppingCartEntityTest.xml | 24 ++++++++++++------- .../CreateDownloadableProductEntityTest.xml | 12 +++++++++- .../CreateSalesRuleEntityPartOneTest.xml | 5 ++++ .../TestCase/DeleteSalesRuleEntityTest.xml | 3 +++ .../Test/TestCase/CreateStoreEntityTest.xml | 10 ++++---- 10 files changed, 51 insertions(+), 15 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/GridFilteringDeletedEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/GridFilteringDeletedEntityTest.xml index 687ed7038f40b..3bb0d5c0e1eb8 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/GridFilteringDeletedEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/GridFilteringDeletedEntityTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFilteringDeletedEntityTest" summary="Grid filtering by deleted entity" ticketId="MAGETWO-88982"> <variation name="GridFilteringDeletedEntityTestVariation1"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="array"> <item name="0" xsi:type="string">Magento\Store\Test\TestStep\DeleteWebsitesEntityStep</item> diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.xml b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.xml index 719e9bb95694e..8b36f78e4fc84 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.xml +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.xml @@ -116,6 +116,7 @@ <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedShoppingCart" /> </variation> <variation name="ApplyCatalogRuleForSimpleProductWithCustomOptions" summary="Apply Catalog Rule for Simple Product With Custom Options" ticketId="MAGETWO-23038"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="products/0" xsi:type="string">catalogProductSimple::with_default_custom_option</data> <data name="products/1" xsi:type="string">catalogProductSimple::with_percent_and_fixed_custom_option</data> <data name="products/2" xsi:type="string">catalogProductSimple::with_custom_options_and_price_56_78</data> @@ -149,6 +150,7 @@ <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleOnOnepageCheckout" /> </variation> <variation name="ApplyCatalogRuleForSimpleProductAndConfigurableProduct" summary="Apply Catalog Rule For Simple Product And Configurable Product" ticketId="MAGETWO-20616"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="products/0" xsi:type="string">configurableProduct::product_with_price_10</data> <data name="products/1" xsi:type="string">catalogProductSimple::simple_10_dollar</data> <data name="catalogRules/0/data/customer_group_ids/option_0" xsi:type="string">NOT LOGGED IN</data> @@ -177,6 +179,7 @@ <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedShoppingCart" /> </variation> <variation name="ApplyCatalogRuleForSimpleProductAndFixedMethod" summary="Apply Catalog Rule For Simple Product And Fixed Shipping Method" ticketId="MAGETWO-23039"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="products/0" xsi:type="string">catalogProductSimple::with_fixed_custom_option_price_100</data> <data name="customer/dataset" xsi:type="string">customer_US</data> <data name="catalogRules/0/data/name" xsi:type="string">CatalogPriceRule %isolation%</data> diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.xml index 25b46ccd6c093..49bf36b0325ba 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.xml @@ -21,6 +21,7 @@ <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleInGrid" /> </variation> <variation name="CatalogRule_Create_Inactive_AdminOnly"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="catalogPriceRule/data/name" xsi:type="string">CatalogPriceRule %isolation%</data> <data name="catalogPriceRule/data/description" xsi:type="string">Catalog Price Rule Description</data> <data name="catalogPriceRule/data/is_active" xsi:type="string">Inactive</data> diff --git a/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/ApplyConfigurableProductCatalogPriceRulesTest.xml b/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/ApplyConfigurableProductCatalogPriceRulesTest.xml index 2e9e2480f382f..1645c68f8fbbd 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/ApplyConfigurableProductCatalogPriceRulesTest.xml +++ b/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/ApplyConfigurableProductCatalogPriceRulesTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\CatalogRuleConfigurable\Test\TestCase\ApplyConfigurableProductCatalogPriceRulesTest" summary="Apply Catalog Price Rules"> <variation name="ApplyCatalogRuleForComfigurableProductWithOptions1" summary="Apply Catalog Rule For Configurable Product With Promo Simple Product" ticketId="MAGETWO-47186"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="products/0" xsi:type="string">configurableProduct::Stellar_Solar_Jacket_SIZE_S</data> <data name="products/1" xsi:type="string">configurableProduct::Stellar_Solar_Jacket_SIZE_M</data> <data name="products/2" xsi:type="string">configurableProduct::Stellar_Solar_Jacket_SIZE_L</data> @@ -39,6 +40,7 @@ <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedShoppingCart" /> </variation> <variation name="ApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts" summary="Apply Catalog Rule For Configurable Product With Custom Options" ticketId="MAGETWO-23042"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="products/0" xsi:type="string">configurableProduct::first_product_with_custom_options_and_option_key_1</data> <data name="products/1" xsi:type="string">configurableProduct::first_product_with_custom_options_and_option_key_2</data> <data name="products/2" xsi:type="string">configurableProduct::second_product_with_custom_options_and_option_key_1</data> diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SuggestSearchingResultEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SuggestSearchingResultEntityTest.xml index e9e4bcca2e136..ffd9e902cdece 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SuggestSearchingResultEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SuggestSearchingResultEntityTest.xml @@ -8,22 +8,26 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\CatalogSearch\Test\TestCase\SuggestSearchingResultEntityTest" summary="Suggest Searching Results" ticketId="MAGETWO-24671, MAGETWO-23186"> <variation name="SuggestSearchingResultEntityTestVariation1" summary="Auto-complete search with product name" ticketId="MAGETWO-24671"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="searchTerm/data/query_text/value" xsi:type="string">catalogProductSimple::name</data> <data name="searchTerm/data/num_results" xsi:type="string">-</data> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertSuggestSearchingResult" /> </variation> <variation name="SuggestSearchingResultEntityTestVariation2" summary="Auto-complete search with product sku" ticketId="MAGETWO-24671"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="searchTerm/data/query_text/value" xsi:type="string">catalogProductSimple::sku</data> <data name="searchTerm/data/num_results" xsi:type="string">1</data> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertSuggestSearchingResult" /> </variation> <variation name="SuggestSearchingResultEntityTestVariation3" summary="Auto-complete search with product description" ticketId="MAGETWO-23186"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="searchTerm/data/query_text/value" xsi:type="string">catalogProductSimple::abc_dfj_simple_for_advancedsearch::adc_Full</data> <data name="searchTerm/data/num_results" xsi:type="string">1</data> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertSuggestSearchingResult" /> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertSearchTermInGrid" /> </variation> <variation name="SuggestSearchingResultEntityTestVariation4" summary="Auto-complete search with product short description" ticketId="MAGETWO-23186"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="searchTerm/data/query_text/value" xsi:type="string">catalogProductSimple::abc_dfj_simple_for_advancedsearch::abc_short</data> <data name="searchTerm/data/num_results" xsi:type="string">1</data> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertSuggestSearchingResult" /> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml index 8d054c0230873..e87d05ac98df8 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Checkout\Test\TestCase\AddProductsToShoppingCartEntityTest" summary="Add Products to Shopping Cart" ticketId="MAGETWO-25382"> <variation name="AddProductsToShoppingCartEntityTestVariation1" ticketId="MAGETWO-42677"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">bundleProduct::bundle_dynamic_product</data> <data name="cart/data/grand_total" xsi:type="string">210</data> <data name="cart/data/subtotal" xsi:type="string">200</data> @@ -61,7 +61,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation5"> - <data name="tag" xsi:type="string">severity:S0</data> + <data name="tag" xsi:type="string">severity:S0, mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">configurableProduct::default</data> <data name="cart/data/grand_total" xsi:type="string">135</data> <data name="cart/data/subtotal" xsi:type="string">120</data> @@ -74,7 +74,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation6"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">downloadableProduct::with_two_separately_links</data> <data name="cart/data/grand_total" xsi:type="string">22.43</data> <data name="cart/data/subtotal" xsi:type="string">22.43</data> @@ -87,7 +87,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation7"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">groupedProduct::three_simple_products</data> <data name="cart/data/grand_total" xsi:type="string">1950</data> <data name="cart/data/subtotal" xsi:type="string">1920</data> @@ -123,6 +123,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation9" summary="Add dynamic bundle product to shopping cart with disabled mini shoping cart sidebar" ticketId="MAGETWO-35535"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="configData" xsi:type="string">disable_display_shopping_cart_sidebar</data> <data name="flushCache" xsi:type="boolean">true</data> <data name="productsData/0" xsi:type="string">bundleProduct::bundle_dynamic_product</data> @@ -136,6 +137,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertMyCartLinkRedirect" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation10" summary="Verify Top Destinations for Country Options configuration applied in shopping cart" ticketId="MAGETWO-38700"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="configData" xsi:type="string">top_destinations_DE_ES_GB</data> <data name="cart/data/grand_total" xsi:type="string">15.00</data> @@ -149,7 +151,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertTopDestinationsInSelect" /> </variation> <variation name="VariationWithCartItemsDisplayDefaultLimitation" summary="Verify visible items count in minicart and checkout summary block according to configuration" ticketId="MAGETWO-63442"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::default</data> <data name="productsData/1" xsi:type="string">catalogProductSimple::default</data> <data name="productsData/2" xsi:type="string">catalogProductSimple::default</data> @@ -170,7 +172,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertVisibleItemsQtyInMiniShoppingCart" /> </variation> <variation name="VariationWithCartItemsDisplayDefaultLimitationAndDefaultTotalQty" summary="Verify visible items count in minicart and checkout summary block according to configuration" ticketId="MAGETWO-63441"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::default</data> <data name="productsData/1" xsi:type="string">catalogProductSimple::default</data> <data name="productsData/2" xsi:type="string">catalogProductSimple::default</data> @@ -190,7 +192,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertVisibleItemsQtyInMiniShoppingCart" /> </variation> <variation name="VariationWithCartItemsDisplayDefaultLimitationOnCheckoutAndDefaultTotalQty" summary="Verify visible items count in minicart and checkout summary block according to configuration" ticketId="MAGETWO-63447"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::default</data> <data name="productsData/1" xsi:type="string">catalogProductSimple::default</data> <data name="productsData/2" xsi:type="string">catalogProductSimple::default</data> @@ -211,7 +213,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertLinkGoToCartNotPresentInSummaryBlock" /> </variation> <variation name="VariationWithCartItemsDisplayDefaultLimitationOnCheckout" summary="Verify visible items count in minicart and checkout summary block according to configuration" ticketId="MAGETWO-63448"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::default</data> <data name="productsData/1" xsi:type="string">catalogProductSimple::default</data> <data name="productsData/2" xsi:type="string">catalogProductSimple::default</data> @@ -233,7 +235,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertLinkGoToCartPresentInSummaryBlock" /> </variation> <variation name="VariationWithCartItemsDisplayCustomLimitations" summary="Verify visible items count in minicart and checkout summary block according to configuration" ticketId="MAGETWO-63445, MAGETWO-63449, MAGETWO-63452"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">catalogProductVirtual::default</data> <data name="productsData/1" xsi:type="string">catalogProductVirtual::default</data> <data name="productsData/2" xsi:type="string">catalogProductVirtual::default</data> @@ -252,6 +254,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertLinkGoToCartPresentInSummaryBlock" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation11" summary="Create product with all types of custom options that are required and trigger JS validation" ticketId="MAGETWO-45389"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::with_all_required_custom_option</data> <data name="cart/data/subtotal" xsi:type="string">6160.00</data> <data name="isValidationFailed" xsi:type="boolean">true</data> @@ -259,12 +262,14 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertProductsAbsentInShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation12" summary="Create product with all types of custom options that are required and check that item options for product(s) display with correct information" ticketId="MAGETWO-45389"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::with_all_required_custom_option</data> <data name="cart/data/subtotal" xsi:type="string">6160.00</data> <data name="isValidationFailed" xsi:type="boolean">true</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartItemsOptions" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation13" summary="Check Bundle on Cart Configuration Page." ticketId="MAGETWO-71634"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">bundleProduct::bundle_with_multiselect_option_one_selection</data> <data name="cart/data/grand_total" xsi:type="string">105</data> <data name="cart/data/subtotal" xsi:type="string">100</data> @@ -277,6 +282,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertGrandTotalInShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation14" summary="Check Bundle on Cart Configuration Page." ticketId="MAGETWO-71634"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="productsData/0" xsi:type="string">bundleProduct::bundle_with_multiselect_option_two_selections</data> <data name="cart/data/grand_total" xsi:type="string">665</data> <data name="cart/data/subtotal" xsi:type="string">660</data> diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest.xml index 5afe815edad45..b61a244345a58 100644 --- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Downloadable\Test\TestCase\CreateDownloadableProductEntityTest" summary="Create Downloadable Product" ticketId="MAGETWO-23425"> <variation name="CreateDownloadableProductEntityTestVariation1" summary="Create Downloadable Product with Required Fields Only and Assign it to the Category" ticketId="MAGETWO-13595"> - <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test</data> + <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test, mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">10</data> @@ -24,6 +24,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductInCart" /> </variation> <variation name="CreateDownloadableProductEntityTestVariation2" summary="Create product with default set links"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/price/value" xsi:type="string">100</data> @@ -61,6 +62,7 @@ <constraint name="Magento\Downloadable\Test\Constraint\AssertDownloadableLinksData" /> </variation> <variation name="CreateDownloadableProductEntityTestVariation4" summary="Create product with custom options"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/price/value" xsi:type="string">33</data> @@ -102,6 +104,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductSearchableBySku" /> </variation> <variation name="CreateDownloadableProductEntityTestVariation6" summary="Create product with out of stock status"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/price/value" xsi:type="string">100</data> @@ -117,6 +120,7 @@ <constraint name="Magento\Downloadable\Test\Constraint\AssertDownloadableProductForm" /> </variation> <variation name="CreateDownloadableProductEntityTestVariation7" summary="Create product with manage stock"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/price/value" xsi:type="string">9999</data> @@ -133,6 +137,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductOutOfStock" /> </variation> <variation name="CreateDownloadableProductEntityTestVariation8" summary="Create product without tax class id"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/price/value" xsi:type="string">98</data> @@ -217,6 +222,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductCustomOptionsOnProductPage" /> </variation> <variation name="CreateDownloadableProductEntityTestVariation12" summary="Create product without filling quantity and stock"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/price/value" xsi:type="string">100</data> @@ -231,6 +237,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductPage" /> </variation> <variation name="CreateDownloadableProductEntityTestVariation13" summary="Create product with special price"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/price/value" xsi:type="string">10</data> @@ -248,6 +255,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductSpecialPriceOnProductPage" /> </variation> <variation name="CreateDownloadableProductEntityTestVariation14" summary="Create product with group price"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/price/value" xsi:type="string">365</data> @@ -263,6 +271,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductPage" /> </variation> <variation name="CreateDownloadableProductEntityTestVariation15" summary="Create product with tier price"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/price/value" xsi:type="string">250</data> @@ -280,6 +289,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductTierPriceOnProductPage" /> </variation> <variation name="CreateDownloadableProductEntityTestVariation16" summary="Create downloadable product and assign it to custom website"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/name" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/sku" xsi:type="string">DownloadableProduct_%isolation%</data> <data name="product/data/price/value" xsi:type="string">350</data> diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityPartOneTest.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityPartOneTest.xml index 7ea54daccf5a8..23256b192b2d0 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityPartOneTest.xml +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityPartOneTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\SalesRule\Test\TestCase\CreateSalesRuleEntityPartOneTest" summary="Create Cart Price Rule" ticketId="MAGETWO-24855"> <variation name="CreateSalesRuleEntityTestVariation7"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="address/data/country_id" xsi:type="string">United States</data> <data name="address/data/region_id" xsi:type="string">California</data> <data name="address/data/postcode" xsi:type="string">95814</data> @@ -37,6 +38,7 @@ <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleFreeShippingIsApplied" /> </variation> <variation name="CreateSalesRuleEntityTestVariation8"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="address/data/country_id" xsi:type="string">United States</data> <data name="address/data/region_id" xsi:type="string">California</data> <data name="address/data/postcode" xsi:type="string">95814</data> @@ -66,6 +68,7 @@ <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleConditionIsApplied" /> </variation> <variation name="CreateSalesRuleEntityTestVariation9"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="salesRule/data/name" xsi:type="string">Cart Price Rule9 %isolation%</data> <data name="salesRule/data/description" xsi:type="string">Cart Price Rule Description %isolation%</data> <data name="salesRule/data/is_active" xsi:type="string">Yes</data> @@ -85,6 +88,7 @@ <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleConditionIsNotApplied" /> </variation> <variation name="CreateSalesRuleEntityTestVariation10"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="salesRule/data/name" xsi:type="string">Cart Price Rule10 %isolation%</data> <data name="salesRule/data/description" xsi:type="string">Cart Price Rule Description %isolation%</data> <data name="salesRule/data/is_active" xsi:type="string">Yes</data> @@ -110,6 +114,7 @@ <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleConditionIsApplied" /> </variation> <variation name="CreateSalesRuleEntityTestVariation11"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="salesRule/data/name" xsi:type="string">Cart Price Rule11 %isolation%</data> <data name="salesRule/data/description" xsi:type="string">Cart Price Rule Description %isolation%</data> <data name="salesRule/data/is_active" xsi:type="string">Yes</data> diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.xml index ec3ccf331c2f3..c9af05b8f779a 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.xml @@ -8,16 +8,19 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\SalesRule\Test\TestCase\DeleteSalesRuleEntityTest" summary="Delete Sales Rule" ticketId="MAGETWO-24985"> <variation name="DeleteSalesRuleEntityTestVariation1"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="salesRule/dataset" xsi:type="string">active_sales_rule_with_percent_price_discount_coupon</data> <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleSuccessDeleteMessage" /> <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleIsNotPresentedInGrid" /> </variation> <variation name="DeleteSalesRuleEntityTestVariation2"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="salesRule/dataset" xsi:type="string">active_sales_rule_with_complex_conditions</data> <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleSuccessDeleteMessage" /> <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleIsNotPresentedInGrid" /> </variation> <variation name="DeleteSalesRuleEntityTestVariation3" summary="Assert That Cart Price Rule Condition Is Not Applied" ticketId="MAGETWO-16987"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="salesRule/dataset" xsi:type="string">inactive_sales_rule</data> <data name="productForSalesRule1/dataset" xsi:type="string">simple_for_salesrule_1</data> <data name="productQuantity/productForSalesRule1" xsi:type="string">1</data> diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreEntityTest.xml b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreEntityTest.xml index 31e7f611a12e8..d86c36c984dbd 100644 --- a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreEntityTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Store\Test\TestCase\CreateStoreEntityTest" summary="Create Store View" ticketId="MAGETWO-27647"> <variation name="CreateStoreEntityTestVariation1"> - <data name="tag" xsi:type="string">severity:S1</data> + <data name="tag" xsi:type="string">severity:S1, mftf_migrated:yes</data> <data name="store/data/group_id/dataset" xsi:type="string">default</data> <data name="store/data/name" xsi:type="string">store_name_%isolation%</data> <data name="store/data/code" xsi:type="string">storecode_%isolation%</data> @@ -18,7 +18,7 @@ <constraint name="Magento\Store\Test\Constraint\AssertStoreFrontend" /> </variation> <variation name="CreateStoreEntityTestVariation2"> - <data name="tag" xsi:type="string">severity:S3</data> + <data name="tag" xsi:type="string">severity:S3, mftf_migrated:yes</data> <data name="store/data/group_id/dataset" xsi:type="string">default</data> <data name="store/data/name" xsi:type="string">store_name_%isolation%</data> <data name="store/data/code" xsi:type="string">storecode_%isolation%</data> @@ -28,7 +28,7 @@ <constraint name="Magento\Store\Test\Constraint\AssertStoreNotOnFrontend" /> </variation> <variation name="CreateStoreEntityTestVariation3"> - <data name="tag" xsi:type="string">severity:S1</data> + <data name="tag" xsi:type="string">severity:S1, mftf_migrated:yes</data> <data name="store/data/group_id/dataset" xsi:type="string">custom</data> <data name="store/data/name" xsi:type="string">store_name_%isolation%</data> <data name="store/data/code" xsi:type="string">storecode_%isolation%</data> @@ -40,7 +40,7 @@ <constraint name="Magento\Store\Test\Constraint\AssertStoreFrontend" /> </variation> <variation name="CreateStoreEntityTestVariation4" summary="Create New Localized Store View" ticketId="MAGETWO-12405"> - <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test, severity:S0</data> + <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test, severity:S0, mftf_migrated:yes</data> <data name="store/data/group_id/dataset" xsi:type="string">default</data> <data name="store/data/name" xsi:type="string">DE_%isolation%</data> <data name="store/data/code" xsi:type="string">de_%isolation%</data> @@ -51,12 +51,14 @@ <constraint name="Magento\Store\Test\Constraint\AssertStoreInGrid" /> </variation> <variation name="CreateStoreEntityTestVariation5" summary="Check the absence of delete button" ticketId="MAGETWO-17475"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="store/dataset" xsi:type="string">custom_store</data> <constraint name="Magento\Store\Test\Constraint\AssertStoreSuccessSaveMessage" /> <constraint name="Magento\Store\Test\Constraint\AssertStoreForm" /> <constraint name="Magento\Store\Test\Constraint\AssertStoreNoDeleteButton" /> </variation> <variation name="CreateDisabledStoreView" summary="Create disabled store view" ticketId="MAGETWO-17475"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="store/data/group_id/dataset" xsi:type="string">custom_new_group</data> <data name="store/data/name" xsi:type="string">store_name_%isolation%</data> <data name="store/data/code" xsi:type="string">storecode_%isolation%</data> From e0e7873fbb60f22adf20b657de39871be71c1f78 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 17 Apr 2019 19:11:04 +0300 Subject: [PATCH 352/585] graphQl-309: fixed request type in tests --- .../Quote/Customer/SetOfflinePaymentMethodOnCartTest.php | 6 +++--- .../Quote/Guest/SetOfflinePaymentMethodOnCartTest.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php index 36189db4094e9..ed7b6288f0910 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php @@ -71,7 +71,7 @@ public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() } } QUERY; - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); @@ -112,7 +112,7 @@ public function testSetPurchaseOrderPaymentMethodOnCartWithoutPurchaseOrderNumbe } } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -149,7 +149,7 @@ public function testSetDisabledPurchaseOrderPaymentMethodOnCart() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php index bbc7fc9df839d..70996f584b9db 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php @@ -63,7 +63,7 @@ public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() } } QUERY; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); @@ -103,7 +103,7 @@ public function testSetPurchaseOrderPaymentMethodOnCartWithoutPurchaseOrderNumbe } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -139,6 +139,6 @@ public function testSetDisabledPurchaseOrderPaymentMethodOnCart() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } } From 4d821390cbf0e792b9e47e97fd56453c28c4cbc3 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 17 Apr 2019 12:39:52 -0500 Subject: [PATCH 353/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- app/code/Magento/Backend/Model/Auth/Session.php | 1 + .../Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php | 3 +++ lib/internal/Magento/Framework/App/Response/Http.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/app/code/Magento/Backend/Model/Auth/Session.php b/app/code/Magento/Backend/Model/Auth/Session.php index e253881c2253b..61db71c1803e2 100644 --- a/app/code/Magento/Backend/Model/Auth/Session.php +++ b/app/code/Magento/Backend/Model/Auth/Session.php @@ -23,6 +23,7 @@ * @method \Magento\Backend\Model\Auth\Session setUpdatedAt(int $value) * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @todo implement solution that keeps is_first_visit flag in session during redirects * @api * @since 100.0.2 diff --git a/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php b/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php index eaa93887fee9e..f3baaeebc137d 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php @@ -13,6 +13,9 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\Framework\Acl\Builder as AclBuilder; +/** + * Test for session hydrator. + */ class SessionAclHydratorInterfaceTest extends TestCase { /** diff --git a/lib/internal/Magento/Framework/App/Response/Http.php b/lib/internal/Magento/Framework/App/Response/Http.php index a152b655e42a3..a80d9cbdd6689 100644 --- a/lib/internal/Magento/Framework/App/Response/Http.php +++ b/lib/internal/Magento/Framework/App/Response/Http.php @@ -17,6 +17,8 @@ /** * HTTP Response. + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class Http extends \Magento\Framework\HTTP\PhpEnvironment\Response { From bf84115dee655e77405d02d7f1735d9bfce330bf Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Wed, 17 Apr 2019 12:45:50 -0500 Subject: [PATCH 354/585] Issue-230: Implement cache tag generation for GraphQL queries - Integration tests --- .../Controller/AbstractGraphqlCacheTest.php | 42 +++++++++++++++++ .../Controller/Cms/BlockCacheTest.php | 45 ++----------------- 2 files changed, 46 insertions(+), 41 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php new file mode 100644 index 0000000000000..d2e853c2aa0ea --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php @@ -0,0 +1,42 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller; + +use PHPUnit\Framework\TestCase; +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Abstract test class for Graphql cache tests + */ +class AbstractGraphqlCacheTest extends TestCase +{ + /** + * @var ObjectManager + */ + protected $objectManager; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->usePageCachePlugin(); + } + + /** + * Enable full page cache plugin + */ + protected function usePageCachePlugin(): void + { + /** @var $registry \Magento\Framework\Registry */ + $registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $registry->register('use_page_cache_plugin', true, true); + } +} diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php index fe90a42c9f7c6..005007fce58fb 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php @@ -10,22 +10,16 @@ use Magento\Cms\Model\BlockRepository; use Magento\Framework\App\Request\Http; use Magento\GraphQl\Controller\GraphQl; -use Magento\TestFramework\ObjectManager; -use Magento\TestFramework\Helper\Bootstrap; +use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; /** * Test caching works for CMS blocks * * @magentoAppArea graphql - * @magentoDbIsolation disabled + * @magentoCache full_page enabled */ -class BlockCacheTest extends \Magento\TestFramework\Indexer\TestCase +class BlockCacheTest extends AbstractGraphqlCacheTest { - /** - * @var ObjectManager - */ - private $objectManager; - /** * @var GraphQl */ @@ -36,31 +30,14 @@ class BlockCacheTest extends \Magento\TestFramework\Indexer\TestCase */ private $request; - /** - * @inheritdoc - */ - public static function setUpBeforeClass() - { - $db = Bootstrap::getInstance()->getBootstrap() - ->getApplication() - ->getDbInstance(); - if (!$db->isDbDumpExists()) { - throw new \LogicException('DB dump does not exist.'); - } - $db->restoreFromDbDump(); - - parent::setUpBeforeClass(); - } - /** * @inheritdoc */ protected function setUp(): void { - $this->objectManager = Bootstrap::getObjectManager(); + parent::setUp(); $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); $this->request = $this->objectManager->create(Http::class); - $this->enableFullPageCache(); } /** @@ -103,18 +80,4 @@ public function testCmsBlocksRequestHasCorrectTags(): void $this->assertContains($expectedCacheTag, $actualCacheTags); } } - - /** - * Enable full page cache so plugins are called - */ - private function enableFullPageCache() - { - /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); - - /** @var \Magento\Framework\App\Cache\StateInterface $cacheState */ - $cacheState = $this->objectManager->get(\Magento\Framework\App\Cache\StateInterface::class); - $cacheState->setEnabled(\Magento\PageCache\Model\Cache\Type::TYPE_IDENTIFIER, true); - } } From c51ec5257ca8a67d04bc384ae7c61123c9ce2b79 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Wed, 17 Apr 2019 14:25:48 -0500 Subject: [PATCH 355/585] Issue-230: adding varnish - fixing test - handling error codes > 400 --- .../TestFramework/TestCase/GraphQl/Client.php | 7 +- .../ProductInMultipleStoresCacheTest.php | 140 ++++++++++++++---- 2 files changed, 117 insertions(+), 30 deletions(-) diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php index 870f840bdfa13..d5a33cfe281fc 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php @@ -86,7 +86,12 @@ public function get(string $query, array $variables = [], string $operationName ]; array_filter($requestArray); - $responseBody = $this->curlClient->get($url, $requestArray, $headers); + try { + $responseBody = $this->curlClient->get($url, $requestArray, $headers); + } catch (\Exception $e) { + // if response code > 400 then response is the exception message + $responseBody = $e->getMessage(); + } return $this->processResponse($responseBody); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php index 916a25ea5acda..12cd8894659b4 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php @@ -18,13 +18,73 @@ class ProductInMultipleStoresCacheTest extends GraphQlAbstract { /** - * Test a non existing or non allowed currency + * @inheritdoc + */ + protected function setUp() + { + /** @var \Magento\Store\Model\Store $store */ + $store = ObjectManager::getInstance()->get(\Magento\Store\Model\Store::class); + $storeCodeFromFixture = 'fixture_second_store'; + + /** @var \Magento\Config\Model\ResourceModel\Config $configResource */ + $configResource = ObjectManager::getInstance()->get(\Magento\Config\Model\ResourceModel\Config::class); + /** @var \Magento\Config\App\Config\Type\System $config */ + $config = ObjectManager::getInstance()->get(\Magento\Config\App\Config\Type\System::class); + + $configResource->saveConfig( + \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_DEFAULT, + 'EUR', + \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES, + $store->load($storeCodeFromFixture)->getWebsiteId() + ); + + // allow USD & EUR currency + $configResource->saveConfig( + \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_ALLOW, + 'EUR,USD', + \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES, + $store->load($storeCodeFromFixture)->getWebsiteId() + ); + + // allow USD & EUR currency + $configResource->saveConfig( + \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_ALLOW, + 'EUR,USD' + ); + + // configuration cache clean is required to reload currency setting + $config->clean(); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + /** @var \Magento\Config\App\Config\Type\System $config */ + $config = ObjectManager::getInstance()->get(\Magento\Config\App\Config\Type\System::class); + /** @var \Magento\Config\Model\ResourceModel\Config $configResource */ + $configResource = ObjectManager::getInstance()->get(\Magento\Config\Model\ResourceModel\Config::class); + + // restore allow USD currency + $configResource->saveConfig( + \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_ALLOW, + 'USD' + ); + + // configuration cache clean is required to reload currency setting + $config->clean(); + parent::tearDown(); + } + + /** + * Test a non existing or non existing currency * * @magentoApiDataFixture Magento/Store/_files/second_website_with_second_currency.php * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function testProductFromSpecificAndDefaultStoreWithMultiCurrencyNotAllowed() + public function testProductFromSpecificAndDefaultStoreWithMultiCurrencyNonExisting() { $productSku = 'simple'; @@ -56,16 +116,58 @@ public function testProductFromSpecificAndDefaultStoreWithMultiCurrencyNotAllowe } QUERY; - $storeCodeFromFixture = 'fixture_second_store'; - //test non existing currency $headerMap = ['Store' => 'default', 'Content-Currency' => 'someNonExistentCurrency']; - $this->expectExceptionMessage('Currency someNonExistentCurrency not allowed for store default'); + $this->expectExceptionMessage('GraphQL response contains errors: Currency not allowed for store default'); $this->graphQlQuery($query, [], '', $headerMap); + } + + /** + * Test a non existing or non allowed currency + * + * @magentoApiDataFixture Magento/Store/_files/second_website_with_second_currency.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testProductFromSpecificAndDefaultStoreWithMultiCurrencyNotAllowed() + { + $productSku = 'simple'; + + $query = <<<QUERY +{ + products(filter: {sku: {eq: "{$productSku}"}}) + { + items { + attribute_set_id + created_at + id + name + price { + minimalPrice { + amount { + value + currency + } + } + } + sku + type_id + updated_at + ... on PhysicalProductInterface { + weight + } + } + } +} +QUERY; + + $storeCodeFromFixture = 'fixture_second_store'; //test not allowed existing currency $headerMap = ['Store' => $storeCodeFromFixture, 'Content-Currency' => 'CAD']; - $this->expectExceptionMessage('Currency not allowed for store ' . $storeCodeFromFixture); + $this->expectExceptionMessage( + "GraphQL response contains errors: Currency not allowed for store {$storeCodeFromFixture}" + ); $this->graphQlQuery($query, [], '', $headerMap); } @@ -113,28 +215,6 @@ public function testProductFromSpecificAndDefaultStoreWithMultiCurrency() $storeCodeFromFixture = 'fixture_second_store'; $storeId = $store->load($storeCodeFromFixture)->getStoreId(); - $configResource = ObjectManager::getInstance()->get(\Magento\Config\Model\ResourceModel\Config::class); - - $configResource->saveConfig( - \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_DEFAULT, - 'EUR', - \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES, - $store->load($storeCodeFromFixture)->getWebsiteId() - ); - - // allow USD & EUR currency - $configResource->saveConfig( - \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_ALLOW, - 'EUR,USD', - \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES, - $store->load($storeCodeFromFixture)->getWebsiteId() - ); - - /** @var \Magento\Config\App\Config\Type\System $config */ - $config = ObjectManager::getInstance()->get(\Magento\Config\App\Config\Type\System::class); - // configuration cache clean is required to reload currency setting - $config->clean(); - /** @var \Magento\Catalog\Model\Product $product */ $product = ObjectManager::getInstance()->get(\Magento\Catalog\Model\Product::class); $product->load($product->getIdBySku($productSku)); @@ -234,7 +314,9 @@ public function testProductFromSpecificAndDefaultStoreWithMultiCurrency() // test cached response store + currency header with non existing currency, and no valid response, no cache $headerMap = ['Store' => $storeCodeFromFixture, 'Content-Currency' => 'SOMECURRENCY']; - $this->expectExceptionMessage('Currency not allowed for store ' . $storeCodeFromFixture); + $this->expectExceptionMessage( + "GraphQL response contains errors: Currency not allowed for store {$storeCodeFromFixture}" + ); $this->graphQlQuery($query, [], '', $headerMap); } } From acc1f349b4e3ab8b9b1ede0587d42337833f54ea Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Wed, 17 Apr 2019 14:32:00 -0500 Subject: [PATCH 356/585] MQE-1519: Deliver weekly MTF conversion PR - Move Customer Segment action group from SalesRule --- ...WithSegmentForCartPriceRuleActionGroup.xml | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml deleted file mode 100644 index 1ae6b7a3e92f4..0000000000000 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml +++ /dev/null @@ -1,46 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <!--Set condition for Customer Segment--> - <actionGroup name="SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup"> - <arguments> - <argument name="attributeName" type="string"/> - <argument name="value" type="entity"/> - </arguments> - - <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToActionTab"/> - <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeaderOpen}}" visible="false" stepKey="openActionTab"/> - <click selector="{{AdminCartPriceRulesFormSection.conditions}}" stepKey="applyRuleForConditions"/> - - <waitForPageLoad stepKey="waitForDropDownOpened"/> - <selectOption selector="{{AdminCartPriceRulesFormSection.childAttribute}}" userInput="{{attributeName}}" stepKey="selectAttribute"/> - - <waitForPageLoad time="20" stepKey="waitForOperator"/> - <click selector="{{AdminCartPriceRulesFormSection.condition('...')}}" stepKey="clickToChooseOption1"/> - <click selector="{{AdminCartPriceRulesFormSection.openList}}" stepKey="openList" /> - <waitForPageLoad time="20" stepKey="waitForGrid"/> - <fillField selector="{{AdminCartPriceRulesFormSection.searchSegmentName}}" userInput="{{value.name}}" stepKey="fillSegmentName"/> - <click selector="{{AdminCartPriceRulesFormSection.searchButton}}" stepKey="clickButtonSearch"/> - - <waitForPageLoad stepKey="waitForResults"/> - <checkOption selector="{{AdminCartPriceRulesFormSection.selectAll}}" stepKey="checkAll"/> - <waitForPageLoad stepKey="waitForChecking"/> - <moveMouseOver selector="{{AdminCartPriceRulesFormSection.setSegment}}" stepKey="moveOnButton"/> - <click selector="{{AdminCartPriceRulesFormSection.setSegment}}" stepKey="setCustomerSegment"/> - <click selector="{{AdminMainActionsSection.saveAndContinue}}" stepKey="clickSaveButton"/> - <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> - </actionGroup> - <actionGroup name="SetCartAttributeConditionWhenMatchForCartPriceRuleActionGroup" extends="SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup"> - <arguments> - <argument name="operatorType" type="string" defaultValue="matches"/> - </arguments> - <click selector="{{AdminCartPriceRulesFormSection.condition('matches')}}" stepKey="clickToChooseOption" after="waitForOperator"/> - <selectOption userInput="{{operatorType}}" selector="{{AdminCartPriceRulesFormSection.conditionsOperator}}" stepKey="setOperatorType" after="clickToChooseOption"/> - </actionGroup> -</actionGroups> \ No newline at end of file From 9ecc0583301b670ac0eabc3dacaf21305e98679c Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Wed, 17 Apr 2019 14:38:17 -0500 Subject: [PATCH 357/585] GraphQL-598: CMS Page Integration Test for Tag Cache Generation Code refactoring --- .../Controller/Cms/CmsPageCacheTest.php | 67 ++++++------------- 1 file changed, 19 insertions(+), 48 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index 61b16a3387dfa..bc436b8f35782 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -9,70 +9,43 @@ use Magento\Cms\Model\GetPageByIdentifier; use Magento\Framework\App\Request\Http; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Serialize\SerializerInterface; -use Magento\TestFramework\Helper\Bootstrap; use Magento\GraphQl\Controller\GraphQl; +use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; /** * Test caching works for CMS page * * @magentoAppArea graphql - * @magentoDbIsolation disabled + * @magentoCache full_page enabled */ -class CmsPageCacheTest extends \Magento\TestFramework\Indexer\TestCase +class CmsPageCacheTest extends AbstractGraphqlCacheTest { - const CONTENT_TYPE = 'application/json'; - - /** @var \Magento\Framework\ObjectManagerInterface */ - private $objectManager; - - /** @var GraphQl */ - private $graphql; - - /** @var SerializerInterface */ - private $jsonSerializer; - - /** @var MetadataPool */ - private $metadataPool; - - /** @var Http */ - private $request; - /** - * @inheritdoc + * @var GraphQl */ - public static function setUpBeforeClass() - { - $db = Bootstrap::getInstance()->getBootstrap() - ->getApplication() - ->getDbInstance(); - if (!$db->isDbDumpExists()) { - throw new \LogicException('DB dump does not exist.'); - } - $db->restoreFromDbDump(); + private $graphqlController; - parent::setUpBeforeClass(); - } + /** + * @var Http + */ + private $request; /** * @inheritdoc */ protected function setUp(): void { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); - $this->metadataPool = $this->objectManager->get(MetadataPool::class); - $this->request = $this->objectManager->get(Http::class); + parent::setUp(); + $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->request = $this->objectManager->create(Http::class); } + /** - * Test cache tags and debug header for category and querying only cms page + * Test that the correct cache tags get added to request for cmsPage query * - * @magentoCache all enabled * @magentoDataFixture Magento/Cms/_files/pages.php */ - public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForCmsPage(): void + public function testToCheckCmsPageRequestCacheTags(): void { $cmsPage = $this->objectManager->get(GetPageByIdentifier::class)->execute('page100', 0); $pageId = $cmsPage->getId(); @@ -92,20 +65,18 @@ public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForCmsPage(): } } QUERY; + $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); + $result = $this->graphqlController->dispatch($this->request); /** @var \Magento\Framework\App\Response\Http $response */ $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); $result->renderResult($response); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); - $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId , 'FPC']; - $this->assertEquals($expectedCacheTags, $actualCacheTags); + $this->assertEquals($expectedCacheTags, $requestedCacheTags); } } From 7ab4ddd46bbce1e7d2a69bf3e555f8ffae896d13 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Wed, 17 Apr 2019 14:41:26 -0500 Subject: [PATCH 358/585] GraphQL-577: Test coverage for tag cache generation for category - api functional test coverage for cache invalidation --- .../GraphQl/PageCache/CacheTagTest.php | 99 ++++++++++++++----- .../Magento/Catalog/_files/categories.php | 21 ++++ .../Catalog/_files/categories_rollback.php | 2 +- 3 files changed, 98 insertions(+), 24 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index 0a0ca960d5acd..0c0631ae2983b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -17,13 +17,16 @@ /** * Class CacheTagTest */ +/** + * Test the caching works properly for products and categories + */ class CacheTagTest extends GraphQlAbstract { /** * Tests if Magento cache tags and debug headers for products are generated properly - * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_url_key.php + * @magentoApiDataFixture Magento/Catalog/_files/multiple_products.php */ - public function testCacheTagsAndCacheDebugHeaderFromResponse() + public function testCacheTagsAndCacheDebugHeaderForProducts() { $this->markTestSkipped( 'This test will stay skipped until DEVOPS-4924 is resolved' @@ -79,18 +82,19 @@ public function testCacheTagsAndCacheDebugHeaderFromResponse() } /** - * Tests if Magento cache tags for categories are generated properly + * Tests if Magento cache tags for categories are generated properly. Also tests the use case for cache invalidation * - * @magentoApiDataFixture Magento/Catalog/_files/category_product.php + * @magentoApiDataFixture Magento/Catalog/_files/categories.php */ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() { - $this->markTestSkipped( + /*$this->markTestSkipped( 'This test will stay skipped until DEVOPS-4924 is resolved' - ); - $productSku = 'simple333'; - $categoryId ='333'; - $query + );*/ + $firstProductSku = 'simple-4'; + $secondProductSku = 'simple-5'; + $categoryId ='10'; + $categoryQuery = <<<'QUERY' query GetCategoryQuery($id: Int!, $pageSize: Int!, $currentPage: Int!) { category(id: $id) { @@ -110,33 +114,82 @@ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() } QUERY; $variables =[ - 'id' => 333, + 'id' => 10, 'pageSize'=> 10, 'currentPage' => 1 ]; - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, $variables, '', []); - /** @var ProductRepositoryInterface $productRepository */ - $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); - /** @var Product $product */ - $product =$productRepository->get($productSku, false, null, true); + $product1Query + = <<<QUERY + { + products(filter: {sku: {eq: "{$firstProductSku}"}}) + { + items { + id + name + sku + } + } + } +QUERY; + $product2Query + = <<<QUERY + { + products(filter: {sku: {eq: "{$secondProductSku}"}}) + { + items { + id + name + sku + } + } + } +QUERY; + + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($categoryQuery, $variables, '', []); /** cache-debug header value should be a MISS when category is loaded first time */ preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + /** @var Product $firstProduct */ + $firstProduct = $productRepository->get($firstProductSku, false, null, true); + /** @var Product $secondProduct */ + $secondProduct = $productRepository->get($secondProductSku, false, null, true); + /** checks to see if the X-Magento-Tags for category is displayed correctly */ preg_match('/X-Magento-Tags: (.*?)\n/', $responseMissHeaders, $headerCacheTags); $actualCacheTags = explode(',', rtrim($headerCacheTags[1], "\r")); - $expectedCacheTags=['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $product->getId(),'FPC']; - foreach (array_keys($actualCacheTags) as $key) { - $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); - } - /** cache-debug header value should be MISS after updating child-product and reloading the category */ - $product->setPrice(15); - $product->save(); - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, $variables, '', []); + $expectedCacheTags = + ['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $firstProduct->getId(),'cat_p_' .$secondProduct->getId(),'FPC']; + $this->assertEquals($expectedCacheTags, $actualCacheTags); + // Cach-debug header should be a MISS for product 1 during first load + $responseHeadersFirstProduct = $this->graphQlQueryForHttpHeaders($product1Query, [], '', []); + preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHeadersFirstProduct, $match); + $this->assertEquals('MISS', rtrim($match[1], "\r")); + + // Cach-debug header should be a MISS for product 2 during first load + $responseHeadersSecondProduct = $this->graphQlQueryForHttpHeaders($product2Query, [], '', []); + preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHeadersSecondProduct, $match); + $this->assertEquals('MISS', rtrim($match[1], "\r")); + + /** cache-debug header value should be MISS after updating product1 and reloading the category */ + $firstProduct->setPrice(20); + $firstProduct->save(); + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($categoryQuery, $variables, '', []); preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); + + /** cache-debug should be a MISS for product 1 after it is updated - cache invalidation */ + $responseHeadersForProd1 = $this->graphQlQueryForHttpHeaders($product1Query, [], '', []); + preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHeadersForProd1, $match); + $this->assertEquals('MISS', rtrim($match[1], "\r")); + + // Cach-debug header should be a HIT for prod 2 during second load since prod 2 should be fetched from cache + $responseHeadersSecondProduct = $this->graphQlQueryForHttpHeaders($product2Query, [], '', []); + preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHeadersSecondProduct, $match); + $this->assertEquals('HIT', rtrim($match[1], "\r")); } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php index a5ab961932461..dc2d3939cf698 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php @@ -267,3 +267,24 @@ $product->getSku(), [10, 11, 12, 13] ); + +/** @var $product \Magento\Catalog\Model\Product */ +$product = $objectManager->create(\Magento\Catalog\Model\Product::class); +$product->isObjectNew(true); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setAttributeSetId($defaultAttributeSet) + ->setStoreId(1) + ->setWebsiteIds([1]) + ->setName('Simple Product Five') + ->setSku('simple-5') + ->setPrice(10) + ->setWeight(18) + ->setStockData(['use_config_manage_stock' => 0]) + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->save(); + +$categoryLinkManagement->assignProductToCategories( + $product->getSku(), + [10, 11, 12, 13] +); \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_rollback.php index 16c2fab0c6176..6f8bfc14e5ca9 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_rollback.php @@ -14,7 +14,7 @@ // Remove products /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ $productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); -$productsToDelete = ['simple', '12345', 'simple-3', 'simple-4']; +$productsToDelete = ['simple', '12345', 'simple-3', 'simple-4','simple-5']; foreach ($productsToDelete as $sku) { try { From b99e9dd262912f35352e4e2e24a7cbb5af725bfa Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 17 Apr 2019 14:57:06 -0500 Subject: [PATCH 359/585] GraphQL-606: [Test coverage] Add virtual product to cart --- .../Customer/AddVirtualProductToCartTest.php | 24 +++++++++++-------- .../Guest/AddVirtualProductToCartTest.php | 5 ++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index f2beef7aa93c8..eaca5332b63bb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -28,6 +28,13 @@ class AddVirtualProductToCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php @@ -83,6 +90,7 @@ public function testNonExistentProductToCart() } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php @@ -102,9 +110,10 @@ public function testAddVirtualProductToGuestCart() } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/three_customers.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php */ public function testAddVirtualProductToAnotherCustomerCart() { @@ -120,15 +129,10 @@ public function testAddVirtualProductToAnotherCustomerCart() $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } - protected function setUp() - { - $objectManager = Bootstrap::getObjectManager(); - $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); - $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - } - /** * @param string $maskedQuoteId + * @param string $sku + * @param int $qty * @return string */ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string @@ -140,8 +144,8 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: $qty - sku: "$sku" + qty: {$qty} + sku: "{$sku}" } } ] diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index 20d7ee031a044..c57c82a37e9a0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -83,6 +83,7 @@ public function testNonExistentProductToCart() } /** + * _security * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php @@ -117,8 +118,8 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: $qty - sku: "$sku" + qty: {$qty} + sku: "{$sku}" } } ] From 8c34f6c72a92d9018124828b290bff429539e5aa Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 17 Apr 2019 15:08:12 -0500 Subject: [PATCH 360/585] GraphQL-605: [Test coverage] Add simple product to cart --- .../Customer/AddSimpleProductToCartTest.php | 42 ++++++++++--------- .../Guest/AddSimpleProductToCartTest.php | 9 ++-- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index 7b9df8c623c28..73b3e39721866 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -28,6 +28,13 @@ class AddSimpleProductToCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php @@ -49,40 +56,39 @@ public function testAddSimpleProductToCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ public function testAddProductToNonExistentCart() { $sku = 'simple_product'; $qty = 2; $maskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a cart with ID \"$maskedQuoteId\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a product with SKU "simple_product" */ public function testNonExistentProductToCart() { $sku = 'simple_product'; $qty = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a product with SKU \"simple_product\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php @@ -102,9 +108,10 @@ public function testAddSimpleProductToGuestCart() } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/three_customers.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php */ public function testAddSimpleProductToAnotherCustomerCart() { @@ -120,15 +127,10 @@ public function testAddSimpleProductToAnotherCustomerCart() $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } - protected function setUp() - { - $objectManager = Bootstrap::getObjectManager(); - $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); - $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - } - /** * @param string $maskedQuoteId + * @param string $sku + * @param int $qty * @return string */ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string @@ -140,8 +142,8 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: $qty - sku: "$sku" + qty: {$qty} + sku: "{$sku}" } } ] diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index f4345c9ab4826..9e0693b160851 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -66,18 +66,17 @@ public function testAddProductToNonExistentCart() /** * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a product with SKU "simple_product" */ public function testNonExistentProductToCart() { $sku = 'simple_product'; $qty = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a product with SKU \"simple_product\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query); } From a241594a44e78f59038127a9b36b30711e16aeb6 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 17 Apr 2019 15:10:47 -0500 Subject: [PATCH 361/585] GraphQL-606: [Test coverage] Add virtual product to cart --- .../Customer/AddVirtualProductToCartTest.php | 18 ++++++++---------- .../Guest/AddVirtualProductToCartTest.php | 18 ++++++++---------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index eaca5332b63bb..4ec25bb030079 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -56,36 +56,34 @@ public function testAddVirtualProductToCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ public function testAddVirtualToNonExistentCart() { $sku = 'virtual_product'; $qty = 2; $nonExistentMaskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($nonExistentMaskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a cart with ID \"$nonExistentMaskedQuoteId\"" - ); + $query = $this->getQuery($nonExistentMaskedQuoteId, $sku, $qty); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a product with SKU "virtual_product" */ public function testNonExistentProductToCart() { $sku = 'virtual_product'; $qty = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a product with SKU \"virtual_product\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index c57c82a37e9a0..3f2d734635c3e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -50,35 +50,33 @@ public function testAddVirtualProductToCart() /** * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ public function testAddVirtualToNonExistentCart() { $sku = 'virtual_product'; $qty = 1; $maskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a cart with ID \"non_existent_masked_id\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query); } /** * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a product with SKU "virtual_product" */ public function testNonExistentProductToCart() { $sku = 'virtual_product'; $qty = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a product with SKU \"virtual_product\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query); } From 965e3bf81f0a5118259595463cc7a5097ef4877e Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Wed, 17 Apr 2019 15:11:09 -0500 Subject: [PATCH 362/585] GraphQL-598: CMS Page Integration Test for Tag Cache Generation - addressed review comments --- dev/tests/integration/testsuite/Magento/Cms/_files/pages.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php b/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php index 5edb2a79b148f..0b7c3a2242fee 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php +++ b/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php @@ -18,7 +18,6 @@ ->setPageLayout('1column') ->save(); - $page = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Cms\Model\Page::class); $page->setTitle('Cms Page Design Blank') ->setIdentifier('page_design_blank') From afac739965143b3b08724e75af136e5781cab0a3 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Wed, 17 Apr 2019 16:16:26 -0500 Subject: [PATCH 363/585] GraphQL-577: Test coverage for tag cache generation for category and products - address review comments --- .../GraphQl/PageCache/CacheTagTest.php | 61 ++++++++----------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index 0c0631ae2983b..3a84d1eb519d5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -31,9 +31,6 @@ public function testCacheTagsAndCacheDebugHeaderForProducts() $this->markTestSkipped( 'This test will stay skipped until DEVOPS-4924 is resolved' ); - /** @var State $state */ - $state = Bootstrap::getObjectManager()->get(State::class); - $state->setMode(State::MODE_DEVELOPER); $productSku='simple2'; $query @@ -51,14 +48,13 @@ public function testCacheTagsAndCacheDebugHeaderForProducts() QUERY; /** cache-debug should be a MISS when product is queried for first time */ - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); - preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); - $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); /** cache-debug should be a HIT for the second round */ - $responseHitHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); - preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHitHeaders, $matchesHit); - $this->assertEquals('HIT', rtrim($matchesHit[1], "\r")); + $responseHitHeaders = $this->graphQlQueryForHttpHeaders($query); + //preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHitHeaders, $matchesHit); + $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHitHeaders); /** @var ProductRepositoryInterface $productRepository */ $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); @@ -68,17 +64,14 @@ public function testCacheTagsAndCacheDebugHeaderForProducts() $product->setPrice(15); $product->save(); /** Cache invalidation happens and cache-debug header value is a MISS after product update */ - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query, [], '', []); - preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); - $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); /** checks if cache tags for products are correctly displayed in the response header */ preg_match('/X-Magento-Tags: (.*?)\n/', $responseMissHeaders, $headerCacheTags); $actualCacheTags = explode(',', rtrim($headerCacheTags[1], "\r")); $expectedCacheTags=['cat_p','cat_p_' . $product->getId(),'FPC']; - foreach (array_keys($actualCacheTags) as $key) { - $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); - } + $this->assertEquals($expectedCacheTags, $actualCacheTags); } /** @@ -88,9 +81,9 @@ public function testCacheTagsAndCacheDebugHeaderForProducts() */ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() { - /*$this->markTestSkipped( + $this->markTestSkipped( 'This test will stay skipped until DEVOPS-4924 is resolved' - );*/ + ); $firstProductSku = 'simple-4'; $secondProductSku = 'simple-5'; $categoryId ='10'; @@ -146,11 +139,10 @@ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() } QUERY; - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($categoryQuery, $variables, '', []); + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($categoryQuery, $variables); /** cache-debug header value should be a MISS when category is loaded first time */ - preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); - $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); /** @var ProductRepositoryInterface $productRepository */ $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); @@ -165,31 +157,28 @@ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $firstProduct->getId(),'cat_p_' .$secondProduct->getId(),'FPC']; $this->assertEquals($expectedCacheTags, $actualCacheTags); + // Cach-debug header should be a MISS for product 1 during first load - $responseHeadersFirstProduct = $this->graphQlQueryForHttpHeaders($product1Query, [], '', []); - preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHeadersFirstProduct, $match); - $this->assertEquals('MISS', rtrim($match[1], "\r")); + $responseHeadersFirstProduct = $this->graphQlQueryForHttpHeaders($product1Query); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHeadersFirstProduct); // Cach-debug header should be a MISS for product 2 during first load - $responseHeadersSecondProduct = $this->graphQlQueryForHttpHeaders($product2Query, [], '', []); - preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHeadersSecondProduct, $match); - $this->assertEquals('MISS', rtrim($match[1], "\r")); + $responseHeadersSecondProduct = $this->graphQlQueryForHttpHeaders($product2Query); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHeadersSecondProduct); - /** cache-debug header value should be MISS after updating product1 and reloading the category */ + /** cache-debug header value should be MISS after updating product1 and reloading the Category */ $firstProduct->setPrice(20); $firstProduct->save(); - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($categoryQuery, $variables, '', []); + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($categoryQuery, $variables); preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); /** cache-debug should be a MISS for product 1 after it is updated - cache invalidation */ - $responseHeadersForProd1 = $this->graphQlQueryForHttpHeaders($product1Query, [], '', []); - preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHeadersForProd1, $match); - $this->assertEquals('MISS', rtrim($match[1], "\r")); - - // Cach-debug header should be a HIT for prod 2 during second load since prod 2 should be fetched from cache - $responseHeadersSecondProduct = $this->graphQlQueryForHttpHeaders($product2Query, [], '', []); - preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHeadersSecondProduct, $match); - $this->assertEquals('HIT', rtrim($match[1], "\r")); + $responseHeadersFirstProduct = $this->graphQlQueryForHttpHeaders($product1Query); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHeadersFirstProduct); + + // Cach-debug header should be a HIT for prod 2 during second load since prod 2 is fetched from cache. + $responseHeadersSecondProduct = $this->graphQlQueryForHttpHeaders($product2Query); + $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHeadersSecondProduct); } } From cede6e9afa62183d489915844f685479548c6d3c Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Wed, 17 Apr 2019 17:18:22 -0500 Subject: [PATCH 364/585] 596: Category with Products with...(deep nesting) (Integration Test for Tag Cache Generation) - Fixed review comments --- .../DeepNestedCategoriesAndProductsTest.php | 44 +++---------------- 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php index f6628be18ff5c..2ca31a3ebf293 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php @@ -10,9 +10,7 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Framework\App\Request\Http; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Serialize\SerializerInterface; -use Magento\TestFramework\Helper\Bootstrap; +use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; use Magento\TestFramework\ObjectManager; /** @@ -22,50 +20,21 @@ * @magentoDbIsolation disabled * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class DeepNestedCategoriesAndProductsTest extends \Magento\TestFramework\Indexer\TestCase +class DeepNestedCategoriesAndProductsTest extends AbstractGraphqlCacheTest { - const CONTENT_TYPE = 'application/json'; - - /** @var \Magento\Framework\ObjectManagerInterface */ - private $objectManager; - - /** @var GraphQl */ + /** @var \Magento\GraphQl\Controller\GraphQl */ private $graphql; - /** @var SerializerInterface */ - private $jsonSerializer; - - /** @var MetadataPool */ - private $metadataPool; - /** @var Http */ private $request; - /** - * @inheritdoc - */ - public static function setUpBeforeClass() - { - $db = Bootstrap::getInstance()->getBootstrap() - ->getApplication() - ->getDbInstance(); - if (!$db->isDbDumpExists()) { - throw new \LogicException('DB dump does not exist.'); - } - $db->restoreFromDbDump(); - - parent::setUpBeforeClass(); - } - /** * @inheritdoc */ protected function setUp(): void { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + parent::setUp(); $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); - $this->metadataPool = $this->objectManager->get(MetadataPool::class); $this->request = $this->objectManager->get(Http::class); } @@ -148,9 +117,6 @@ public function testDispatchForCacheHeadersOnDeepNestedQueries(): void $result = $this->graphql->dispatch($this->request); /** @var \Magento\Framework\App\Response\Http $response */ $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); $result->renderResult($response); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); @@ -161,4 +127,4 @@ public function testDispatchForCacheHeadersOnDeepNestedQueries(): void ) ); } -} +} \ No newline at end of file From af4b0446d6d29dee3583df382053df006c8a79fa Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Wed, 17 Apr 2019 17:35:16 -0500 Subject: [PATCH 365/585] GraphQL-577: Test coverage for tag cache generation for category and products - reverted fixture changes --- .../GraphQl/PageCache/CacheTagTest.php | 10 ++++----- .../Magento/Catalog/_files/categories.php | 21 ------------------- .../Catalog/_files/categories_rollback.php | 2 +- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index 3a84d1eb519d5..44ef97db35930 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -77,16 +77,16 @@ public function testCacheTagsAndCacheDebugHeaderForProducts() /** * Tests if Magento cache tags for categories are generated properly. Also tests the use case for cache invalidation * - * @magentoApiDataFixture Magento/Catalog/_files/categories.php + * @magentoApiDataFixture Magento/Catalog/_files/product_in_multiple_categories.php */ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() { $this->markTestSkipped( 'This test will stay skipped until DEVOPS-4924 is resolved' ); - $firstProductSku = 'simple-4'; - $secondProductSku = 'simple-5'; - $categoryId ='10'; + $firstProductSku = 'simple333'; + $secondProductSku = 'simple444'; + $categoryId ='4'; $categoryQuery = <<<'QUERY' query GetCategoryQuery($id: Int!, $pageSize: Int!, $currentPage: Int!) { @@ -107,7 +107,7 @@ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() } QUERY; $variables =[ - 'id' => 10, + 'id' => 4, 'pageSize'=> 10, 'currentPage' => 1 ]; diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php index dc2d3939cf698..a5ab961932461 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php @@ -267,24 +267,3 @@ $product->getSku(), [10, 11, 12, 13] ); - -/** @var $product \Magento\Catalog\Model\Product */ -$product = $objectManager->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) - ->setAttributeSetId($defaultAttributeSet) - ->setStoreId(1) - ->setWebsiteIds([1]) - ->setName('Simple Product Five') - ->setSku('simple-5') - ->setPrice(10) - ->setWeight(18) - ->setStockData(['use_config_manage_stock' => 0]) - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->save(); - -$categoryLinkManagement->assignProductToCategories( - $product->getSku(), - [10, 11, 12, 13] -); \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_rollback.php index 6f8bfc14e5ca9..16c2fab0c6176 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_rollback.php @@ -14,7 +14,7 @@ // Remove products /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ $productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); -$productsToDelete = ['simple', '12345', 'simple-3', 'simple-4','simple-5']; +$productsToDelete = ['simple', '12345', 'simple-3', 'simple-4']; foreach ($productsToDelete as $sku) { try { From 43a22d4c3af0835d2adf83c87b7aa1d7be2c4063 Mon Sep 17 00:00:00 2001 From: Hailong Zhao <hailongzh@hotmail.com> Date: Wed, 17 Apr 2019 23:23:06 -0400 Subject: [PATCH 366/585] Needs to provide the currency code explicitly in the -bash.00 verification call, otherwise the payment would fail when store's default currency is not USD. --- .../Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php b/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php index da5599984b701..8a2825a16d33a 100644 --- a/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php +++ b/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php @@ -64,6 +64,7 @@ public function requestToken(Quote $quote) $request->setTrxtype(Payflowpro::TRXTYPE_AUTH_ONLY); $request->setVerbosity('HIGH'); $request->setAmt(0); + $request->setCurrency($quote->getBaseCurrencyCode()); $request->setCreatesecuretoken('Y'); $request->setSecuretokenid($this->mathRandom->getUniqueHash()); $request->setReturnurl($this->url->getUrl('paypal/transparent/response')); From 408e38690ad884049bee9bb8cf73b9ca24aa870a Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Thu, 18 Apr 2019 10:50:52 +0530 Subject: [PATCH 367/585] disabled comment and qty field when out of stock --- .../Wishlist/view/frontend/templates/item/column/cart.phtml | 4 ++-- .../view/frontend/templates/item/column/comment.phtml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml index c85f41bbf0775..314c40c6ebecd 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml @@ -18,12 +18,12 @@ $allowedQty = $block->getMinMaxQty(); <?php endforeach;?> <div class="box-tocart"> <fieldset class="fieldset"> - <?php if ($item->canHaveQty() && $product->isVisibleInSiteVisibility() && $product->isSaleable()): ?> + <?php if ($item->canHaveQty() && $product->isVisibleInSiteVisibility()): ?> <div class="field qty"> <label class="label" for="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]"><span><?= $block->escapeHtml(__('Qty')) ?></span></label> <div class="control"> <input type="number" data-role="qty" id="qty[<?= /* @noEscape */ $block->escapeHtmlAttr($item->getId()) ?>]" class="input-text qty" data-validate="{'required-number':true,'validate-greater-than-zero':true, 'validate-item-quantity':{'minAllowed':<?= /* @noEscape */ $allowedQty['minAllowed'] ?>,'maxAllowed':<?= /* @noEscape */ $allowedQty['maxAllowed'] ?>}}" - name="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]" value="<?= /* @noEscape */ (int)($block->getAddToCartQty($item) * 1) ?>"> + name="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]" value="<?= /* @noEscape */ (int)($block->getAddToCartQty($item) * 1) ?>" <?= $product->isSaleable() ? '' : 'disabled="disabled"' ?>> </div> </div> <?php endif; ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml index 17e2404ee23cf..5ab5bc5422e7e 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml @@ -17,6 +17,6 @@ $item = $block->getItem(); <span><?= $block->escapeHtml(__('Comment')) ?></span> </label> <div class="control"> - <textarea id="product-item-comment-<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>" placeholder="<?= /* @noEscape */ $this->helper('Magento\Wishlist\Helper\Data')->defaultCommentString() ?>" name="description[<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>]" title="<?= $block->escapeHtmlAttr(__('Comment')) ?>" class="product-item-comment"><?= ($block->escapeHtml($item->getDescription())) ?></textarea> + <textarea id="product-item-comment-<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>" placeholder="<?= /* @noEscape */ $this->helper('Magento\Wishlist\Helper\Data')->defaultCommentString() ?>" name="description[<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>]" title="<?= $block->escapeHtmlAttr(__('Comment')) ?>" class="product-item-comment" <?= $item->getProduct()->isSaleable() ? '' : 'disabled="disabled"' ?>><?= ($block->escapeHtml($item->getDescription())) ?></textarea> </div> </div> From be34f65e5001ee3b17fb5a109803b14a50ae8906 Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Thu, 18 Apr 2019 11:59:52 +0530 Subject: [PATCH 368/585] Resolved git conflict --- .../Wishlist/view/frontend/templates/item/column/cart.phtml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml index 314c40c6ebecd..f296b950f3abb 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml @@ -11,7 +11,9 @@ /** @var \Magento\Wishlist\Model\Item $item */ $item = $block->getItem(); $product = $item->getProduct(); -$allowedQty = $block->getMinMaxQty(); +/** @var \Magento\Wishlist\ViewModel\AllowedQuantity $viewModel */ +$viewModel = $block->getData('allowedQuantityViewModel'); +$allowedQty = $viewModel->setItem($item)->getMinMaxQty(); ?> <?php foreach ($block->getChildNames() as $childName): ?> <?= /* @noEscape */ $block->getLayout()->renderElement($childName, false) ?> @@ -22,7 +24,7 @@ $allowedQty = $block->getMinMaxQty(); <div class="field qty"> <label class="label" for="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]"><span><?= $block->escapeHtml(__('Qty')) ?></span></label> <div class="control"> - <input type="number" data-role="qty" id="qty[<?= /* @noEscape */ $block->escapeHtmlAttr($item->getId()) ?>]" class="input-text qty" data-validate="{'required-number':true,'validate-greater-than-zero':true, 'validate-item-quantity':{'minAllowed':<?= /* @noEscape */ $allowedQty['minAllowed'] ?>,'maxAllowed':<?= /* @noEscape */ $allowedQty['maxAllowed'] ?>}}" + <input type="number" data-role="qty" id="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]" class="input-text qty" data-validate="{'required-number':true,'validate-greater-than-zero':true, 'validate-item-quantity':{'minAllowed':<?= /* @noEscape */ $allowedQty['minAllowed'] ?>,'maxAllowed':<?= /* @noEscape */ $allowedQty['maxAllowed'] ?>}}" name="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]" value="<?= /* @noEscape */ (int)($block->getAddToCartQty($item) * 1) ?>" <?= $product->isSaleable() ? '' : 'disabled="disabled"' ?>> </div> </div> From 92d0f9324b991f2fdd92692ed643f5be60211148 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Thu, 18 Apr 2019 11:16:16 +0300 Subject: [PATCH 369/585] Fix static tests. --- .../Annotation/AnnotationFormatValidator.php | 23 +++++++++++++++---- .../Annotation/MethodArgumentsSniff.php | 13 +++++++---- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php index b102fa87b76a8..33df6e8ae54f1 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ declare(strict_types=1); + namespace Magento\Sniffs\Annotation; use PHP_CodeSniffer\Files\File; @@ -261,14 +262,13 @@ public function validateTagAligningFormat(File $phpcsFile, int $commentStartPtr) $noAlignmentPositions = []; $actualPositions = []; $stackPtr = null; - foreach ($tokens[$commentStartPtr]['comment_tags'] as $position => $tag) { + foreach ($tokens[$commentStartPtr]['comment_tags'] as $tag) { $content = $tokens[$tag]['content']; if (preg_match('/^@/', $content) && ($tokens[$tag]['line'] === $tokens[$tag + 2]['line'])) { $noAlignmentPositions[] = $tokens[$tag + 1]['column'] + 1; $actualPositions[] = $tokens[$tag + 2]['column']; $stackPtr = $stackPtr ?? $tag; } - } if (!$this->allTagsAligned($actualPositions) @@ -281,11 +281,26 @@ public function validateTagAligningFormat(File $phpcsFile, int $commentStartPtr) } } - private function allTagsAligned(array $actualPositions) { + /** + * Check whether all docblock params are aligned. + * + * @param array $actualPositions + * @return bool + */ + private function allTagsAligned(array $actualPositions) + { return count(array_unique($actualPositions)) === 1; } - private function noneTagsAligned(array $actualPositions, array $noAlignmentPositions) { + /** + * Check whether all docblock params are not aligned. + * + * @param array $actualPositions + * @param array $noAlignmentPositions + * @return bool + */ + private function noneTagsAligned(array $actualPositions, array $noAlignmentPositions) + { return $actualPositions === $noAlignmentPositions; } diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php index 5bd4667c4f4be..50efca9b1ed23 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php @@ -124,7 +124,8 @@ private function getMethodArguments(File $phpcsFile, int $openParenthesisPtr, in private function getMethodParameters(array $paramDefinitions): array { $paramName = []; - for ($i = 0; $i < count($paramDefinitions); $i++) { + $paramCount = count($paramDefinitions); + for ($i = 0; $i < $paramCount; $i++) { if (isset($paramDefinitions[$i]['paramName'])) { $paramName[] = $paramDefinitions[$i]['paramName']; } @@ -371,10 +372,11 @@ private function validateDuplicateAnnotationDoesnotExists( $parametersCount = count($paramPointers); if ($argumentsCount <= $parametersCount && $argumentsCount > 0) { $duplicateParameters = []; - for ($i = 0; $i < count($paramDefinitions); $i++) { + $paramCount = count($paramDefinitions); + for ($i = 0; $i < $paramCount; $i++) { if (isset($paramDefinitions[$i]['paramName'])) { $parameterContent = $paramDefinitions[$i]['paramName']; - for ($j = $i + 1; $j < count($paramDefinitions); $j++) { + for ($j = $i + 1; $j < $paramCount; $j++) { if (isset($paramDefinitions[$j]['paramName']) && $parameterContent === $paramDefinitions[$j]['paramName'] ) { @@ -517,7 +519,7 @@ private function validateMethodParameterAnnotations( $paramPointers ); $tokens = $phpcsFile->getTokens(); - for ($ptr = 0; $ptr < count($methodArguments); $ptr++) { + for ($ptr = 0; $ptr < $argumentCount; $ptr++) { if (isset($paramPointers[$ptr])) { $this->validateArgumentNameInParameterAnnotationExists( $stackPtr, @@ -614,7 +616,8 @@ private function validateFormattingConsistency( $argumentPositions = []; $commentPositions = []; $tokens = $phpcsFile->getTokens(); - for ($ptr = 0; $ptr < count($methodArguments); $ptr++) { + $argumentCount = count($methodArguments); + for ($ptr = 0; $ptr < $argumentCount; $ptr++) { if (isset($paramPointers[$ptr])) { $paramContent = $tokens[$paramPointers[$ptr] + 2]['content']; $paramDefinition = $paramDefinitions[$ptr]; From c2e7399d4082cdc1ab1e5b11195f7486b32cefc8 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Thu, 18 Apr 2019 12:04:54 +0300 Subject: [PATCH 370/585] Fix static tests. --- .../Catalog/Api/Data/CategoryInterface.php | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Api/Data/CategoryInterface.php b/app/code/Magento/Catalog/Api/Data/CategoryInterface.php index c1ca89f51ea58..1940a0ac80c0b 100644 --- a/app/code/Magento/Catalog/Api/Data/CategoryInterface.php +++ b/app/code/Magento/Catalog/Api/Data/CategoryInterface.php @@ -1,7 +1,5 @@ <?php /** - * Category data interface - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -9,6 +7,8 @@ namespace Magento\Catalog\Api\Data; /** + * Category data interface. + * * @api * @since 100.0.2 */ @@ -46,11 +46,15 @@ interface CategoryInterface extends \Magento\Framework\Api\CustomAttributesDataI /**#@-*/ /** + * Retrieve category id. + * * @return int|null */ public function getId(); /** + * Set category id. + * * @param int $id * @return $this */ @@ -132,60 +136,82 @@ public function getLevel(); public function setLevel($level); /** + * Retrieve children ids comma separated. + * * @return string|null */ public function getChildren(); /** + * Retrieve category creation date and time. + * * @return string|null */ public function getCreatedAt(); /** + * Set category creation date and time. + * * @param string $createdAt * @return $this */ public function setCreatedAt($createdAt); /** + * Retrieve category last update date and time. + * * @return string|null */ public function getUpdatedAt(); /** + * Set category last update date and time. + * * @param string $updatedAt * @return $this */ public function setUpdatedAt($updatedAt); /** + * Retrieve category full path. + * * @return string|null */ public function getPath(); /** + * Set category full path. + * * @param string $path * @return $this */ public function setPath($path); /** + * Retrieve available sort by for category. + * * @return string[]|null */ public function getAvailableSortBy(); /** + * Set available sort by for category. + * * @param string[]|string $availableSortBy * @return $this */ public function setAvailableSortBy($availableSortBy); /** + * Get category is included in menu. + * * @return bool|null */ public function getIncludeInMenu(); /** + * Set category is included in menu. + * * @param bool $includeInMenu * @return $this */ From 3beb15adfd769cbf259f45313948e6e3d04dcd4d Mon Sep 17 00:00:00 2001 From: niravkrish <nirav.patel@krishtechnolabs.com> Date: Thu, 18 Apr 2019 15:09:02 +0530 Subject: [PATCH 371/585] fixed - issue 21596 --- .../view/frontend/web/js/view/payment.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js index c17e5e40d5c98..ad6f39b7d6d5f 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js @@ -66,9 +66,21 @@ define([ navigate: function () { var self = this; - getPaymentInformation().done(function () { - self.isVisible(true); - }); + if(!self.hasShippingMethod()) { + this.isVisible(false); + stepNavigator.setHash('shipping'); + } else { + getPaymentInformation().done(function () { + self.isVisible(true); + }); + } + }, + + /** + * @return {Boolean} + */ + hasShippingMethod: function () { + return window.checkoutConfig.selectedShippingMethod !== null; }, /** From 0ade930796f0857030823dcce9c2bcb4a1a483bd Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 18 Apr 2019 13:22:46 +0300 Subject: [PATCH 372/585] magento/magento2#21711: Static test fix. --- .../Downloadable/Observer/UpdateLinkPurchasedObserver.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php index 067c91981cd89..db391ccda6866 100644 --- a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php +++ b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php @@ -10,7 +10,6 @@ use Magento\Framework\Event\ObserverInterface; /** - * Class UpdateLinkPurchasedObserver * Assign Downloadable links to customer created after issuing guest order. */ class UpdateLinkPurchasedObserver implements ObserverInterface @@ -47,9 +46,10 @@ public function __construct( } /** - * re-save order data after order update + * Re-save order data after order update. + * * @param \Magento\Framework\Event\Observer $observer - * @return $this|void + * @return $this */ public function execute(\Magento\Framework\Event\Observer $observer) { From 432334e33cf028edd74aaf04e4c31468c4808d80 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 18 Apr 2019 14:22:27 +0300 Subject: [PATCH 373/585] magento/magento2#22339: Static test fix. --- .../Magento/Framework/Setup/Patch/DependentPatchInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php b/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php index 21fafd273f9ed..7573441fa9466 100644 --- a/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php +++ b/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php @@ -20,7 +20,7 @@ interface DependentPatchInterface /** * Get array of patches that have to be executed prior to this. * - * example of implementation: + * Example of implementation: * * [ * \Vendor_Name\Module_Name\Setup\Patch\Patch1::class, From fd92027ac2c34c47ff1f09dafbd1c01b549adc47 Mon Sep 17 00:00:00 2001 From: hiren pandya <hiren.pandya@krishtechnolabs.com> Date: Thu, 18 Apr 2019 17:28:53 +0530 Subject: [PATCH 374/585] Resolve issue of Backup tool not correctly detecting .maintenance.flag --- app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php b/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php index 53f45aff50cbc..715df71501f7e 100644 --- a/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php +++ b/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php @@ -55,7 +55,9 @@ public function execute() $this->_coreRegistry->register('backup_manager', $backupManager); if ($this->getRequest()->getParam('maintenance_mode')) { - if (!$this->maintenanceMode->set(true)) { + $this->maintenanceMode->set(true); + + if (!$this->maintenanceMode->isOn()) { $response->setError( __( 'You need more permissions to activate maintenance mode right now.' From 875fa4ce039a177d4f0f597f392a68218cfea007 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 18 Apr 2019 15:31:02 +0300 Subject: [PATCH 375/585] magento/magento2#21856: Static test fix. --- lib/internal/Magento/Framework/Validator/Factory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/internal/Magento/Framework/Validator/Factory.php b/lib/internal/Magento/Framework/Validator/Factory.php index 87c29dd6681c3..2a296f7cdcb24 100644 --- a/lib/internal/Magento/Framework/Validator/Factory.php +++ b/lib/internal/Magento/Framework/Validator/Factory.php @@ -52,6 +52,7 @@ class Factory * @param ObjectManagerInterface $objectManager * @param Reader $moduleReader * @param FrontendInterface $cache @deprecated + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( ObjectManagerInterface $objectManager, From e949e85159dd00640106be24ff72b79441cba121 Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Wed, 17 Apr 2019 09:36:28 +0300 Subject: [PATCH 376/585] Don't skip row on import if image not available. --- .../Model/Import/Product.php | 8 +++- .../Model/Import/ProductTest.php | 39 +++++++++++++++++++ ...ucts_to_import_with_non_existing_image.csv | 2 + 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 404c31296e4dd..c6ce3e24ce02f 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -1798,7 +1798,13 @@ protected function _saveProducts() $uploadedImages[$columnImage] = $uploadedFile; } else { unset($rowData[$column]); - $this->skipRow($rowNum, ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE); + $this->addRowError( + ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE, + $rowNum, + null, + null, + ProcessingError::ERROR_LEVEL_NOT_CRITICAL + ); } } else { $uploadedFile = $uploadedImages[$columnImage]; diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index c4c6d3ba2d1d2..dd2237d6080ca 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -1590,6 +1590,45 @@ public function testAddUpdateProductWithInvalidUrlKeys() : void } } + /** + * Make sure the non existing image in the csv file won't erase the qty key of the existing products. + * + * @magentoDataFixture Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ + public function testImportWithNonExistingImage() + { + $products = [ + 'simple_new' => 100, + ]; + $filesystem = $this->objectManager->create(\Magento\Framework\Filesystem::class); + $directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); + $source = $this->objectManager->create( + \Magento\ImportExport\Model\Import\Source\Csv::class, + [ + 'file' => __DIR__ . '/_files/products_to_import_with_non_existing_image.csv', + 'directory' => $directory + ] + ); + + $errors = $this->_model->setParameters( + ['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product'] + ) + ->setSource($source) + ->validateData(); + + $this->assertTrue($errors->getErrorsCount() == 0); + $this->_model->importData(); + + $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + foreach ($products as $productSku => $productQty) { + $product = $productRepository->get($productSku); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $this->assertEquals($productQty, $stockItem->getQty()); + } + } + /** * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php * @magentoDbIsolation disabled diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv new file mode 100644 index 0000000000000..8122433a8c9e1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv @@ -0,0 +1,2 @@ +sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label1,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,related_skus,crosssell_skus,upsell_skus,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,associated_skus +simple_new,,Default,simple,,base,New Product,,,,1,Taxable Goods,"Catalog, Search",10,,,,new-product,New Product,New Product,New Product ,/no/exists/image/magento_image.jpg,Image Label,magento_small_image.jpg,Small Image Label,magento_thumbnail.jpg,Thumbnail Label,magento_image.jpg,Image Label,10/20/15 07:05,10/20/15 07:05,,,Block after Info Column,,,,,,,,,,,,,"has_options=1,quantity_and_stock_status=In Stock,required_options=1",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,0,1,1,0,0,0,1,,,,"magento_additional_image_one.jpg, magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two",,,,,,,, From 3f5d1ff2834ae69e1ced5b8abf2d51c543111422 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Thu, 18 Apr 2019 16:18:31 +0300 Subject: [PATCH 377/585] MC-5266: Create not anchor subcategory specifying all fields --- .../Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml index ea6808ee2a7f5..663439fd62a1d 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml @@ -17,7 +17,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" /> </variation> <variation name="CreateCategoryEntityTestVariation2_RootCategory_AllFields"> - <data name="issue" xsi:type="string">MAGETWO-60635: [CE][Categories] Design update dates are incorrect after save</data> <data name="description" xsi:type="string">Create root category with all fields</data> <data name="addCategory" xsi:type="string">addRootCategory</data> <data name="category/data/is_active" xsi:type="string">Yes</data> @@ -58,7 +57,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage" /> </variation> <variation name="CreateCategoryEntityTestVariation4_Subcategory_AllFields"> - <data name="issue" xsi:type="string">MAGETWO-60635: [CE][Categories] Design update dates are incorrect after save</data> <data name="description" xsi:type="string">Create not anchor subcategory specifying all fields</data> <data name="addCategory" xsi:type="string">addSubcategory</data> <data name="category/data/parent_id/dataset" xsi:type="string">default_category</data> From 1cb3488686fb99814edcc0a898acc8a26f2ab16a Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 18 Apr 2019 16:22:28 +0300 Subject: [PATCH 378/585] magento/magento2#19913: Static test fix. --- app/code/Magento/Webapi/Controller/PathProcessor.php | 2 +- .../Webapi/Test/Unit/Controller/PathProcessorTest.php | 5 ++++- .../WebapiAsync/Test/Unit/Controller/PathProcessorTest.php | 3 +++ .../Magento/Webapi/Controller/PathProcessorTest.php | 3 +++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Webapi/Controller/PathProcessor.php b/app/code/Magento/Webapi/Controller/PathProcessor.php index b5f0be97de2f2..f32c93fb0c761 100644 --- a/app/code/Magento/Webapi/Controller/PathProcessor.php +++ b/app/code/Magento/Webapi/Controller/PathProcessor.php @@ -1,9 +1,9 @@ <?php - /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Webapi\Controller; use Magento\Framework\App\ObjectManager; diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php index 513e0cbafcbbd..e587756eec7bf 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/PathProcessorTest.php @@ -8,6 +8,9 @@ use Magento\Store\Model\Store; +/** + * Test for Magento\Webapi\Controller\PathProcessor class. + */ class PathProcessorTest extends \PHPUnit\Framework\TestCase { /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\StoreManagerInterface */ @@ -59,7 +62,7 @@ public function testAllStoreCode($storeCodeInPath, $storeCodeSet, $setCurrentSto $this->storeManagerMock->expects($this->exactly($setCurrentStoreCallCtr)) ->method('setCurrentStore') ->with($storeCodeSet); - if($setCurrentStoreCallCtr > 0) { + if ($setCurrentStoreCallCtr > 0) { $this->localeResolverMock->expects($this->once()) ->method('emulate'); } diff --git a/app/code/Magento/WebapiAsync/Test/Unit/Controller/PathProcessorTest.php b/app/code/Magento/WebapiAsync/Test/Unit/Controller/PathProcessorTest.php index cea7a4168ea4e..570df6afd3c5d 100644 --- a/app/code/Magento/WebapiAsync/Test/Unit/Controller/PathProcessorTest.php +++ b/app/code/Magento/WebapiAsync/Test/Unit/Controller/PathProcessorTest.php @@ -10,6 +10,9 @@ use Magento\Store\Model\Store; +/** + * Test for Magento\Webapi\Controller\PathProcessor class. + */ class PathProcessorTest extends \PHPUnit\Framework\TestCase { /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\StoreManagerInterface */ diff --git a/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php b/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php index 43aa788dea3a8..14fbc2ffc67d5 100644 --- a/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php +++ b/dev/tests/integration/testsuite/Magento/Webapi/Controller/PathProcessorTest.php @@ -8,6 +8,9 @@ use Magento\Store\Model\Store; +/** + * Test for Magento\Webapi\Controller\PathProcessor class. + */ class PathProcessorTest extends \PHPUnit\Framework\TestCase { /** From d4eeb4400790989ca35cc36e801c73b62242c36d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Culotta?= <damianculotta@gmail.com> Date: Thu, 18 Apr 2019 10:47:02 -0300 Subject: [PATCH 379/585] Checkout Totals Sort Order fields can not be empty and should be a number. --- app/code/Magento/Sales/etc/adminhtml/system.xml | 5 +++++ app/code/Magento/Weee/etc/adminhtml/system.xml | 1 + 2 files changed, 6 insertions(+) diff --git a/app/code/Magento/Sales/etc/adminhtml/system.xml b/app/code/Magento/Sales/etc/adminhtml/system.xml index 2dc467d6ca247..e437918b683b2 100644 --- a/app/code/Magento/Sales/etc/adminhtml/system.xml +++ b/app/code/Magento/Sales/etc/adminhtml/system.xml @@ -27,18 +27,23 @@ <label>Checkout Totals Sort Order</label> <field id="discount" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> <label>Discount</label> + <validate>required-number validate-number</validate> </field> <field id="grand_total" translate="label" type="text" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> <label>Grand Total</label> + <validate>required-number validate-number</validate> </field> <field id="shipping" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> <label>Shipping</label> + <validate>required-number validate-number</validate> </field> <field id="subtotal" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> <label>Subtotal</label> + <validate>required-number validate-number</validate> </field> <field id="tax" translate="label" type="text" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> <label>Tax</label> + <validate>required-number validate-number</validate> </field> </group> <group id="reorder" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> diff --git a/app/code/Magento/Weee/etc/adminhtml/system.xml b/app/code/Magento/Weee/etc/adminhtml/system.xml index ae02b27d10c72..d3e9efb8f0b46 100644 --- a/app/code/Magento/Weee/etc/adminhtml/system.xml +++ b/app/code/Magento/Weee/etc/adminhtml/system.xml @@ -44,6 +44,7 @@ <group id="totals_sort"> <field id="weee" translate="label" type="text" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> <label>Fixed Product Tax</label> + <validate>required-number validate-number</validate> </field> </group> </section> From 149294b87a63ef89da774862d5ebcacee47975ff Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 18 Apr 2019 16:50:30 +0300 Subject: [PATCH 380/585] magento/magento2#21816: Static test fix. --- .../Magento/Framework/Data/Form/Element/Textarea.php | 10 +++++----- .../Data/Test/Unit/Form/Element/TextareaTest.php | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php b/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php index 47c89e0615df3..1970ebeb9544e 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php @@ -4,15 +4,15 @@ * See COPYING.txt for license details. */ -/** - * Form textarea element - * - * @author Magento Core Team <core@magentocommerce.com> - */ namespace Magento\Framework\Data\Form\Element; use Magento\Framework\Escaper; +/** + * Form textarea element. + * + * @author Magento Core Team <core@magentocommerce.com> + */ class Textarea extends AbstractElement { /** diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php index 4653aa2a50769..eec85ca35775d 100644 --- a/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php +++ b/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php @@ -4,11 +4,11 @@ * See COPYING.txt for license details. */ -/** - * Tests for \Magento\Framework\Data\Form\Element\Textarea - */ namespace Magento\Framework\Data\Test\Unit\Form\Element; +/** + * Tests for \Magento\Framework\Data\Form\Element\Textarea class. + */ class TextareaTest extends \PHPUnit\Framework\TestCase { /** From 233e4c51f7d525f4573b11a24ae5a81c13762343 Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Wed, 10 Apr 2019 12:04:19 +0300 Subject: [PATCH 381/585] Disabling "Display on Product Details Page" the button is shown anyway. --- .../Magento/Paypal/Model/SmartButtonConfig.php | 3 ++- .../Test/Unit/Model/_files/expected_config.php | 15 ++++++++++----- .../web/js/in-context/product-express-checkout.js | 6 +++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Paypal/Model/SmartButtonConfig.php b/app/code/Magento/Paypal/Model/SmartButtonConfig.php index 80a0d477216b0..c491f2978e560 100644 --- a/app/code/Magento/Paypal/Model/SmartButtonConfig.php +++ b/app/code/Magento/Paypal/Model/SmartButtonConfig.php @@ -67,7 +67,8 @@ public function getConfig(string $page): array 'locale' => $this->localeResolver->getLocale(), 'allowedFunding' => $this->getAllowedFunding($page), 'disallowedFunding' => $this->getDisallowedFunding(), - 'styles' => $this->getButtonStyles($page) + 'styles' => $this->getButtonStyles($page), + 'isVisibleOnProductPage' => (int)$this->config->getValue('visible_on_product') ]; } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/_files/expected_config.php b/app/code/Magento/Paypal/Test/Unit/Model/_files/expected_config.php index 3a76d11e51374..1442642a324b9 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/_files/expected_config.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/_files/expected_config.php @@ -31,7 +31,8 @@ 'shape' => 'pillow', 'label' => 'installment', 'installmentperiod' => 0 - ] + ], + 'isVisibleOnProductPage' => 0 ] ], 'checkout' => [ @@ -59,7 +60,8 @@ 'shape' => 'pillow', 'label' => 'installment', 'installmentperiod' => 0 - ] + ], + 'isVisibleOnProductPage' => 0 ] ], 'mini_cart' => [ @@ -86,7 +88,8 @@ 'color' => 'gold', 'shape' => 'rect', 'label' => 'paypal' - ] + ], + 'isVisibleOnProductPage' => 0 ] ], 'mini_cart' => [ @@ -113,7 +116,8 @@ 'color' => 'gold', 'shape' => 'rect', 'label' => 'paypal' - ] + ], + 'isVisibleOnProductPage' => 0 ] ], 'product' => [ @@ -140,7 +144,8 @@ 'color' => 'gold', 'shape' => 'rect', 'label' => 'paypal', - ] + ], + 'isVisibleOnProductPage' => 0 ] ] ]; diff --git a/app/code/Magento/Paypal/view/frontend/web/js/in-context/product-express-checkout.js b/app/code/Magento/Paypal/view/frontend/web/js/in-context/product-express-checkout.js index 413820cc731ac..f4adaae06a112 100644 --- a/app/code/Magento/Paypal/view/frontend/web/js/in-context/product-express-checkout.js +++ b/app/code/Magento/Paypal/view/frontend/web/js/in-context/product-express-checkout.js @@ -24,7 +24,11 @@ define([ customer = customerData.get('customer'); this._super(); - this.renderPayPalButtons(element); + + if (config.clientConfig.isVisibleOnProductPage) { + this.renderPayPalButtons(element); + } + this.declinePayment = !customer().firstname && !cart().isGuestCheckoutAllowed; return this; From 6374f9ddd3c51aa1e4cc96b5e2339c236028c665 Mon Sep 17 00:00:00 2001 From: hiren pandya <hiren.pandya@krishtechnolabs.com> Date: Thu, 18 Apr 2019 19:57:29 +0530 Subject: [PATCH 382/585] Resolve Rollback issue --- .../Magento/Backup/Controller/Adminhtml/Index/Rollback.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php b/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php index 0451f6ed09bd1..51fa0ef8f65ad 100644 --- a/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php +++ b/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php @@ -82,7 +82,9 @@ public function execute() } if ($this->getRequest()->getParam('maintenance_mode')) { - if (!$this->maintenanceMode->set(true)) { + $this->maintenanceMode->set(true); + + if (!$this->maintenanceMode->isOn()) { $response->setError( __( 'You need more permissions to activate maintenance mode right now.' From b5683e86bf6ca0554ca63e3fe9b93ab73558370f Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Thu, 18 Apr 2019 10:21:48 -0500 Subject: [PATCH 383/585] Fix for issue #21299. Change HEAD action mapping to GET action interface and add HEAD request handling --- .../Framework/App/Test/Unit/HttpTest.php | 10 +++---- .../Test/Unit/Transfer/Adapter/HttpTest.php | 4 +-- .../Framework/File/Transfer/Adapter/Http.php | 27 +++++++++++-------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php index 23e58bd3df1e8..dbb315e88a526 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php @@ -181,13 +181,9 @@ public function testLaunchException() $this->setUpLaunch(); $this->frontControllerMock->expects($this->once()) ->method('dispatch') - ->with($this->requestMock)->will( - $this->returnCallback( - function () { - // phpcs:ignore Magento2.Exceptions.DirectThrow - throw new \Exception('Message'); - } - ) + ->with($this->requestMock) + ->willThrowException( + new \Exception('Message') ); $this->http->launch(); } diff --git a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php index 8147ed4eb0005..023c4cc4ddba6 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php @@ -73,10 +73,10 @@ public function testSend(): void $this->mime->expects($this->once()) ->method('getMimeType') ->with($file) - ->will($this->returnValue($contentType)); + ->willReturn($contentType); $this->request->expects($this->once()) ->method('isHead') - ->will($this->returnValue(false)); + ->willReturn(false); $this->expectOutputString(file_get_contents($file)); $this->object->send($file); diff --git a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php index 8c09fbdc45124..c57952e7027d5 100644 --- a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php +++ b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php @@ -6,40 +6,45 @@ namespace Magento\Framework\File\Transfer\Adapter; +use Magento\Framework\HTTP\PhpEnvironment\Response; +use Magento\Framework\File\Mime; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\App\ObjectManager; + /** * File adapter to send the file to the client. */ class Http { /** - * @var \Magento\Framework\HTTP\PhpEnvironment\Response + * @var Response */ private $response; /** - * @var \Magento\Framework\File\Mime + * @var Mime */ private $mime; /** - * @var \Magento\Framework\App\Request\Http + * @var HttpRequest */ private $request; /** - * @param \Magento\Framework\HTTP\PhpEnvironment\Response $response - * @param \Magento\Framework\File\Mime $mime - * @param \Magento\Framework\App\Request\Http|null $request + * @param Response $response + * @param Mime $mime + * @param HttpRequest|null $request */ public function __construct( - \Magento\Framework\HTTP\PhpEnvironment\Response $response, - \Magento\Framework\File\Mime $mime, - \Magento\Framework\App\Request\Http $request = null + Response $response, + Mime $mime, + HttpRequest $request = null ) { $this->response = $response; $this->mime = $mime; - $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); - $this->request = $request ?: $objectManager->get(\Magento\Framework\App\Request\Http::class); + $objectManager = ObjectManager::getInstance(); + $this->request = $request ?: $objectManager->get(HttpRequest::class); } /** From 740e4bd80021fbfc8a781c3137c4b9c5cc0b176c Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Thu, 18 Apr 2019 10:42:25 -0500 Subject: [PATCH 384/585] Fix for issue #21299. Change HEAD action mapping to GET action interface and add HEAD request handling --- lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php index c57952e7027d5..cd42c8d04b477 100644 --- a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php +++ b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php @@ -10,6 +10,7 @@ use Magento\Framework\File\Mime; use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\App\ObjectManager; +use Zend\Http\Headers; /** * File adapter to send the file to the client. @@ -114,7 +115,7 @@ private function getFilePath($options): string private function prepareResponse($options, string $filepath): void { $mimeType = $this->mime->getMimeType($filepath); - if (is_array($options) && isset($options['headers']) && $options['headers'] instanceof \Zend\Http\Headers) { + if (is_array($options) && isset($options['headers']) && $options['headers'] instanceof Headers) { $this->response->setHeaders($options['headers']); } $this->response->setHeader('Content-length', filesize($filepath)); From b14d3246315fb4454b1aaf1c7c1e4e33056fc47d Mon Sep 17 00:00:00 2001 From: Iryna Lagno <ilagno@adobe.com> Date: Thu, 18 Apr 2019 11:24:06 -0500 Subject: [PATCH 385/585] MAGETWO-99210: Magento\Install\Test\TestCase\InstallTest is failing on php 7.1 -revert MQE-1352: bug fix in dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php --- .../lib/Magento/Mtf/Util/Command/Cli.php | 41 +++-------- .../Mtf/Util/Command/File/Export/Reader.php | 38 +++------- .../Command/File/Export/ReaderInterface.php | 2 +- .../lib/Magento/Mtf/Util/Command/File/Log.php | 38 +++------- .../Mtf/Util/Command/GeneratedCode.php | 39 ++--------- .../lib/Magento/Mtf/Util/Command/Locales.php | 42 +++-------- .../Magento/Mtf/Util/Command/PathChecker.php | 43 +++--------- .../lib/Magento/Mtf/Util/Command/Website.php | 40 ++++------- .../CurlTransport/BackendDecorator.php | 69 +++++-------------- .../CurlTransport/WebapiDecorator.php | 32 +-------- .../TestCase/ExportAdvancedPricingTest.php | 7 +- .../TestCase/ExportCustomerAddressesTest.php | 3 +- dev/tests/functional/utils/authenticate.php | 29 -------- dev/tests/functional/utils/command.php | 31 +++++---- .../utils/deleteMagentoGeneratedCode.php | 12 +--- dev/tests/functional/utils/export.php | 46 +++++++------ dev/tests/functional/utils/locales.php | 31 ++++----- dev/tests/functional/utils/log.php | 29 ++++---- dev/tests/functional/utils/pathChecker.php | 24 +++---- dev/tests/functional/utils/website.php | 47 ++++++------- 20 files changed, 200 insertions(+), 443 deletions(-) delete mode 100644 dev/tests/functional/utils/authenticate.php diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php index f0abd280f3ebc..8fa22122cce89 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php @@ -8,7 +8,6 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Perform bin/magento commands from command line for functional tests executions. @@ -18,7 +17,7 @@ class Cli /** * Url to command.php. */ - const URL = '/dev/tests/functional/utils/command.php'; + const URL = 'dev/tests/functional/utils/command.php'; /** * Curl transport protocol. @@ -27,21 +26,12 @@ class Cli */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -53,31 +43,22 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function execute($command, $options = []) { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray($command, $options), - CurlInterface::POST, - [] - ); - $this->transport->read(); - $this->transport->close(); + $curl = $this->transport; + $curl->write($this->prepareUrl($command, $options), [], CurlInterface::GET); + $curl->read(); + $curl->close(); } /** - * Prepare parameter array. + * Prepare url. * * @param string $command * @param array $options [optional] - * @return array + * @return string */ - private function prepareParamArray($command, $options = []) + private function prepareUrl($command, $options = []) { - if (!empty($options)) { - $command .= ' ' . implode(' ', $options); - } - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'command' => urlencode($command) - ]; + $command .= ' ' . implode(' ', $options); + return $_ENV['app_frontend_url'] . self::URL . '?command=' . urlencode($command); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php index 69df78a5cad64..79dd435ada7e6 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php @@ -3,12 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Mtf\Util\Command\File\Export; use Magento\Mtf\ObjectManagerInterface; use Magento\Mtf\Util\Protocol\CurlTransport; use Magento\Mtf\Util\Protocol\CurlInterface; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * File reader for Magento export files. @@ -36,29 +36,16 @@ class Reader implements ReaderInterface */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @param ObjectManagerInterface $objectManager * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler * @param string $template */ - public function __construct( - ObjectManagerInterface $objectManager, - CurlTransport $transport, - WebapiDecorator $webapiHandler, - $template - ) { + public function __construct(ObjectManagerInterface $objectManager, CurlTransport $transport, $template) + { $this->objectManager = $objectManager; $this->template = $template; $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -83,27 +70,20 @@ public function getData() */ private function getFiles() { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray(), - CurlInterface::POST, - [] - ); + $this->transport->write($this->prepareUrl(), [], CurlInterface::GET); $serializedFiles = $this->transport->read(); $this->transport->close(); + // phpcs:ignore Magento2.Security.InsecureFunction return unserialize($serializedFiles); } /** - * Prepare parameter array. + * Prepare url. * - * @return array + * @return string */ - private function prepareParamArray() + private function prepareUrl() { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'template' => urlencode($this->template) - ]; + return $_ENV['app_frontend_url'] . self::URL . '?template=' . urlencode($this->template); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php index 3666e8643efa3..93f7cf1ce9764 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php @@ -14,7 +14,7 @@ interface ReaderInterface /** * Url to export.php. */ - const URL = '/dev/tests/functional/utils/export.php'; + const URL = 'dev/tests/functional/utils/export.php'; /** * Exporting files as Data object from Magento. diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php index 820a5b0a82228..f4e55682857a2 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php @@ -7,7 +7,6 @@ namespace Magento\Mtf\Util\Command\File; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Get content of log file in var/log folder. @@ -17,7 +16,7 @@ class Log /** * Url to log.php. */ - const URL = '/dev/tests/functional/utils/log.php'; + const URL = 'dev/tests/functional/utils/log.php'; /** * Curl transport protocol. @@ -26,21 +25,12 @@ class Log */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -51,28 +41,22 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function getFileContent($name) { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray($name), - CurlInterface::POST, - [] - ); - $data = $this->transport->read(); - $this->transport->close(); + $curl = $this->transport; + $curl->write($this->prepareUrl($name), [], CurlTransport::GET); + $data = $curl->read(); + $curl->close(); + // phpcs:ignore Magento2.Security.InsecureFunction return unserialize($data); } /** - * Prepare parameter array. + * Prepare url. * * @param string $name - * @return array + * @return string */ - private function prepareParamArray($name) + private function prepareUrl($name) { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'name' => urlencode($name) - ]; + return $_ENV['app_frontend_url'] . self::URL . '?name=' . urlencode($name); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php index a9fefa25ffa24..dde3409ed1562 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php @@ -7,7 +7,6 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * GeneratedCode removes generated code of Magento (like generated/code and generated/metadata). @@ -17,7 +16,7 @@ class GeneratedCode /** * Url to deleteMagentoGeneratedCode.php. */ - const URL = '/dev/tests/functional/utils/deleteMagentoGeneratedCode.php'; + const URL = 'dev/tests/functional/utils/deleteMagentoGeneratedCode.php'; /** * Curl transport protocol. @@ -26,21 +25,12 @@ class GeneratedCode */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -50,25 +40,10 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function delete() { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray(), - CurlInterface::POST, - [] - ); - $this->transport->read(); - $this->transport->close(); - } - - /** - * Prepare parameter array. - * - * @return array - */ - private function prepareParamArray() - { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()) - ]; + $url = $_ENV['app_frontend_url'] . self::URL; + $curl = $this->transport; + $curl->write($url, [], CurlInterface::GET); + $curl->read(); + $curl->close(); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php index a55d803f43087..f669d91f2f2e5 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php @@ -7,7 +7,6 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Returns array of locales depends on fetching type. @@ -27,7 +26,7 @@ class Locales /** * Url to locales.php. */ - const URL = '/dev/tests/functional/utils/locales.php'; + const URL = 'dev/tests/functional/utils/locales.php'; /** * Curl transport protocol. @@ -36,21 +35,12 @@ class Locales */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @param CurlTransport $transport Curl transport protocol - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -61,28 +51,12 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function getList($type = self::TYPE_ALL) { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray($type), - CurlInterface::POST, - [] - ); - $result = $this->transport->read(); - $this->transport->close(); - return explode('|', $result); - } + $url = $_ENV['app_frontend_url'] . self::URL . '?type=' . $type; + $curl = $this->transport; + $curl->write($url, [], CurlInterface::GET); + $result = $curl->read(); + $curl->close(); - /** - * Prepare parameter array. - * - * @param string $type - * @return array - */ - private function prepareParamArray($type) - { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'type' => urlencode($type) - ]; + return explode('|', $result); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php index 4b12f6eec87aa..fd1f746a6f09c 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php @@ -7,7 +7,6 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * PathChecker checks that path to file or directory exists. @@ -17,7 +16,7 @@ class PathChecker /** * Url to checkPath.php. */ - const URL = '/dev/tests/functional/utils/pathChecker.php'; + const URL = 'dev/tests/functional/utils/pathChecker.php'; /** * Curl transport protocol. @@ -27,21 +26,11 @@ class PathChecker private $transport; /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - - /** - * @constructor * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -52,28 +41,12 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function pathExists($path) { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray($path), - CurlInterface::POST, - [] - ); - $result = $this->transport->read(); - $this->transport->close(); - return strpos($result, 'path exists: true') !== false; - } + $url = $_ENV['app_frontend_url'] . self::URL . '?path=' . urlencode($path); + $curl = $this->transport; + $curl->write($url, [], CurlInterface::GET); + $result = $curl->read(); + $curl->close(); - /** - * Prepare parameter array. - * - * @param string $path - * @return array - */ - private function prepareParamArray($path) - { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'path' => urlencode($path) - ]; + return strpos($result, 'path exists: true') !== false; } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php index fec20bb2a8715..7d73634c0360d 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php @@ -3,11 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Mtf\Util\Command; use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Perform Website folder creation for functional tests executions. @@ -17,7 +17,7 @@ class Website /** * Url to website.php. */ - const URL = '/dev/tests/functional/utils/website.php'; + const URL = 'dev/tests/functional/utils/website.php'; /** * Curl transport protocol. @@ -26,22 +26,13 @@ class Website */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @constructor * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -52,28 +43,21 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function create($websiteCode) { - $this->transport->addOption(CURLOPT_HEADER, 1); - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray($websiteCode), - CurlInterface::POST, - [] - ); - $this->transport->read(); - $this->transport->close(); + $curl = $this->transport; + $curl->addOption(CURLOPT_HEADER, 1); + $curl->write($this->prepareUrl($websiteCode), [], CurlInterface::GET); + $curl->read(); + $curl->close(); } /** - * Prepare parameter array. + * Prepare url. * * @param string $websiteCode - * @return array + * @return string */ - private function prepareParamArray($websiteCode) + private function prepareUrl($websiteCode) { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'website_code' => urlencode($websiteCode) - ]; + return $_ENV['app_frontend_url'] . self::URL . '?website_code=' . urlencode($websiteCode); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php index d7026e9b8efb3..b1c552370835c 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php @@ -63,56 +63,24 @@ public function __construct(CurlTransport $transport, DataInterface $configurati */ protected function authorize() { - // There are situations where magento application backend url could be slightly different from the environment - // variable we know. It could be intentionally (e.g. InstallTest) or unintentionally. We would still want tests - // to run in this case. - // When the original app_backend_url does not work, we will try 4 variants of the it. i.e. with and without - // url rewrite, http and https. - $urls = []; - $originalUrl = rtrim($_ENV['app_backend_url'], '/') . '/'; - $urls[] = $originalUrl; - // It could be the case that the page needs a refresh, so we will try the original one twice. - $urls[] = $originalUrl; - if (strpos($originalUrl, '/index.php') !== false) { - $url2 = str_replace('/index.php', '', $originalUrl); - } else { - $url2 = $originalUrl . 'index.php/'; - } - $urls[] = $url2; - if (strpos($originalUrl, 'https') !== false) { - $urls[] = str_replace('https', 'http', $originalUrl); - } else { - $urls[] = str_replace('http', 'https', $url2); - } - - $isAuthorized = false; - foreach ($urls as $url) { - try { - // Perform GET to backend url so form_key is set - $this->transport->write($url, [], CurlInterface::GET); - $this->read(); - - $authUrl = $url . $this->configuration->get('application/0/backendLoginUrl/0/value'); - $data = [ - 'login[username]' => $this->configuration->get('application/0/backendLogin/0/value'), - 'login[password]' => $this->configuration->get('application/0/backendPassword/0/value'), - 'form_key' => $this->formKey, - ]; - - $this->transport->write($authUrl, $data, CurlInterface::POST); - $response = $this->read(); - if (strpos($response, 'login-form') !== false) { - continue; - } - $isAuthorized = true; - $_ENV['app_backend_url'] = $url; - break; - } catch (\Exception $e) { - continue; - } - } - if ($isAuthorized == false) { - throw new \Exception('Admin user cannot be logged in by curl handler!'); + // Perform GET to backend url so form_key is set + $url = $_ENV['app_backend_url']; + $this->transport->write($url, [], CurlInterface::GET); + $this->read(); + + $url = $_ENV['app_backend_url'] . $this->configuration->get('application/0/backendLoginUrl/0/value'); + $data = [ + 'login[username]' => $this->configuration->get('application/0/backendLogin/0/value'), + 'login[password]' => $this->configuration->get('application/0/backendPassword/0/value'), + 'form_key' => $this->formKey, + ]; + $this->transport->write($url, $data, CurlInterface::POST); + $response = $this->read(); + if (strpos($response, 'login-form') !== false) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception( + 'Admin user cannot be logged in by curl handler!' + ); } } @@ -144,6 +112,7 @@ public function write($url, $params = [], $method = CurlInterface::POST, $header if ($this->formKey) { $params['form_key'] = $this->formKey; } else { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception(sprintf('Form key is absent! Url: "%s" Response: "%s"', $url, $this->response)); } $this->transport->write($url, http_build_query($params), $method, $headers); diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php index df5ab45a3f96d..3aa756904ab00 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php @@ -70,13 +70,6 @@ class WebapiDecorator implements CurlInterface */ protected $response; - /** - * Webapi token. - * - * @var string - */ - protected $webapiToken; - /** * @construct * @param ObjectManager $objectManager @@ -117,9 +110,6 @@ protected function init() $integration->persist(); $this->setConfiguration($integration); - $this->webapiToken = $integration->getToken(); - } else { - $this->webapiToken = $integrationToken; } } @@ -171,13 +161,7 @@ protected function setConfiguration(Integration $integration) */ protected function isValidIntegration() { - $url = rtrim($_ENV['app_frontend_url'], '/'); - if (strpos($url, 'index.php') === false) { - $url .= '/index.php/rest/V1/modules'; - } else { - $url .= '/rest/V1/modules'; - } - $this->write($url, [], CurlInterface::GET); + $this->write($_ENV['app_frontend_url'] . 'rest/V1/modules', [], CurlInterface::GET); $response = json_decode($this->read(), true); return (null !== $response) && !isset($response['message']); @@ -235,18 +219,4 @@ public function close() { $this->transport->close(); } - - /** - * Return webapiToken. - * - * @return string - */ - public function getWebapiToken() - { - // Request token if integration is no longer valid - if (!$this->isValidIntegration()) { - $this->init(); - } - return $this->webapiToken; - } } diff --git a/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.php b/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.php index fefe0d2c126e5..c2c684c89d06b 100644 --- a/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.php +++ b/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.php @@ -140,9 +140,9 @@ public function test( if ($website) { $website->persist(); $this->setupCurrencyForCustomWebsite($website, $currencyCustomWebsite); - $this->cron->run(); - $this->cron->run(); } + $this->cron->run(); + $this->cron->run(); $products = $this->prepareProducts($products, $website); $this->cron->run(); $this->cron->run(); @@ -165,7 +165,8 @@ public function test( if (!empty($advancedPricingAttributes)) { $products = [$products[0]]; } - + $this->cron->run(); + $this->cron->run(); return [ 'products' => $products ]; diff --git a/dev/tests/functional/tests/app/Magento/CustomerImportExport/Test/TestCase/ExportCustomerAddressesTest.php b/dev/tests/functional/tests/app/Magento/CustomerImportExport/Test/TestCase/ExportCustomerAddressesTest.php index 6b92891ada2b4..17dfb4fb8cdaf 100644 --- a/dev/tests/functional/tests/app/Magento/CustomerImportExport/Test/TestCase/ExportCustomerAddressesTest.php +++ b/dev/tests/functional/tests/app/Magento/CustomerImportExport/Test/TestCase/ExportCustomerAddressesTest.php @@ -87,7 +87,8 @@ public function test( $exportData->persist(); $this->adminExportIndex->getExportForm()->fill($exportData); $this->adminExportIndex->getFilterExport()->clickContinue(); - + $this->cron->run(); + $this->cron->run(); return [ 'customer' => $customer ]; diff --git a/dev/tests/functional/utils/authenticate.php b/dev/tests/functional/utils/authenticate.php deleted file mode 100644 index 15851f6e8000a..0000000000000 --- a/dev/tests/functional/utils/authenticate.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -/** - * Check if token passed in is a valid auth token. - * - * @param string $token - * @return bool - */ -function authenticate($token) -{ - require_once __DIR__ . '/../../../../app/bootstrap.php'; - - $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); - $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); - $tokenModel = $magentoObjectManager->get(\Magento\Integration\Model\Oauth\Token::class); - - $tokenPassedIn = $token; - // Token returned will be null if the token we passed in is invalid - $tokenFromMagento = $tokenModel->loadByToken($tokenPassedIn)->getToken(); - if (!empty($tokenFromMagento) && ($tokenFromMagento == $tokenPassedIn)) { - return true; - } else { - return false; - } -} diff --git a/dev/tests/functional/utils/command.php b/dev/tests/functional/utils/command.php index 4e18598a935ad..99025dd1cffcc 100644 --- a/dev/tests/functional/utils/command.php +++ b/dev/tests/functional/utils/command.php @@ -3,25 +3,26 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; + +// phpcs:ignore Magento2.Security.IncludeFile require_once __DIR__ . '/../../../../app/bootstrap.php'; use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\NullOutput; -if (!empty($_POST['token']) && !empty($_POST['command'])) { - if (authenticate(urldecode($_POST['token']))) { - $command = urldecode($_POST['command']); - $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); - $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); - $cli = $magentoObjectManager->create(\Magento\Framework\Console\Cli::class); - $input = new StringInput(escapeshellcmd($command)); - $input->setInteractive(false); - $output = new NullOutput(); - $cli->doRun($input, $output); - } else { - echo "Command not unauthorized."; - } +// phpcs:ignore Magento2.Security.Superglobal +if (isset($_GET['command'])) { + // phpcs:ignore Magento2.Security.Superglobal + $command = urldecode($_GET['command']); + // phpcs:ignore Magento2.Security.Superglobal + $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); + // phpcs:ignore Magento2.Security.Superglobal + $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); + $cli = $magentoObjectManager->create(\Magento\Framework\Console\Cli::class); + $input = new StringInput($command); + $input->setInteractive(false); + $output = new NullOutput(); + $cli->doRun($input, $output); } else { - echo "'token' or 'command' parameter is not set."; + throw new \InvalidArgumentException("Command GET parameter is not set."); } diff --git a/dev/tests/functional/utils/deleteMagentoGeneratedCode.php b/dev/tests/functional/utils/deleteMagentoGeneratedCode.php index 17e3575c87686..17260bd1da635 100644 --- a/dev/tests/functional/utils/deleteMagentoGeneratedCode.php +++ b/dev/tests/functional/utils/deleteMagentoGeneratedCode.php @@ -3,14 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token']) && !empty($_POST['path'])) { - if (authenticate(urldecode($_POST['token']))) { - exec('rm -rf ../../../../generated/*'); - } else { - echo "Command not unauthorized."; - } -} else { - echo "'token' parameter is not set."; -} +// phpcs:ignore Magento2.Security.InsecureFunction +exec('rm -rf ../../../../generated/*'); diff --git a/dev/tests/functional/utils/export.php b/dev/tests/functional/utils/export.php index e3eff6e3fec17..fa50bc729d0f6 100644 --- a/dev/tests/functional/utils/export.php +++ b/dev/tests/functional/utils/export.php @@ -3,30 +3,32 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token']) && !empty($_POST['template'])) { - if (authenticate(urldecode($_POST['token']))) { - $varDir = '../../../../var/export/'; - $template = urldecode($_POST['template']); - $fileList = scandir($varDir, SCANDIR_SORT_NONE); - $files = []; +// phpcs:ignore Magento2.Security.Superglobal +if (!isset($_GET['template'])) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \InvalidArgumentException('Argument "template" must be set.'); +} - foreach ($fileList as $fileName) { - if (preg_match("`$template`", $fileName) === 1) { - $filePath = $varDir . $fileName; - $files[] = [ - 'content' => file_get_contents($filePath), - 'name' => $fileName, - 'date' => filectime($filePath), - ]; - } - } +$varDir = '../../../../var/export/'; +// phpcs:ignore Magento2.Security.Superglobal +$template = urldecode($_GET['template']); +// phpcs:ignore Magento2.Functions.DiscouragedFunction +$fileList = scandir($varDir, SCANDIR_SORT_NONE); +$files = []; - echo serialize($files); - } else { - echo "Command not unauthorized."; +foreach ($fileList as $fileName) { + if (preg_match("`$template`", $fileName) === 1) { + $filePath = $varDir . $fileName; + $files[] = [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction + 'content' => file_get_contents($filePath), + 'name' => $fileName, + // phpcs:ignore Magento2.Functions.DiscouragedFunction + 'date' => filectime($filePath), + ]; } -} else { - echo "'token' or 'template' parameter is not set."; } + +// phpcs:ignore Magento2.Security.LanguageConstruct, Magento2.Security.InsecureFunction +echo serialize($files); diff --git a/dev/tests/functional/utils/locales.php b/dev/tests/functional/utils/locales.php index a3b4ec05eed65..11e1e2b70fa50 100644 --- a/dev/tests/functional/utils/locales.php +++ b/dev/tests/functional/utils/locales.php @@ -3,23 +3,20 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token'])) { - if (authenticate(urldecode($_POST['token']))) { - if ($_POST['type'] == 'deployed') { - $themePath = isset($_POST['theme_path']) ? $_POST['theme_path'] : 'adminhtml/Magento/backend'; - $directory = __DIR__ . '/../../../../pub/static/' . $themePath; - $locales = array_diff(scandir($directory), ['..', '.']); - } else { - require_once __DIR__ . DIRECTORY_SEPARATOR . 'bootstrap.php'; - $localeConfig = $magentoObjectManager->create(\Magento\Framework\Locale\Config::class); - $locales = $localeConfig->getAllowedLocales(); - } - echo implode('|', $locales); - } else { - echo "Command not unauthorized."; - } +// phpcs:ignore Magento2.Security.Superglobal +if (isset($_GET['type']) && $_GET['type'] == 'deployed') { + // phpcs:ignore Magento2.Security.Superglobal + $themePath = isset($_GET['theme_path']) ? $_GET['theme_path'] : 'adminhtml/Magento/backend'; + $directory = __DIR__ . '/../../../../pub/static/' . $themePath; + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $locales = array_diff(scandir($directory), ['..', '.']); } else { - echo "'token' parameter is not set."; + // phpcs:ignore Magento2.Security.IncludeFile + require_once __DIR__ . DIRECTORY_SEPARATOR . 'bootstrap.php'; + $localeConfig = $magentoObjectManager->create(\Magento\Framework\Locale\Config::class); + $locales = $localeConfig->getAllowedLocales(); } + +// phpcs:ignore Magento2.Security.LanguageConstruct +echo implode('|', $locales); diff --git a/dev/tests/functional/utils/log.php b/dev/tests/functional/utils/log.php index 889056bfbdd63..30783ae8e1d28 100644 --- a/dev/tests/functional/utils/log.php +++ b/dev/tests/functional/utils/log.php @@ -3,20 +3,21 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -declare(strict_types=1); -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token']) && !empty($_POST['name'])) { - if (authenticate(urldecode($_POST['token']))) { - $name = urldecode($_POST['name']); - if (preg_match('/\.\.(\\\|\/)/', $name)) { - throw new \InvalidArgumentException('Invalid log file name'); - } +declare(strict_types=1); +// phpcs:ignore Magento2.Security.Superglobal +if (!isset($_GET['name'])) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \InvalidArgumentException( + 'The name of log file is required for getting logs.' + ); +} - echo serialize(file_get_contents('../../../../var/log' . '/' . $name)); - } else { - echo "Command not unauthorized."; - } -} else { - echo "'token' or 'name' parameter is not set."; +// phpcs:ignore Magento2.Security.Superglobal +$name = urldecode($_GET['name']); +if (preg_match('/\.\.(\\\|\/)/', $name)) { + throw new \InvalidArgumentException('Invalid log file name'); } + +// phpcs:ignore Magento2.Security.InsecureFunction, Magento2.Functions.DiscouragedFunction, Magento2.Security.LanguageConstruct +echo serialize(file_get_contents('../../../../var/log' .'/' .$name)); diff --git a/dev/tests/functional/utils/pathChecker.php b/dev/tests/functional/utils/pathChecker.php index b5a2ddb405bde..217cf90af0a56 100644 --- a/dev/tests/functional/utils/pathChecker.php +++ b/dev/tests/functional/utils/pathChecker.php @@ -3,20 +3,20 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token']) && !empty($_POST['path'])) { - if (authenticate(urldecode($_POST['token']))) { - $path = urldecode($_POST['path']); - - if (file_exists('../../../../' . $path)) { - echo 'path exists: true'; - } else { - echo 'path exists: false'; - } +// phpcs:ignore Magento2.Security.Superglobal +if (isset($_GET['path'])) { + // phpcs:ignore Magento2.Security.Superglobal + $path = urldecode($_GET['path']); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + if (file_exists('../../../../' . $path)) { + // phpcs:ignore Magento2.Security.LanguageConstruct + echo 'path exists: true'; } else { - echo "Command not unauthorized."; + // phpcs:ignore Magento2.Security.LanguageConstruct + echo 'path exists: false'; } } else { - echo "'token' or 'path' parameter is not set."; + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \InvalidArgumentException("GET parameter 'path' is not set."); } diff --git a/dev/tests/functional/utils/website.php b/dev/tests/functional/utils/website.php index ab8e3742f55ae..720b4962aedd4 100644 --- a/dev/tests/functional/utils/website.php +++ b/dev/tests/functional/utils/website.php @@ -3,35 +3,36 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token']) && !empty($_POST['website_code'])) { - if (authenticate(urldecode($_POST['token']))) { - $websiteCode = urldecode($_POST['website_code']); - $rootDir = '../../../../'; - $websiteDir = $rootDir . 'websites/' . $websiteCode . '/'; - $contents = file_get_contents($rootDir . 'index.php'); +// phpcs:ignore Magento2.Security.Superglobal +if (!isset($_GET['website_code'])) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception("website_code GET parameter is not set."); +} + +// phpcs:ignore Magento2.Security.Superglobal +$websiteCode = urldecode($_GET['website_code']); +$rootDir = '../../../../'; +$websiteDir = $rootDir . 'websites/' . $websiteCode . '/'; +// phpcs:ignore Magento2.Functions.DiscouragedFunction +$contents = file_get_contents($rootDir . 'index.php'); - $websiteParam = <<<EOD +$websiteParam = <<<EOD \$params = \$_SERVER; \$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = '$websiteCode'; \$params[\Magento\Store\Model\StoreManager::PARAM_RUN_TYPE] = 'website'; EOD; - $pattern = '`(try {.*?)(\/app\/bootstrap.*?}\n)(.*?)\$_SERVER`mis'; - $replacement = "$1/../..$2\n$websiteParam$3\$params"; +$pattern = '`(try {.*?)(\/app\/bootstrap.*?}\n)(.*?)\$_SERVER`mis'; +$replacement = "$1/../..$2\n$websiteParam$3\$params"; - $contents = preg_replace($pattern, $replacement, $contents); +$contents = preg_replace($pattern, $replacement, $contents); - $old = umask(0); - mkdir($websiteDir, 0760, true); - umask($old); - - copy($rootDir . '.htaccess', $websiteDir . '.htaccess'); - file_put_contents($websiteDir . 'index.php', $contents); - } else { - echo "Command not unauthorized."; - } -} else { - echo "'token' or 'website_code' parameter is not set."; -} +$old = umask(0); +// phpcs:ignore Magento2.Functions.DiscouragedFunction +mkdir($websiteDir, 0760, true); +umask($old); +// phpcs:ignore Magento2.Functions.DiscouragedFunction +copy($rootDir . '.htaccess', $websiteDir . '.htaccess'); +// phpcs:ignore Magento2.Functions.DiscouragedFunction +file_put_contents($websiteDir . 'index.php', $contents); From 7dc85ece16f068f663012b333e7367ffbc9e8d44 Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Thu, 18 Apr 2019 11:45:32 -0500 Subject: [PATCH 386/585] 596: Category with Products with...(deep nesting) (Integration Test for Tag Cache Generation) - Fixed review comments --- .../DeepNestedCategoriesAndProductsTest.php | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php index 2ca31a3ebf293..f8cc7f0e59105 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php @@ -11,14 +11,12 @@ use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Framework\App\Request\Http; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; -use Magento\TestFramework\ObjectManager; /** * Tests cache debug headers and cache tag validation for a deep nested category and product query * * @magentoAppArea graphql * @magentoDbIsolation disabled - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class DeepNestedCategoriesAndProductsTest extends AbstractGraphqlCacheTest { @@ -47,11 +45,11 @@ protected function setUp(): void */ public function testDispatchForCacheHeadersOnDeepNestedQueries(): void { - $categoryId ='333'; + $baseCategoryId ='333'; $query = <<<QUERY { - category(id: $categoryId) { + category(id: $baseCategoryId) { products { items { attribute_set_id @@ -80,19 +78,23 @@ public function testDispatchForCacheHeadersOnDeepNestedQueries(): void } QUERY; /** @var CategoryRepositoryInterface $categoryRepository */ - $categoryRepository = ObjectManager::getInstance()->get(CategoryRepositoryInterface::class); + $categoryRepository = $this->objectManager->get(CategoryRepositoryInterface::class); /** @var ProductRepositoryInterface $productRepository */ - $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); - $categoryIds = []; - $category = $categoryRepository->get('333'); + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + + $resolvedCategoryIds = []; + $category = $categoryRepository->get($baseCategoryId); $productIdsFromCategory = $category->getProductCollection()->getAllIds(); foreach ($productIdsFromCategory as $productId) { - $categoryIds = array_merge($categoryIds, $productRepository->getById($productId)->getCategoryIds()); + $resolvedCategoryIds = array_merge( + $resolvedCategoryIds, + $productRepository->getById($productId)->getCategoryIds() + ); } - $categoryIds = array_merge($categoryIds, ['333']); - foreach ($categoryIds as $categoryId) { + $resolvedCategoryIds = array_merge($resolvedCategoryIds, [$baseCategoryId]); + foreach ($resolvedCategoryIds as $categoryId) { $category = $categoryRepository->get($categoryId); $productIdsFromCategory= array_merge( $productIdsFromCategory, @@ -101,13 +103,13 @@ public function testDispatchForCacheHeadersOnDeepNestedQueries(): void } $uniqueProductIds = array_unique($productIdsFromCategory); - $uniqueCategoryIds = array_unique($categoryIds); + $uniqueCategoryIds = array_unique($resolvedCategoryIds); $expectedCacheTags = ['cat_c', 'cat_p', 'FPC']; - foreach ($uniqueProductIds as $productId) { - $expectedCacheTags = array_merge($expectedCacheTags, ['cat_p_'.$productId]); + foreach ($uniqueProductIds as $uniqueProductId) { + $expectedCacheTags = array_merge($expectedCacheTags, ['cat_p_'.$uniqueProductId]); } - foreach ($uniqueCategoryIds as $categoryId) { - $expectedCacheTags = array_merge($expectedCacheTags, ['cat_c_'.$categoryId]); + foreach ($uniqueCategoryIds as $uniqueCategoryId) { + $expectedCacheTags = array_merge($expectedCacheTags, ['cat_c_'.$uniqueCategoryId]); } $this->request->setPathInfo('/graphql'); @@ -127,4 +129,4 @@ public function testDispatchForCacheHeadersOnDeepNestedQueries(): void ) ); } -} \ No newline at end of file +} From ddeb43e3ef6f479962d04ded3216697a8d68d2e9 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Thu, 18 Apr 2019 12:03:59 -0500 Subject: [PATCH 387/585] GraphQL-594,595,600:code refactored for the integretaion tests --- ...hp => CategoriesWithProductsCacheTest.php} | 60 +++++------------- ...DispatchTest.php => CategoryCacheTest.php} | 59 +++++------------- ...DispatchTest.php => ProductsCacheTest.php} | 62 +++++-------------- 3 files changed, 46 insertions(+), 135 deletions(-) rename dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/{CategoriesWithProductsDispatchTest.php => CategoriesWithProductsCacheTest.php} (62%) rename dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/{CategoryDispatchTest.php => CategoryCacheTest.php} (52%) rename dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/{ProductsDispatchTest.php => ProductsCacheTest.php} (54%) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php similarity index 62% rename from dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php rename to dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php index c999c75307dd2..142e0770937fc 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsDispatchTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php @@ -10,64 +10,37 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Framework\App\Request\Http; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Serialize\SerializerInterface; -use Magento\TestFramework\Helper\Bootstrap; +use Magento\GraphQl\Controller\GraphQl; +use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; /** * Tests cache debug headers and cache tag validation for a category with product query * * @magentoAppArea graphql + * @magentoCache full_page enabled * @magentoDbIsolation disabled - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class CategoriesWithProductsDispatchTest extends \Magento\TestFramework\Indexer\TestCase +class CategoriesWithProductsCacheTest extends AbstractGraphqlCacheTest { - const CONTENT_TYPE = 'application/json'; - - /** @var \Magento\Framework\ObjectManagerInterface */ - private $objectManager; - - /** @var GraphQl */ - private $graphql; - - /** @var SerializerInterface */ - private $jsonSerializer; - - /** @var MetadataPool */ - private $metadataPool; - - /** @var Http */ - private $request; - /** - * @inheritdoc + * @var GraphQl */ - public static function setUpBeforeClass() - { - $db = Bootstrap::getInstance()->getBootstrap() - ->getApplication() - ->getDbInstance(); - if (!$db->isDbDumpExists()) { - throw new \LogicException('DB dump does not exist.'); - } - $db->restoreFromDbDump(); + private $graphqlController; - parent::setUpBeforeClass(); - } + /** + * @var Http + */ + private $request; /** * @inheritdoc */ protected function setUp(): void { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); - $this->metadataPool = $this->objectManager->get(MetadataPool::class); - $this->request = $this->objectManager->get(Http::class); + parent::setUp(); + $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->request = $this->objectManager->create(Http::class); } - /** * Test cache tags and debug header for category with products querying for products and category * @@ -75,7 +48,7 @@ protected function setUp(): void * @magentoDataFixture Magento/Catalog/_files/category_product.php * */ - public function testDispatchForCacheHeadersAndCacheTagsForCategoryWtihProducts(): void + public function testToCheckRequestCacheTagsForCategoryWithProducts(): void { /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); @@ -124,12 +97,9 @@ public function testDispatchForCacheHeadersAndCacheTagsForCategoryWtihProducts() $this->request->setMethod('GET'); $this->request->setParams($queryParams); /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); + $result = $this->graphqlController->dispatch($this->request); /** @var \Magento\Framework\App\Response\Http $response */ $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); $result->renderResult($response); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $product->getId(),'FPC']; diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php similarity index 52% rename from dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php rename to dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php index c6c523aff3d05..d665a0cb5302c 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryDispatchTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php @@ -8,64 +8,37 @@ namespace Magento\GraphQlCache\Controller\Catalog; use Magento\Framework\App\Request\Http; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Serialize\SerializerInterface; -use Magento\TestFramework\Helper\Bootstrap; +use Magento\GraphQl\Controller\GraphQl; +use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; /** * Tests cache debug headers and cache tag validation for a simple category query * * @magentoAppArea graphql + * @magentoCache full_page enabled * @magentoDbIsolation disabled - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class CategoryDispatchTest extends \Magento\TestFramework\Indexer\TestCase +class CategoryCacheTest extends AbstractGraphqlCacheTest { - const CONTENT_TYPE = 'application/json'; - - /** @var \Magento\Framework\ObjectManagerInterface */ - private $objectManager; - - /** @var GraphQl */ - private $graphql; - - /** @var SerializerInterface */ - private $jsonSerializer; - - /** @var MetadataPool */ - private $metadataPool; - - /** @var Http */ - private $request; - /** - * @inheritdoc + * @var GraphQl */ - public static function setUpBeforeClass() - { - $db = Bootstrap::getInstance()->getBootstrap() - ->getApplication() - ->getDbInstance(); - if (!$db->isDbDumpExists()) { - throw new \LogicException('DB dump does not exist.'); - } - $db->restoreFromDbDump(); + private $graphqlController; - parent::setUpBeforeClass(); - } + /** + * @var Http + */ + private $request; /** * @inheritdoc */ protected function setUp(): void { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); - $this->metadataPool = $this->objectManager->get(MetadataPool::class); - $this->request = $this->objectManager->get(Http::class); + parent::setUp(); + $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->request = $this->objectManager->create(Http::class); } - /** * Test cache tags and debug header for category and querying only for category * @@ -73,7 +46,7 @@ protected function setUp(): void * @magentoDataFixture Magento/Catalog/_files/category_product.php * */ - public function testDispatchForCacheDebugHeadersAndCacheTagsForCategory(): void + public function testToCheckRequestCacheTagsForForCategory(): void { $categoryId ='333'; $query @@ -92,12 +65,10 @@ public function testDispatchForCacheDebugHeadersAndCacheTagsForCategory(): void $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); + $result = $this->graphqlController->dispatch($this->request); /** @var \Magento\Framework\App\Response\Http $response */ $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); $result->renderResult($response); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php similarity index 54% rename from dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php rename to dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php index 53b8e2123063a..6b4813fe76d42 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsDispatchTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php @@ -9,72 +9,44 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Framework\App\Request\Http; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Serialize\SerializerInterface; -use Magento\TestFramework\Helper\Bootstrap; +use Magento\GraphQl\Controller\GraphQl; +use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; /** * Tests cache debug headers and cache tag validation for a simple product query * * @magentoAppArea graphql + * @magentoCache full_page enabled * @magentoDbIsolation disabled - * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class ProductsDispatchTest extends \Magento\TestFramework\Indexer\TestCase +class ProductsCacheTest extends AbstractGraphqlCacheTest { - const CONTENT_TYPE = 'application/json'; - - /** @var \Magento\Framework\ObjectManagerInterface */ - private $objectManager; - - /** @var GraphQl */ - private $graphql; - - /** @var SerializerInterface */ - private $jsonSerializer; - - /** @var MetadataPool */ - private $metadataPool; - - /** @var Http */ - private $request; - /** - * @inheritdoc + * @var GraphQl */ - public static function setUpBeforeClass() - { - $db = Bootstrap::getInstance()->getBootstrap() - ->getApplication() - ->getDbInstance(); - if (!$db->isDbDumpExists()) { - throw new \LogicException('DB dump does not exist.'); - } - $db->restoreFromDbDump(); + private $graphqlController; - parent::setUpBeforeClass(); - } + /** + * @var Http + */ + private $request; /** * @inheritdoc */ protected function setUp(): void { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); - $this->metadataPool = $this->objectManager->get(MetadataPool::class); - $this->request = $this->objectManager->get(Http::class); + parent::setUp(); + $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $this->request = $this->objectManager->create(Http::class); } - /** * Test request is dispatched and response is checked for debug headers and cache tags * * @magentoCache all enabled - * @return void + * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php */ - public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForProducts(): void + public function testToCheckRequestCacheTagsForProducts(): void { /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); @@ -103,12 +75,10 @@ public function testDispatchWithGetForCacheDebugHeadersAndCacheTagsForProducts() $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); + $result = $this->graphqlController->dispatch($this->request); /** @var \Magento\Framework\App\Response\Http $response */ $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); $result->renderResult($response); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); From 7ab95ac818a410b08509b1a0889864e208a58b40 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 18 Apr 2019 12:08:51 -0500 Subject: [PATCH 388/585] Issue-230: adding varnish - fixing static --- app/code/Magento/GraphQlCache/etc/module.xml | 1 + .../TestCase/HttpClient/CurlClient.php | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/GraphQlCache/etc/module.xml b/app/code/Magento/GraphQlCache/etc/module.xml index d7f08c5529332..3cbd4d8f0cb48 100644 --- a/app/code/Magento/GraphQlCache/etc/module.xml +++ b/app/code/Magento/GraphQlCache/etc/module.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Magento_GraphQlCache"> <sequence> + <module name="Magento_PageCache"/> <module name="Magento_GraphQl"/> </sequence> </module> diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php index 11af91bd3e008..11d7ee08cb827 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php @@ -35,7 +35,7 @@ public function get($url, $data = [], $headers = []) /** * Perform a HTTP GET request and returns just the response headers * - * @param $url + * @param string $url * @param array $data * @param array $headers * @return mixed @@ -118,8 +118,10 @@ public function put($url, $data, $headers = []) public function invokeApi($url, $additionalCurlOpts, $headers = []) { // initialize cURL + // phpcs:ignore Magento2.Functions.DiscouragedFunction $curl = curl_init($url); if ($curl === false) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception("Error Initializing cURL for baseUrl: " . $url); } @@ -128,28 +130,40 @@ public function invokeApi($url, $additionalCurlOpts, $headers = []) // add CURL opts foreach ($curlOpts as $opt => $val) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction curl_setopt($curl, $opt, $val); } + // phpcs:ignore Magento2.Functions.DiscouragedFunction $response = curl_exec($curl); if ($response === false) { - throw new \Exception(curl_error($curl)); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $error = curl_error($curl); + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception($error; } $resp = []; + // phpcs:ignore Magento2.Functions.DiscouragedFunction $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); $resp["header"] = substr($response, 0, $headerSize); $resp["body"] = substr($response, $headerSize); + // phpcs:ignore Magento2.Functions.DiscouragedFunction $resp["meta"] = curl_getinfo($curl); if ($resp["meta"] === false) { - throw new \Exception(curl_error($curl)); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $error = curl_error($curl); + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception($error); } + // phpcs:ignore Magento2.Functions.DiscouragedFunction curl_close($curl); $meta = $resp["meta"]; if ($meta && $meta['http_code'] >= 400) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception($resp["body"], $meta['http_code']); } From 1e135ca5d979562fd82f6ff669a5c99d1f39800d Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 18 Apr 2019 12:29:48 -0500 Subject: [PATCH 389/585] Issue-230: adding varnish - fixing static --- .../Magento/TestFramework/TestCase/HttpClient/CurlClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php index 11d7ee08cb827..0a24e64297e10 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php @@ -140,7 +140,7 @@ public function invokeApi($url, $additionalCurlOpts, $headers = []) // phpcs:ignore Magento2.Functions.DiscouragedFunction $error = curl_error($curl); // phpcs:ignore Magento2.Exceptions.DirectThrow - throw new \Exception($error; + throw new \Exception($error); } $resp = []; From 0e78cca8b562a437993f875181666e96c9fa35e9 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Thu, 18 Apr 2019 12:40:51 -0500 Subject: [PATCH 390/585] GraphQL-594,595,600:fixed some code review comments for integration tests --- .../Controller/Catalog/CategoriesWithProductsCacheTest.php | 4 +--- .../GraphQlCache/Controller/Catalog/CategoryCacheTest.php | 2 -- .../GraphQlCache/Controller/Catalog/ProductsCacheTest.php | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php index 142e0770937fc..fc9b8f38ed1f1 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php @@ -44,16 +44,14 @@ protected function setUp(): void /** * Test cache tags and debug header for category with products querying for products and category * - * @magentoCache all enabled * @magentoDataFixture Magento/Catalog/_files/category_product.php - * */ public function testToCheckRequestCacheTagsForCategoryWithProducts(): void { /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); /** @var ProductInterface $product */ - $product= $productRepository->get('simple333'); + $product = $productRepository->get('simple333'); $categoryId ='333'; $query = <<<QUERY diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php index d665a0cb5302c..efa08b32d35ea 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php @@ -42,9 +42,7 @@ protected function setUp(): void /** * Test cache tags and debug header for category and querying only for category * - * @magentoCache all enabled * @magentoDataFixture Magento/Catalog/_files/category_product.php - * */ public function testToCheckRequestCacheTagsForForCategory(): void { diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php index 6b4813fe76d42..b9f3a4c9a3956 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php @@ -43,7 +43,6 @@ protected function setUp(): void /** * Test request is dispatched and response is checked for debug headers and cache tags * - * @magentoCache all enabled * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php */ public function testToCheckRequestCacheTagsForProducts(): void From 66eea55d4a37c4fcc79677d9e779be079bf08ef9 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Thu, 18 Apr 2019 13:35:49 -0500 Subject: [PATCH 391/585] GraphQL-594,595,600:fixed additional code review comments for integration tests --- dev/tests/integration/testsuite/Magento/Cms/_files/pages.php | 4 ++-- .../Controller/Catalog/CategoriesWithProductsCacheTest.php | 4 ++-- .../GraphQlCache/Controller/Catalog/CategoryCacheTest.php | 5 ++--- .../GraphQlCache/Controller/Catalog/ProductsCacheTest.php | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php b/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php index 0b7c3a2242fee..b2742ecd380f3 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php +++ b/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php @@ -14,7 +14,7 @@ ->setContentHeading('<h2>Cms Page 100 Title</h2>') ->setMetaTitle('Cms Meta title for page100') ->setMetaKeywords('Cms Meta Keywords for page100') - ->setsetMetaDescription('Cms Meta Description for page100') + ->setMetaDescription('Cms Meta Description for page100') ->setPageLayout('1column') ->save(); @@ -27,7 +27,7 @@ ->setContentHeading('<h2>Cms Page Blank Title</h2>') ->setMetaTitle('Cms Meta title for Blank page') ->setMetaKeywords('Cms Meta Keywords for Blank page') - ->setsetMetaDescription('Cms Meta Description for Blank page') + ->setMetaDescription('Cms Meta Description for Blank page') ->setPageLayout('1column') ->setCustomTheme('Magento/blank') ->save(); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php index fc9b8f38ed1f1..bcd3b7fecad58 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php @@ -18,7 +18,6 @@ * * @magentoAppArea graphql * @magentoCache full_page enabled - * @magentoDbIsolation disabled */ class CategoriesWithProductsCacheTest extends AbstractGraphqlCacheTest { @@ -81,7 +80,7 @@ public function testToCheckRequestCacheTagsForCategoryWithProducts(): void } QUERY; $variables =[ - 'id' => 333, + 'id' => $categoryId, 'pageSize'=> 10, 'currentPage' => 1 ]; @@ -105,3 +104,4 @@ public function testToCheckRequestCacheTagsForCategoryWithProducts(): void $this->assertEquals($expectedCacheTags, $actualCacheTags); } } + diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php index efa08b32d35ea..06d9fc1ff5965 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php @@ -71,8 +71,7 @@ public function testToCheckRequestCacheTagsForForCategory(): void $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'FPC']; - foreach (array_keys($actualCacheTags) as $key) { - $this->assertEquals($expectedCacheTags[$key], $actualCacheTags[$key]); - } + $this->assertEquals($expectedCacheTags, $actualCacheTags); } } + diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php index b9f3a4c9a3956..4cfd74ee49b81 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php @@ -17,7 +17,6 @@ * * @magentoAppArea graphql * @magentoCache full_page enabled - * @magentoDbIsolation disabled */ class ProductsCacheTest extends AbstractGraphqlCacheTest { @@ -85,3 +84,4 @@ public function testToCheckRequestCacheTagsForProducts(): void $this->assertEquals($expectedCacheTags, $actualCacheTags); } } + From c84a7a3b00fe78af13bb4a263b91da5677ea531f Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Thu, 18 Apr 2019 13:39:50 -0500 Subject: [PATCH 392/585] GraphQL-577: Test coverage for tag cache generation for category and products - refactored test --- .../GraphQl/PageCache/CacheTagTest.php | 136 ++++++++++-------- 1 file changed, 74 insertions(+), 62 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index 44ef97db35930..457461d24d351 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -10,28 +10,31 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Product; use Magento\TestFramework\ObjectManager; -use Magento\TestFramework\App\State; -use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; -/** - * Class CacheTagTest - */ /** * Test the caching works properly for products and categories */ class CacheTagTest extends GraphQlAbstract { + /** - * Tests if Magento cache tags and debug headers for products are generated properly - * @magentoApiDataFixture Magento/Catalog/_files/multiple_products.php + * @inheritdoc */ - public function testCacheTagsAndCacheDebugHeaderForProducts() + protected function setUp() { $this->markTestSkipped( 'This test will stay skipped until DEVOPS-4924 is resolved' ); + } + /** + * Tests if Magento cache tags and debug headers for products are generated properly + * + * @magentoApiDataFixture Magento/Catalog/_files/multiple_products.php + */ + public function testCacheTagsAndCacheDebugHeaderForProducts() + { $productSku='simple2'; $query = <<<QUERY @@ -75,70 +78,25 @@ public function testCacheTagsAndCacheDebugHeaderForProducts() } /** - * Tests if Magento cache tags for categories are generated properly. Also tests the use case for cache invalidation + * Tests if X-Magento-Tags for categories are generated properly. Also tests the use case for cache invalidation * * @magentoApiDataFixture Magento/Catalog/_files/product_in_multiple_categories.php */ - public function testCacheTagFromResponseHeaderForCategoriesWithProduct() + public function testCacheTagForCategoriesWithProduct() { - $this->markTestSkipped( - 'This test will stay skipped until DEVOPS-4924 is resolved' - ); $firstProductSku = 'simple333'; $secondProductSku = 'simple444'; $categoryId ='4'; - $categoryQuery - = <<<'QUERY' -query GetCategoryQuery($id: Int!, $pageSize: Int!, $currentPage: Int!) { - category(id: $id) { - id - description - name - product_count - products(pageSize: $pageSize, currentPage: $currentPage) { - items { - id - name - url_key - } - total_count - } - } - } -QUERY; + $variables =[ - 'id' => 4, + 'id' => $categoryId, 'pageSize'=> 10, 'currentPage' => 1 ]; - $product1Query - = <<<QUERY - { - products(filter: {sku: {eq: "{$firstProductSku}"}}) - { - items { - id - name - sku - } - } - } -QUERY; - $product2Query - = <<<QUERY - { - products(filter: {sku: {eq: "{$secondProductSku}"}}) - { - items { - id - name - sku - } - } - } -QUERY; - + $product1Query = $this->getProductQuery($firstProductSku); + $product2Query =$this->getProductQuery($secondProductSku); + $categoryQuery = $this->getCategoryQuery(); $responseMissHeaders = $this->graphQlQueryForHttpHeaders($categoryQuery, $variables); /** cache-debug header value should be a MISS when category is loaded first time */ @@ -155,10 +113,12 @@ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() preg_match('/X-Magento-Tags: (.*?)\n/', $responseMissHeaders, $headerCacheTags); $actualCacheTags = explode(',', rtrim($headerCacheTags[1], "\r")); $expectedCacheTags = - ['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $firstProduct->getId(),'cat_p_' .$secondProduct->getId(),'FPC']; + ['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $firstProduct->getId(), + 'cat_p_' .$secondProduct->getId(),'FPC' + ]; $this->assertEquals($expectedCacheTags, $actualCacheTags); - // Cach-debug header should be a MISS for product 1 during first load + // Cach-debug header should be a MISS for product 1 on first request $responseHeadersFirstProduct = $this->graphQlQueryForHttpHeaders($product1Query); $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHeadersFirstProduct); @@ -181,4 +141,56 @@ public function testCacheTagFromResponseHeaderForCategoriesWithProduct() $responseHeadersSecondProduct = $this->graphQlQueryForHttpHeaders($product2Query); $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHeadersSecondProduct); } + + /** + * Get Product query + * + * @param string $productSku + * @return string + */ + private function getProductQuery(string $productSku): string + { + $productQuery = <<<QUERY + { + products(filter: {sku: {eq: "{$productSku}"}}) + { + items { + id + name + sku + } + } + } +QUERY; + return $productQuery; + } + + /** + * Get category query + * + * @return string + */ + private function getCategoryQuery(): string + { + $categoryQueryString = <<<QUERY +query GetCategoryQuery(\$id: Int!, \$pageSize: Int!, \$currentPage: Int!) { + category(id: \$id) { + id + description + name + product_count + products(pageSize: \$pageSize, currentPage: \$currentPage) { + items { + id + name + url_key + } + total_count + } + } + } +QUERY; + + return $categoryQueryString; + } } From aa378d608f383d6804965dcac930521d16b7b0b1 Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Thu, 18 Apr 2019 14:12:39 -0500 Subject: [PATCH 393/585] MAGETWO-99022: Braintree Displaying Incorrect Ship-To Name - Fixed unit test --- .../Test/Unit/Controller/Paypal/ReviewTest.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php b/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php index 609b7f21dbf87..d68838bafbf0e 100644 --- a/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php @@ -6,6 +6,7 @@ namespace Magento\Braintree\Test\Unit\Controller\Paypal; +use Magento\Payment\Model\Method\Logger; use Magento\Quote\Model\Quote; use Magento\Framework\View\Layout; use Magento\Checkout\Model\Session; @@ -65,6 +66,11 @@ class ReviewTest extends \PHPUnit\Framework\TestCase */ private $review; + /** + * @var Logger|\PHPUnit_Framework_MockObject_MockObject + */ + private $loggerMock; + protected function setUp() { /** @var Context|\PHPUnit_Framework_MockObject_MockObject $contextMock */ @@ -88,6 +94,9 @@ protected function setUp() ->getMock(); $this->messageManagerMock = $this->getMockBuilder(ManagerInterface::class) ->getMockForAbstractClass(); + $this->loggerMock = $this->getMockBuilder(Logger::class) + ->disableOriginalConstructor() + ->getMock(); $contextMock->expects(self::once()) ->method('getRequest') @@ -103,7 +112,8 @@ protected function setUp() $contextMock, $this->configMock, $this->checkoutSessionMock, - $this->quoteUpdaterMock + $this->quoteUpdaterMock, + $this->loggerMock ); } From e2cb7364680f55a8160bf455a15397ce79cf2cc1 Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Thu, 18 Apr 2019 14:14:02 -0500 Subject: [PATCH 394/585] MAGETWO-99091: Name of categories in the Category tree on Product Edit page is not displayed according to the selected store view scope - Fixed returnable method type --- .../Ui/DataProvider/Product/Form/Modifier/Categories.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php index db80d110e123a..800ead0e4030c 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php @@ -395,10 +395,10 @@ private function retrieveShownCategoriesIds(int $storeId, string $filter = '') : * * @param int $storeId * @param array $shownCategoriesIds - * @return array + * @return array|null * @throws LocalizedException */ - private function retrieveCategoriesTree(int $storeId, array $shownCategoriesIds) : array + private function retrieveCategoriesTree(int $storeId, array $shownCategoriesIds) : ?array { /* @var $collection \Magento\Catalog\Model\ResourceModel\Category\Collection */ $collection = $this->categoryCollectionFactory->create(); From d63d618c86b2821fc41e795ebb4335f6a181aff4 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Thu, 18 Apr 2019 14:32:08 -0500 Subject: [PATCH 395/585] MAGETWO-99027: Customizable Option Price input is not saved on Store View level when Catalog Price Scope set to Global --- .../Model/ResourceModel/Product/Option/Value.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php index 318c9bd132ccd..8224d9674956e 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php @@ -17,6 +17,7 @@ use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; +use Magento\Catalog\Helper\Data; /** * Catalog product custom option resource model @@ -51,6 +52,11 @@ class Value extends AbstractDb */ private $localeFormat; + /** + * @var Data + */ + private $dataHelper; + /** * Class constructor * @@ -59,17 +65,21 @@ class Value extends AbstractDb * @param StoreManagerInterface $storeManager * @param ScopeConfigInterface $config * @param string $connectionName + * @param Data $dataHelper */ public function __construct( Context $context, CurrencyFactory $currencyFactory, StoreManagerInterface $storeManager, ScopeConfigInterface $config, - $connectionName = null + $connectionName = null, + Data $dataHelper = null ) { $this->_currencyFactory = $currencyFactory; $this->_storeManager = $storeManager; $this->_config = $config; + $this->dataHelper = $dataHelper ?: ObjectManager::getInstance() + ->get(Data::class); parent::__construct($context, $connectionName); } @@ -131,7 +141,7 @@ protected function _saveValuePrices(AbstractModel $object) $optionTypeId = $this->getConnection()->fetchOne($select); if ($optionTypeId) { - if ($object->getStoreId() == '0') { + if ($object->getStoreId() == '0' || $this->dataHelper->isPriceGlobal()) { $bind = ['price' => $price, 'price_type' => $priceType]; $where = [ 'option_type_id = ?' => $optionTypeId, From b792752740da09176763e2e35aa8f30c8f56a247 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Thu, 18 Apr 2019 15:25:27 -0500 Subject: [PATCH 396/585] MAGETWO-99027: Customizable Option Price input is not saved on Store View level when Catalog Price Scope set to Global --- .../Catalog/Model/ResourceModel/Product/Option/Value.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php index 8224d9674956e..494dbac02d792 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php @@ -22,7 +22,7 @@ /** * Catalog product custom option resource model * - * @author Magento Core Team <core@magentocommerce.com> + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Value extends AbstractDb { From fe547079fddbb6f15182e2f1b9d13cc8602fc969 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Thu, 18 Apr 2019 16:12:23 -0500 Subject: [PATCH 397/585] MC-15922: Skip 'Get Category List by category_id' scenario from benchmark --- setup/performance-toolkit/benchmark.jmx | 65 ------------------------- 1 file changed, 65 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 50fdd7462b254..55cdf7379cc5e 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -42802,71 +42802,6 @@ vars.putObject("category", categories[number]); <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/extract_category_setup.jmx</stringProp></JSR223Sampler> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Category List by category_id" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"> - {"query":"query categoryList($id: Int!) {\n category(id: $id) {\n id\n children {\n id\n name\n url_key\n url_path\n children_count\n path\n image\n productImagePreview: products(pageSize: 1) {\n items {\n small_image {\n label\n url\n }\n }\n }\n }\n }\n}","variables":{"id":${category_id}},"operationName":"categoryList"} - </stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_category_list_by_category_id.jmx</stringProp></HTTPSamplerProxy> - <hashTree> - <JSR223Assertion guiclass="TestBeanGUI" testclass="JSR223Assertion" testname="Assert found categories" enabled="true"> - <stringProp name="scriptLanguage">javascript</stringProp> - <stringProp name="parameters"/> - <stringProp name="filename"/> - <stringProp name="cacheKey"/> - <stringProp name="script">var category = vars.getObject("category"); -var response = JSON.parse(prev.getResponseDataAsString()); - -assertCategoryId(category, response); -assertCategoryChildren(category, response); - -function assertCategoryId(category, response) { - if (response.data == undefined || response.data.category == undefined || response.data.category.id != category.id) { - AssertionResult.setFailureMessage("Cannot find category with id \"" + category.id + "\""); - AssertionResult.setFailure(true); - } -} - -function assertCategoryChildren(category, response) { - foundCategory = response.data && response.data.category ? response.data.category : null; - if (foundCategory) { - var childrenFound = foundCategory.children.map(function (c) {return parseInt(c.id)}); - var children = category.children.map(function (c) {return parseInt(c)}); - if (JSON.stringify(children.sort()) != JSON.stringify(childrenFound.sort())) { - AssertionResult.setFailureMessage("Cannot math children categories \"" + JSON.stringify(children) + "\" for to found one: \"" + JSON.stringify(childrenFound) + "\""); - AssertionResult.setFailure(true); - } - } - -} - -</stringProp> - </JSR223Assertion> - <hashTree/> - </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Navigation Menu by category_id" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> From 8a3f00a07ba3b95d96a1589975b9bcec04a7aa88 Mon Sep 17 00:00:00 2001 From: Joan He <johe@magento.com> Date: Thu, 18 Apr 2019 16:14:56 -0500 Subject: [PATCH 398/585] MC-15873: Catch unserializer exception --- .../Model/Config/Backend/Serialized.php | 19 ++++++++++++++- .../Model/Config/Backend/SerializedTest.php | 24 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Config/Model/Config/Backend/Serialized.php b/app/code/Magento/Config/Model/Config/Backend/Serialized.php index 3d5713357c39c..6e0b6275db836 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Serialized.php +++ b/app/code/Magento/Config/Model/Config/Backend/Serialized.php @@ -9,6 +9,8 @@ use Magento\Framework\Serialize\Serializer\Json; /** + * Serialized backend model + * * @api * @since 100.0.2 */ @@ -46,17 +48,32 @@ public function __construct( } /** + * Processing object after load data + * * @return void */ protected function _afterLoad() { $value = $this->getValue(); if (!is_array($value)) { - $this->setValue(empty($value) ? false : $this->serializer->unserialize($value)); + try { + $this->setValue(empty($value) ? false : $this->serializer->unserialize($value)); + } catch (\Exception $e) { + $this->_logger->critical( + sprintf( + 'Failed to unserialize %s config value. The error is: %s', + $this->getPath(), + $e->getMessage() + ) + ); + $this->setValue(false); + } } } /** + * Processing object before save data + * * @return $this */ public function beforeSave() diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SerializedTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SerializedTest.php index bb1e0e0225901..c2685e0a265cd 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SerializedTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SerializedTest.php @@ -9,7 +9,11 @@ use Magento\Framework\Model\Context; use Magento\Framework\Serialize\Serializer\Json; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Psr\Log\LoggerInterface; +/** + * Class SerializedTest + */ class SerializedTest extends \PHPUnit\Framework\TestCase { /** @var \Magento\Config\Model\Config\Backend\Serialized */ @@ -18,14 +22,20 @@ class SerializedTest extends \PHPUnit\Framework\TestCase /** @var Json|\PHPUnit_Framework_MockObject_MockObject */ private $serializerMock; + /** @var LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $loggerMock; + protected function setUp() { $objectManager = new ObjectManager($this); $this->serializerMock = $this->createMock(Json::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); $contextMock = $this->createMock(Context::class); $eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); $contextMock->method('getEventDispatcher') ->willReturn($eventManagerMock); + $contextMock->method('getLogger') + ->willReturn($this->loggerMock); $this->serializedConfig = $objectManager->getObject( Serialized::class, [ @@ -72,6 +82,20 @@ public function afterLoadDataProvider() ]; } + public function testAfterLoadWithException() + { + $value = '{"key":'; + $expected = false; + $this->serializedConfig->setValue($value); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->willThrowException(new \Exception()); + $this->loggerMock->expects($this->once()) + ->method('critical'); + $this->serializedConfig->afterLoad(); + $this->assertEquals($expected, $this->serializedConfig->getValue()); + } + /** * @param string $expected * @param int|double|string|array|boolean|null $value From 822359d4b43581590113ca0de1456672015a883d Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 18 Apr 2019 16:19:15 -0500 Subject: [PATCH 399/585] Issue-230: adding varnish - fixing static --- .../Framework/App/PageCache/Kernel.php | 51 +++++-------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/lib/internal/Magento/Framework/App/PageCache/Kernel.php b/lib/internal/Magento/Framework/App/PageCache/Kernel.php index 813762c646d4c..a76847f64e45d 100644 --- a/lib/internal/Magento/Framework/App/PageCache/Kernel.php +++ b/lib/internal/Magento/Framework/App/PageCache/Kernel.php @@ -6,6 +6,7 @@ namespace Magento\Framework\App\PageCache; use Magento\Framework\App\State as AppState; +use Magento\Framework\App\ObjectManager; /** * Builtin cache processor @@ -82,43 +83,17 @@ public function __construct( $this->cache = $cache; $this->identifier = $identifier; $this->request = $request; - - if ($context) { - $this->context = $context; - } else { - $this->context = \Magento\Framework\App\ObjectManager::getInstance()->get( - \Magento\Framework\App\Http\Context::class - ); - } - if ($contextFactory) { - $this->contextFactory = $contextFactory; - } else { - $this->contextFactory = \Magento\Framework\App\ObjectManager::getInstance()->get( - \Magento\Framework\App\Http\ContextFactory::class - ); - } - if ($httpFactory) { - $this->httpFactory = $httpFactory; - } else { - $this->httpFactory = \Magento\Framework\App\ObjectManager::getInstance()->get( - \Magento\Framework\App\Response\HttpFactory::class - ); - } - if ($serializer) { - $this->serializer = $serializer; - } else { - $this->serializer = \Magento\Framework\App\ObjectManager::getInstance()->get( - \Magento\Framework\Serialize\SerializerInterface::class - ); - } - - if ($state) { - $this->state = $state; - } else { - $this->state = \Magento\Framework\App\ObjectManager::getInstance()->get( - AppState::class - ); - } + $this->context = $context ?? ObjectManager::getInstance()->get(\Magento\Framework\App\Http\Context::class); + $this->contextFactory = $contextFactory ?? ObjectManager::getInstance()->get( + \Magento\Framework\App\Http\ContextFactory::class + ); + $this->httpFactory = $httpFactory ?? ObjectManager::getInstance()->get( + \Magento\Framework\App\Response\HttpFactory::class + ); + $this->serializer = $serializer ?? ObjectManager::getInstance()->get( + \Magento\Framework\Serialize\SerializerInterface::class + ); + $this->state = $state ?? ObjectManager::getInstance()->get(AppState::class); } /** @@ -231,7 +206,7 @@ private function buildResponse($responseData) private function getCache() { if (!$this->fullPageCache) { - $this->fullPageCache = \Magento\Framework\App\ObjectManager::getInstance()->get( + $this->fullPageCache = $objectManager->get( \Magento\PageCache\Model\Cache\Type::class ); } From c4947cedb0965c9208202d40116885c6f134fa04 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 18 Apr 2019 17:07:10 -0500 Subject: [PATCH 400/585] Issue-230: adding varnish - fixing objectmanager --- lib/internal/Magento/Framework/App/PageCache/Kernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/PageCache/Kernel.php b/lib/internal/Magento/Framework/App/PageCache/Kernel.php index a76847f64e45d..9f6d796ad39f8 100644 --- a/lib/internal/Magento/Framework/App/PageCache/Kernel.php +++ b/lib/internal/Magento/Framework/App/PageCache/Kernel.php @@ -206,7 +206,7 @@ private function buildResponse($responseData) private function getCache() { if (!$this->fullPageCache) { - $this->fullPageCache = $objectManager->get( + $this->fullPageCache = ObjectManager::getInstance()->get( \Magento\PageCache\Model\Cache\Type::class ); } From 3ac980d873f49d570be4f264581fa4c7916d978f Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Thu, 18 Apr 2019 17:19:30 -0500 Subject: [PATCH 401/585] GraphQL-597: Test coverage for cart-not cached test - api-functional test coverage --- .../GraphQl/PageCache/CacheTagTest.php | 10 +- .../PageCache/Quote/Guest/CartCacheTest.php | 132 ++++++++++++++++++ 2 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index 457461d24d351..824f29cf0b1e8 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -17,7 +17,6 @@ */ class CacheTagTest extends GraphQlAbstract { - /** * @inheritdoc */ @@ -87,7 +86,6 @@ public function testCacheTagForCategoriesWithProduct() $firstProductSku = 'simple333'; $secondProductSku = 'simple444'; $categoryId ='4'; - $variables =[ 'id' => $categoryId, 'pageSize'=> 10, @@ -118,22 +116,22 @@ public function testCacheTagForCategoriesWithProduct() ]; $this->assertEquals($expectedCacheTags, $actualCacheTags); - // Cach-debug header should be a MISS for product 1 on first request + // Cache-debug header should be a MISS for product 1 on first request $responseHeadersFirstProduct = $this->graphQlQueryForHttpHeaders($product1Query); $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHeadersFirstProduct); - // Cach-debug header should be a MISS for product 2 during first load + // Cache-debug header should be a MISS for product 2 during first load $responseHeadersSecondProduct = $this->graphQlQueryForHttpHeaders($product2Query); $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHeadersSecondProduct); - /** cache-debug header value should be MISS after updating product1 and reloading the Category */ + /** Cache-debug header value should be MISS after updating product1 and reloading the Category */ $firstProduct->setPrice(20); $firstProduct->save(); $responseMissHeaders = $this->graphQlQueryForHttpHeaders($categoryQuery, $variables); preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); - /** cache-debug should be a MISS for product 1 after it is updated - cache invalidation */ + /** Cache-debug should be a MISS for product 1 after it is updated - cache invalidation */ $responseHeadersFirstProduct = $this->graphQlQueryForHttpHeaders($product1Query); $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHeadersFirstProduct); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php new file mode 100644 index 0000000000000..e0c57ea373820 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php @@ -0,0 +1,132 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\PageCache\Quote\Guest; + +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * End to end test which creates an empty cart and add product to the cart and load the cart. + * Validates that the cache-debug header is a MISS for any subsequent cart requests + * + * @magentoApiDataFixture Magento/Catalog/_files/products.php + */ +class CartCacheTest extends GraphQlAbstract +{ + /** @var string */ + private $maskedQuoteId; + + protected function setUp() + { + $this->markTestSkipped( + 'This test will stay skipped until DEVOPS-4924 is resolved' + ); + } + /** + * Tests that X-Magento-Tags are correct + */ + public function testCartIsNotCached() + { + $qty = 2; + $sku = 'simple'; + $cartId = $this->createEmptyCart(); + $this->addSimpleProductToCart($cartId, $qty, $sku); + $getCartQuery = $this->checkCart($cartId); + $response = $this->graphQlQuery($getCartQuery); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('items', $response['cart']); + + $responseMissHeaders = $this->graphQlQueryForHttpHeaders($getCartQuery); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); + + /** Cache debug header value is still a MISS for any subsequent request */ + $responseMissHeadersNext = $this->graphQlQueryForHttpHeaders($getCartQuery); + $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeadersNext); + } + + /** + * Create a guest cart which generates a maskedQuoteId + * + * @return mixed + */ + private function createEmptyCart() + { + $query = + <<<QUERY + mutation + { + createEmptyCart + } +QUERY; + + $response = $this->graphQlMutation($query); + $this->maskedQuoteId = $response['createEmptyCart']; + return $this->maskedQuoteId; + } + + /** + * Add simple product to the cart using the maskedQuoteId + * @param $maskedCartId + * @param $qty + * @param $sku + */ + private function addSimpleProductToCart($maskedCartId, $qty, $sku) + { + $addProductToCartQuery = + <<<QUERY + mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$maskedCartId}" + cartItems: [ + { + data: { + qty: $qty + sku: "$sku" + } + } + ] + } + ) { + cart { + items { + qty + product { + sku + } + } + } + } + } +QUERY; + $response = $this->graphQlMutation($addProductToCartQuery); + self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); + } + + /** + * + * @param string $maskedQuoteId + * @return string + */ + private function checkCart(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id: "{$maskedQuoteId}") { + items { + id + qty + product { + sku + } + } + } +} +QUERY; + } +} From 43500fb37ba4f64e371b4baacdaa2f2dac508ddc Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 18 Apr 2019 17:23:09 -0500 Subject: [PATCH 402/585] Issue-230: adding varnish - fixing objectmanager --- .../Framework/App/PageCache/Kernel.php | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/lib/internal/Magento/Framework/App/PageCache/Kernel.php b/lib/internal/Magento/Framework/App/PageCache/Kernel.php index 9f6d796ad39f8..f89fe93957a97 100644 --- a/lib/internal/Magento/Framework/App/PageCache/Kernel.php +++ b/lib/internal/Magento/Framework/App/PageCache/Kernel.php @@ -69,6 +69,7 @@ class Kernel * @param \Magento\Framework\App\Response\HttpFactory|null $httpFactory * @param \Magento\Framework\Serialize\SerializerInterface|null $serializer * @param AppState|null $state + * @param \Magento\PageCache\Model\Cache\Type $fullPageCache */ public function __construct( \Magento\Framework\App\PageCache\Cache $cache, @@ -78,7 +79,8 @@ public function __construct( \Magento\Framework\App\Http\ContextFactory $contextFactory = null, \Magento\Framework\App\Response\HttpFactory $httpFactory = null, \Magento\Framework\Serialize\SerializerInterface $serializer = null, - AppState $state = null + AppState $state = null, + \Magento\PageCache\Model\Cache\Type $fullPageCache = null ) { $this->cache = $cache; $this->identifier = $identifier; @@ -94,6 +96,9 @@ public function __construct( \Magento\Framework\Serialize\SerializerInterface::class ); $this->state = $state ?? ObjectManager::getInstance()->get(AppState::class); + $this->fullPageCache = $fullPageCache ?? ObjectManager::getInstance()->get( + \Magento\PageCache\Model\Cache\Type::class + ); } /** @@ -104,7 +109,7 @@ public function __construct( public function load() { if ($this->request->isGet() || $this->request->isHead()) { - $responseData = $this->getCache()->load($this->identifier->getValue()); + $responseData = $this->fullPageCache->load($this->identifier->getValue()); if (!$responseData) { return false; } @@ -143,7 +148,7 @@ public function process(\Magento\Framework\App\Response\Http $response) header_remove('Set-Cookie'); } - $this->getCache()->save( + $this->fullPageCache->save( $this->serializer->serialize($this->getPreparedData($response)), $this->identifier->getValue(), $tags, @@ -197,19 +202,4 @@ private function buildResponse($responseData) return $response; } - - /** - * TODO: Workaround to support backwards compatibility, will rework to use Dependency Injection in MAGETWO-49547 - * - * @return \Magento\PageCache\Model\Cache\Type - */ - private function getCache() - { - if (!$this->fullPageCache) { - $this->fullPageCache = ObjectManager::getInstance()->get( - \Magento\PageCache\Model\Cache\Type::class - ); - } - return $this->fullPageCache; - } } From 4ba98bfee94828e4dc36afd9d34f24db43ab42ab Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Thu, 18 Apr 2019 17:29:21 -0500 Subject: [PATCH 403/585] GraphQL-597: Test coverage for cart-not cached test - minor changes to annotations --- .../Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php index e0c57ea373820..0ef60e1fbde36 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php @@ -7,7 +7,6 @@ namespace Magento\GraphQl\PageCache\Quote\Guest; -use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; /** @@ -27,6 +26,7 @@ protected function setUp() 'This test will stay skipped until DEVOPS-4924 is resolved' ); } + /** * Tests that X-Magento-Tags are correct */ @@ -52,9 +52,9 @@ public function testCartIsNotCached() /** * Create a guest cart which generates a maskedQuoteId * - * @return mixed + * @return string */ - private function createEmptyCart() + private function createEmptyCart(): string { $query = <<<QUERY From f7b6040e7e02f78476da87cd299341b75d73eec5 Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Fri, 19 Apr 2019 10:08:56 +0300 Subject: [PATCH 404/585] MC-11941: Delete Product Attribute --- .../ProductAttribute/DeleteProductAttributeEntityTest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml index 11ba7266ce564..0dd47942c8fe0 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml @@ -16,7 +16,6 @@ <constraint name="Magento\ImportExport\Test\Constraint\AssertProductAttributeAbsenceForExport" /> </variation> <variation name="DeleteProductAttributeEntityTestVariation2"> - <data name="tag" xsi:type="string">stable:no</data> <data name="attribute/dataset" xsi:type="string">attribute_type_dropdown</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeSuccessDeleteMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeAbsenceInGrid" /> From c3c2a005b7bc0edbf0cb04e7b1c0fde7d74d5642 Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Fri, 19 Apr 2019 12:55:29 +0530 Subject: [PATCH 405/585] Spelling correction --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b86c7b79a0cbd..f30c2c64e06fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4335,7 +4335,7 @@ Tests: * Fixed order placing with virtual product using Express Checkout * Fixed the error during order placement with Recurring profile payment * Fixed wrong redirect after customer registration during multishipping checkout - * Fixed inability to crate shipping labels + * Fixed inability to create shipping labels * Fixed inability to switch language, if the default language is English * Fixed an issue with incorrect XML appearing in cache after some actions on the frontend * Fixed product export From 9f994f5c783ad5403a750f54abde9553829b6b8b Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Fri, 19 Apr 2019 11:19:49 +0300 Subject: [PATCH 406/585] MC-11936: Update Product Attribute --- .../ProductAttribute/UpdateProductAttributeEntityTest.php | 1 - .../ProductAttribute/UpdateProductAttributeEntityTest.xml | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php index 6203f304540c1..b714c61f70198 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php @@ -34,7 +34,6 @@ class UpdateProductAttributeEntityTest extends Injectable { /* tags */ - const MVP = 'yes'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml index 40cf8e40ae33f..d6420ff431ce6 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml @@ -8,7 +8,6 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\UpdateProductAttributeEntityTest" summary="Update Product Attribute" ticketId="MAGETWO-23459"> <variation name="UpdateProductAttributeEntityTestVariation1"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttributeOriginal/dataset" xsi:type="string">attribute_type_text_field</data> <data name="attribute/data/frontend_label" xsi:type="string">Text_Field_%isolation%</data> @@ -29,7 +28,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> </variation> <variation name="UpdateProductAttributeEntityTestVariation2"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttributeOriginal/dataset" xsi:type="string">attribute_type_dropdown</data> <data name="attribute/data/frontend_label" xsi:type="string">Dropdown_%isolation%</data> @@ -55,6 +53,8 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> </variation> <variation name="UpdateProductAttributeEntityTestVariation3"> + <data name="issue" xsi:type="string">MAGETWO-46494: [FT] UpdateProductAttributeEntityTestVariation3 does not actually create an attribute to check</data> + <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttributeOriginal/dataset" xsi:type="string">tax_class_id</data> <data name="attribute/data/is_searchable" xsi:type="string">Yes</data> @@ -62,7 +62,6 @@ <data name="cacheTags" xsi:type="array"> <item name="0" xsi:type="string">FPC</item> </data> - <data name="tag" xsi:type="string">to_maintain:yes</data> <constraint name="Magento\PageCache\Test\Constraint\AssertCacheIsRefreshableAndInvalidated" /> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAdvancedSearchProductByAttribute" /> </variation> From a168a3e1a618c967314fc27a556303530dfd2c26 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 19 Apr 2019 13:57:01 +0300 Subject: [PATCH 407/585] Fix static tests. --- .../Eav/Model/Entity/Attribute/Source/AbstractSource.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php index b291b7b28d5b7..a81d437acea36 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\Entity\Attribute\Source; /** @@ -65,7 +66,7 @@ public function getOptionText($value) { $options = $this->getAllOptions(); // Fixed for tax_class_id and custom_design - if (sizeof($options) > 0) { + if (count($options) > 0) { foreach ($options as $option) { if (isset($option['value']) && $option['value'] == $value) { return isset($option['label']) ? $option['label'] : $option['value']; @@ -168,10 +169,11 @@ public function toOptionArray() } /** - * Multibyte support strcasecmp function version + * Multibyte support strcasecmp function version. + * * @param string $str1 * @param string $str2 - * @return int|\\lt + * @return int */ private function mbStrcasecmp($str1, $str2) { From aeaff53ca08850ecf6e2b97580810190ddad9087 Mon Sep 17 00:00:00 2001 From: YaroslavHolovanych <yaroslavh@gmail.com> Date: Fri, 19 Apr 2019 14:30:25 +0300 Subject: [PATCH 408/585] MC-11937: Add Products to Shopping Cart --- .../Test/TestCase/AddProductsToShoppingCartEntityTest.xml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml index 8d054c0230873..c0df4b16b92e6 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml @@ -22,7 +22,6 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation2"> - <data name="tag" xsi:type="string">to_maintain:yes, severity:S2</data> <data name="productsData/0" xsi:type="string">bundleProduct::bundle_fixed_product</data> <data name="cart/data/grand_total" xsi:type="string">761</data> <data name="cart/data/subtotal" xsi:type="string">756</data> @@ -35,7 +34,6 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation3"> - <data name="tag" xsi:type="string">to_maintain:yes, severity:S0</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::with_two_custom_option</data> <data name="cart/data/grand_total" xsi:type="string">345</data> <data name="cart/data/subtotal" xsi:type="string">340</data> @@ -48,7 +46,6 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation4"> - <data name="tag" xsi:type="string">to_maintain:yes, severity:S1</data> <data name="productsData/0" xsi:type="string">catalogProductVirtual::product_50_dollar</data> <data name="cart/data/grand_total" xsi:type="string">50</data> <data name="cart/data/subtotal" xsi:type="string">50</data> @@ -100,8 +97,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation8" summary="Enable https in backend and add products of different types to cart" ticketId="MAGETWO-42677"> - <data name="tag" xsi:type="string">to_maintain:yes, severity:S0</data> - <data name="issue" xsi:type="string">Errors on configuration step. Skipped.</data> + <data name="tag" xsi:type="string">severity:S0</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::with_two_custom_option</data> <data name="productsData/1" xsi:type="string">catalogProductVirtual::product_50_dollar</data> <data name="productsData/2" xsi:type="string">downloadableProduct::with_two_separately_links</data> From 5bc05b22c10927b9ec1f3c12daba8c09e35940b7 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 19 Apr 2019 14:48:04 +0300 Subject: [PATCH 409/585] Fix static tests. --- .../Magento/Backup/Controller/Adminhtml/Index/Rollback.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php b/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php index 51fa0ef8f65ad..7f450e7e313cc 100644 --- a/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php +++ b/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php @@ -6,13 +6,16 @@ */ namespace Magento\Backup\Controller\Adminhtml\Index; +use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; /** + * Backup rollback controller. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Rollback extends \Magento\Backup\Controller\Adminhtml\Index +class Rollback extends \Magento\Backup\Controller\Adminhtml\Index implements HttpPostActionInterface { /** * Rollback Action @@ -124,6 +127,7 @@ public function execute() $adminSession->destroy(); $response->setRedirectUrl($this->getUrl('*')); + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (\Magento\Framework\Backup\Exception\CantLoadSnapshot $e) { $errorMsg = __('We can\'t find the backup file.'); } catch (\Magento\Framework\Backup\Exception\FtpConnectionFailed $e) { From 651f1d9a0252c6dcafb20e98b4f8b54c3d441281 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 19 Apr 2019 15:08:57 +0300 Subject: [PATCH 410/585] Fix static tests. --- .../Magento/Catalog/Model/Product/Gallery/CreateHandler.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php index d6416a024c6df..d2ad6748a9f83 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php @@ -420,6 +420,7 @@ protected function copyImage($file) $destinationFile = $this->getUniqueFileName($file); if (!$this->mediaDirectory->isFile($this->mediaConfig->getMediaPath($file))) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception(); } @@ -437,6 +438,7 @@ protected function copyImage($file) } return str_replace('\\', '/', $destinationFile); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Exception $e) { $file = $this->mediaConfig->getMediaPath($file); throw new \Magento\Framework\Exception\LocalizedException( From e78592a2045d0408f93272a298bc1e967b5548ed Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 19 Apr 2019 15:16:10 +0300 Subject: [PATCH 411/585] Fix static test. --- app/code/Magento/Checkout/view/frontend/web/js/view/payment.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js index ad6f39b7d6d5f..e8994c61b7221 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js @@ -66,7 +66,7 @@ define([ navigate: function () { var self = this; - if(!self.hasShippingMethod()) { + if (!self.hasShippingMethod()) { this.isVisible(false); stepNavigator.setHash('shipping'); } else { From a45d5196c23985068c8250a9d79fae25e89b4a1d Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 19 Apr 2019 15:46:13 +0300 Subject: [PATCH 412/585] magento/magento2#22178: Static test fix. --- .../Magento/Catalog/Model/Product/Copier.php | 17 ++++---- .../Test/Unit/Model/Product/CopierTest.php | 39 +++++++++++-------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Copier.php b/app/code/Magento/Catalog/Model/Product/Copier.php index 3e899decaeb55..44ebdf0f1f283 100644 --- a/app/code/Magento/Catalog/Model/Product/Copier.php +++ b/app/code/Magento/Catalog/Model/Product/Copier.php @@ -1,7 +1,5 @@ <?php /** - * Catalog product copier. Creates product duplicate - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -11,7 +9,11 @@ use Magento\Catalog\Model\Product; /** - * The copier creates product duplicates. + * Catalog product copier. + * + * Creates product duplicate. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Copier { @@ -120,10 +122,10 @@ private function setStoresUrl(Product $product, Product $duplicate) : void $productId = $product->getId(); $productResource = $product->getResource(); $defaultUrlKey = $productResource->getAttributeRawValue( - $productId, - 'url_key', - \Magento\Store\Model\Store::DEFAULT_STORE_ID - ); + $productId, + 'url_key', + \Magento\Store\Model\Store::DEFAULT_STORE_ID + ); $duplicate->setData('save_rewrites_history', false); foreach ($storeIds as $storeId) { $isDuplicateSaved = false; @@ -139,6 +141,7 @@ private function setStoresUrl(Product $product, Product $duplicate) : void try { $duplicate->save(); $isDuplicateSaved = true; + // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { } } while (!$isDuplicateSaved); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php index 7ae5f70285faa..80b6db2a516bd 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php @@ -6,10 +6,12 @@ namespace Magento\Catalog\Test\Unit\Model\Product; use Magento\Catalog\Api\Data\ProductInterface; -use \Magento\Catalog\Model\Product\Copier; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Copier; /** + * Test for Magento\Catalog\Model\Product\Copier class. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CopierTest extends \PHPUnit\Framework\TestCase @@ -76,6 +78,9 @@ protected function setUp() ]); } + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ public function testCopy() { $stockItem = $this->getMockBuilder(\Magento\CatalogInventory\Api\Data\StockItemInterface::class) @@ -104,27 +109,27 @@ public function testCopy() ]); $entityMock = $this->getMockForAbstractClass( - \Magento\Eav\Model\Entity\AbstractEntity::class, - [], - '', - false, - true, - true, - ['checkAttributeUniqueValue'] - ); + \Magento\Eav\Model\Entity\AbstractEntity::class, + [], + '', + false, + true, + true, + ['checkAttributeUniqueValue'] + ); $entityMock->expects($this->any()) ->method('checkAttributeUniqueValue') ->willReturn(true); $attributeMock = $this->getMockForAbstractClass( - \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class, - [], - '', - false, - true, - true, - ['getEntity'] - ); + \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class, + [], + '', + false, + true, + true, + ['getEntity'] + ); $attributeMock->expects($this->any()) ->method('getEntity') ->willReturn($entityMock); From ce4c1e3508363258c17267450eab0bfe9bf70ca6 Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Fri, 19 Apr 2019 15:47:24 +0300 Subject: [PATCH 413/585] MC-11936: Update Product Attribute --- .../ProductAttribute/UpdateProductAttributeEntityTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php index b714c61f70198..6203f304540c1 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php @@ -34,6 +34,7 @@ class UpdateProductAttributeEntityTest extends Injectable { /* tags */ + const MVP = 'yes'; /* end tags */ /** From b6784b5fab4d6d2b4fdf826b96b8a42b202dc631 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 19 Apr 2019 16:24:52 +0300 Subject: [PATCH 414/585] magento/magento2#22382: Static test fix. --- .../Magento/CatalogImportExport/Model/Import/Product.php | 6 +++++- .../CatalogImportExport/Model/Import/ProductTest.php | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index c6ce3e24ce02f..edeb955b19c9b 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -1247,6 +1247,7 @@ protected function _prepareRowForDb(array $rowData) * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * phpcs:disable Generic.Metrics.NestingLevel */ protected function _saveLinks() { @@ -1256,7 +1257,7 @@ protected function _saveLinks() $nextLinkId = $this->_resourceHelper->getNextAutoincrement($mainTable); // pre-load 'position' attributes ID for each link type once - foreach ($this->_linkNameToId as $linkName => $linkId) { + foreach ($this->_linkNameToId as $linkId) { $select = $this->_connection->select()->from( $resource->getTable('catalog_product_link_attribute'), ['id' => 'product_link_attribute_id'] @@ -1374,6 +1375,7 @@ protected function _saveLinks() } return $this; } + // phpcs:enable /** * Save product attributes. @@ -1608,6 +1610,7 @@ public function getImagesFromRow(array $rowData) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @SuppressWarnings(PHPMD.UnusedLocalVariable) * @throws LocalizedException + * phpcs:disable Generic.Metrics.NestingLevel */ protected function _saveProducts() { @@ -1980,6 +1983,7 @@ protected function _saveProducts() return $this; } + // phpcs:enable /** * Prepare array with image states (visible or hidden from product page) diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index dd2237d6080ca..ceffbc6d138e5 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -34,6 +34,7 @@ * @magentoDataFixtureBeforeTransaction Magento/Catalog/_files/enable_catalog_product_reindex_schedule.php * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * phpcs:disable Generic.PHP.NoSilencedErrors, Generic.Metrics.NestingLevel, Magento2.Functions.StaticFunction */ class ProductTest extends \Magento\TestFramework\Indexer\TestCase { @@ -1820,6 +1821,7 @@ function (ProductInterface $item) { if ($product->getId()) { $productRepository->delete($product); } + // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { //Product already removed } From ab443a09123d90f615e447fef58e5ba6ab22dead Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Thu, 18 Apr 2019 15:08:19 +0300 Subject: [PATCH 415/585] Fix undeclared variables. --- app/code/Magento/Rule/view/adminhtml/web/rules.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Rule/view/adminhtml/web/rules.js b/app/code/Magento/Rule/view/adminhtml/web/rules.js index a15caa08cc0ae..95175d272f9af 100644 --- a/app/code/Magento/Rule/view/adminhtml/web/rules.js +++ b/app/code/Magento/Rule/view/adminhtml/web/rules.js @@ -126,7 +126,7 @@ define([ var values = this.updateElement.value.split(','), s = ''; - for (i = 0; i < values.length; i++) { + for (var i = 0; i < values.length; i++) { s = values[i].strip(); if (s != '') { @@ -255,7 +255,7 @@ define([ if (elem && elem.options) { var selectedOptions = []; - for (i = 0; i < elem.options.length; i++) { + for (var i = 0; i < elem.options.length; i++) { if (elem.options[i].selected) { selectedOptions.push(elem.options[i].text); } From 827c51e53f6d79627a7b4b9f71bcbfba4730d80d Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Fri, 19 Apr 2019 09:36:05 -0500 Subject: [PATCH 416/585] magento-engcom/magento2ce#2771: Fixed code style issues --- .../Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php | 2 +- lib/internal/Magento/Framework/App/Http.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php index 2c32a74eb0f1d..e6c098ab0254e 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php @@ -115,7 +115,7 @@ public function build($storeId, $changedIds, $valueFieldSuffix) /** * Create empty temporary table with given columns list * - * @param string $tableName Table name + * @param string $tableName Table name * @param array $columns array('columnName' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute, ...) * @param string $valueFieldSuffix * diff --git a/lib/internal/Magento/Framework/App/Http.php b/lib/internal/Magento/Framework/App/Http.php index 3564e5e0ecb9b..ca3976da1df52 100644 --- a/lib/internal/Magento/Framework/App/Http.php +++ b/lib/internal/Magento/Framework/App/Http.php @@ -277,7 +277,7 @@ private function redirectToSetup(Bootstrap $bootstrap, \Exception $exception) * Handler for bootstrap errors * * @param Bootstrap $bootstrap - * @param \Exception &$exception + * @param \Exception $exception * @return bool */ private function handleBootstrapErrors(Bootstrap $bootstrap, \Exception &$exception) From a7d1f1b183b573bb8dbcfb7e266759a1bb647ba5 Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Fri, 19 Apr 2019 17:44:36 +0300 Subject: [PATCH 417/585] MAGETWO-98584: Google chart API used by Magento dashboard scheduled to be turned off --- .../Magento/Backend/Block/Dashboard/Graph.php | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Backend/Block/Dashboard/Graph.php b/app/code/Magento/Backend/Block/Dashboard/Graph.php index f57b03fdbfa0b..b76421e4e6f67 100644 --- a/app/code/Magento/Backend/Block/Dashboard/Graph.php +++ b/app/code/Magento/Backend/Block/Dashboard/Graph.php @@ -114,8 +114,8 @@ public function __construct( \Magento\Backend\Helper\Dashboard\Data $dashboardData, array $data = [] ) { - $this->_dashboardData = $dashboardData; parent::__construct($context, $collectionFactory, $data); + $this->_dashboardData = $dashboardData; } /** @@ -131,7 +131,7 @@ protected function _getTabTemplate() /** * Set data rows * - * @param array $rows + * @param string $rows * @return void */ public function setDataRows($rows) @@ -155,15 +155,14 @@ public function addSeries($seriesId, array $options) * Get series * * @param string $seriesId - * @return array|false + * @return array|bool */ public function getSeries($seriesId) { if (isset($this->_allSeries[$seriesId])) { return $this->_allSeries[$seriesId]; - } else { - return false; } + return false; } /** @@ -308,7 +307,7 @@ public function getChartUrl($directUrl = true) if ($minvalue >= 0 && $maxvalue >= 0) { if ($maxvalue > 10) { - $p = pow(10, $this->_getPow($maxvalue)); + $p = pow(10, $this->_getPow((int) $maxvalue)); $maxy = ceil($maxvalue / $p) * $p; $yLabels = range($miny, $maxy, $p); } else { @@ -349,7 +348,7 @@ public function getChartUrl($directUrl = true) $indexid = 0; foreach ($this->_axisLabels as $idx => $labels) { if ($idx == 'x') { - $this->formatAxisLabelDate($idx, $timezoneLocal); + $this->formatAxisLabelDate((string) $idx, (string) $timezoneLocal); $tmpstring = implode('|', $this->_axisLabels[$idx]); $valueBuffer[] = $indexid . ":|" . $tmpstring; } elseif ($idx == 'y') { @@ -369,13 +368,12 @@ public function getChartUrl($directUrl = true) foreach ($params as $name => $value) { $p[] = $name . '=' . urlencode($value); } - return self::API_URL . '?' . implode('&', $p); - } else { - $gaData = urlencode(base64_encode(json_encode($params))); - $gaHash = $this->_dashboardData->getChartDataHash($gaData); - $params = ['ga' => $gaData, 'h' => $gaHash]; - return $this->getUrl('adminhtml/*/tunnel', ['_query' => $params]); + return (string) self::API_URL . '?' . implode('&', $p); } + $gaData = urlencode(base64_encode(json_encode($params))); + $gaHash = $this->_dashboardData->getChartDataHash($gaData); + $params = ['ga' => $gaData, 'h' => $gaHash]; + return $this->getUrl('adminhtml/*/tunnel', ['_query' => $params]); } /** @@ -394,7 +392,7 @@ private function formatAxisLabelDate($idx, $timezoneLocal) switch ($this->getDataHelper()->getParam('period')) { case '24h': $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime( - $period->setTime($period->format('H'), 0, 0), + $period->setTime((int) $period->format('H'), 0, 0), \IntlDateFormatter::NONE, \IntlDateFormatter::SHORT ); From 82c2eab9edb06d4e242fd0436d262a015f0eabd1 Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Fri, 19 Apr 2019 10:50:01 -0500 Subject: [PATCH 418/585] 230: Implement cache tag generation for GraphQL queries - Added integration tests for cache tag in the schema --- .../Framework/GraphQl/GraphQlConfigTest.php | 29 ++++++++++++------- .../GraphQl/_files/query_array_output.php | 6 +++- .../Framework/GraphQl/_files/schemaC.graphqls | 2 +- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/GraphQlConfigTest.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/GraphQlConfigTest.php index ef4612ea357ea..5668c1bef6687 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/GraphQlConfigTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/GraphQlConfigTest.php @@ -7,11 +7,8 @@ namespace Magento\Framework\GraphQl; -use Magento\Framework\App\Bootstrap; use Magento\Framework\App\Cache; -use Magento\Framework\Config\FileResolverInterface; use Magento\Framework\GraphQl\Config\Config; -use Magento\Framework\GraphQl\Config\ConfigElementInterface; use Magento\Framework\GraphQl\Config\Data\Argument; use Magento\Framework\GraphQl\Config\Data\Enum; use Magento\Framework\GraphQl\Config\Data\Field; @@ -19,9 +16,11 @@ use Magento\Framework\GraphQl\Config\Data\Type; use Magento\Framework\GraphQl\Config\Element\EnumValue; use Magento\Framework\GraphQl\Config\Element\InterfaceType; -use Magento\Framework\GraphQl\Config\Element\TypeFactory; use Magento\Framework\ObjectManagerInterface; +/** + * Test of schema configuration reading and parsing + */ class GraphQlConfigTest extends \PHPUnit\Framework\TestCase { /** @var \Magento\Framework\GraphQl\Config */ @@ -76,7 +75,12 @@ public function testGraphQlTypeAndFieldConfigStructure() ['response_field' => 'required', 'expected_value' => $queryFields[$fieldKey]->isRequired()], ['response_field' => 'isList', 'expected_value' => $queryFields[$fieldKey]->isList()], ['response_field' => 'resolver', 'expected_value' => $queryFields[$fieldKey]->getResolver()], - ['response_field' => 'description', 'expected_value' => $queryFields[$fieldKey]->getDescription()] + ['response_field' => 'description', 'expected_value' => $queryFields[$fieldKey]->getDescription()], + [ + 'response_field' => 'cache', + 'expected_value' => $queryFields[$fieldKey]->getCache(), + 'optional' => true + ] ]; $this->assertResponseFields($expectedOutputArray['Query']['fields'][$fieldKey], $fieldAssertionMap); /** @var \Magento\Framework\GraphQl\Config\Element\Argument $queryFieldArguments */ @@ -212,12 +216,15 @@ private function assertResponseFields($actualResponse, $assertionMap) $expectedValue, "Value of '{$responseField}' field must not be NULL" ); - $this->assertEquals( - $expectedValue, - $actualResponse[$responseField], - "Value of '{$responseField}' field in response does not match expected value: " - . var_export($expectedValue, true) - ); + $optionalField = isset($assertionData['optional']) ? $assertionData['optional'] : false; + if (!$optionalField || isset($actualResponse[$responseField])) { + $this->assertEquals( + $expectedValue, + $actualResponse[$responseField], + "Value of '{$responseField}' field in response does not match expected value: " + . var_export($expectedValue, true) + ); + } } } diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php index 9ebd0160240a8..f7c2597fe5710 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php @@ -32,7 +32,11 @@ 'required' => false, 'isList' => false, 'resolver' => 'Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata', - 'description' => 'Returns the attribute type, given an attribute code and entity type' + 'description' => 'Returns the attribute type, given an attribute code and entity type', + 'cache' => [ + 'cacheTag' => 'cat_test', + 'cacheIdentityResolver' => 'Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata' + ] ], 'products' => [ 'name' => 'products', diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/schemaC.graphqls b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/schemaC.graphqls index 84609293f31a8..895185bc6dd2f 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/schemaC.graphqls +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/schemaC.graphqls @@ -1,6 +1,6 @@ type Query { customAttributeMetadata(attributes: [AttributeInput!]!): CustomAttributeMetadata @resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata") - @doc(description: "Returns the attribute type, given an attribute code and entity type") + @doc(description: "Returns the attribute type, given an attribute code and entity type") @cache(cacheTag: "cat_test", cacheIdentityResolver: "Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata") } type CustomAttributeMetadata { From bc8efd2c46924888080186b30ecdcc435333074c Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 19 Apr 2019 11:05:47 -0500 Subject: [PATCH 419/585] Minor fixes for magento/magento-functional-tests-migration#387: Convert ResetUserPasswordFailedTest to MFTF --- .../AssertMessageOnAdminLoginActionGroup.xml | 2 ++ .../Backend/Test/Mftf/Page/AdminLoginPage.xml | 2 +- .../Mftf/Section/AdminLoginFormSection.xml | 2 +- .../Section/AdminUserLoginMessagesSection.xml | 15 --------------- .../Test/AdminResetUserPasswordFailedTest.xml | 19 +++++++++++++++++++ ...AssertAdminLoginPageMessageActionGroup.xml | 19 ------------------- .../Test/AdminResetUserPasswordFailedTest.xml | 10 ++-------- 7 files changed, 25 insertions(+), 44 deletions(-) delete mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml delete mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml index ccc7cd24350c5..607fba3736c42 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml @@ -13,6 +13,8 @@ <argument name="message" type="string" defaultValue="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." /> <argument name="messageType" type="string" defaultValue="error" /> </arguments> + + <waitForElementVisible selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="waitForAdminLoginFormMessage" /> <see userInput="{{message}}" selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="verifyMessage" /> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml b/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml index a499c8f5ed7a7..78226d79273d9 100644 --- a/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml +++ b/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml @@ -9,7 +9,7 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminLoginPage" url="admin" area="admin" module="Magento_Backend"> - <section name="AdminUserLoginMessagesSection"/> + <section name="AdminLoginMessagesSection"/> <section name="AdminLoginFormSection"/> </page> </pages> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 9092ef31bbdca..bd65dea89abc2 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,6 +12,6 @@ <element name="username" type="input" selector="#username"/> <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> - <element name="forgotPasswordLink" type="link" selector=".action-forgotpassword" timeout="10"/> + <element name="forgotPasswordLink" type="button" selector=".action-forgotpassword" timeout="10"/> </section> </sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml deleted file mode 100644 index 209a795dc48ae..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="AdminUserLoginMessagesSection"> - <element name="successMessage" type="text" selector=".message-success"/> - <element name="errorMessage" type="text" selector=".message-error"/> - </section> -</sections> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml new file mode 100644 index 0000000000000..8f9c5828e2f5e --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminResetUserPasswordFailedTest"> + <before> + <magentoCLI command="config:set {{AdminCaptchaDisableConfigData.path}} {{AdminCaptchaDisableConfigData.value}} " stepKey="disableAdminCaptcha"/> + </before> + <after> + <magentoCLI command="config:set {{AdminCaptchaEnableConfigData.path}} {{AdminCaptchaEnableConfigData.value}} " stepKey="enableAdminCaptcha"/> + </after> + </test> +</tests> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml deleted file mode 100644 index 5535d2314a69f..0000000000000 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertAdminLoginPageMessageActionGroup"> - <arguments> - <argument name="messageType" type="string"/> - <argument name="message" type="string"/> - </arguments> - - <waitForElementVisible selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="waitForAdminLoginFormMessage" /> - <see userInput="{{message}}" selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="seeAdminLoginFormMessage"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml index 0d66ed38d4310..e3889b7396a2c 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml @@ -16,12 +16,6 @@ <group value="security"/> <group value="mtf_migrated"/> </annotations> - <before> - <magentoCLI command="config:set {{AdminCaptchaDisableConfigData.path}} {{AdminCaptchaDisableConfigData.value}} " stepKey="disableAdminCaptcha"/> - </before> - <after> - <magentoCLI command="config:set {{AdminCaptchaEnableConfigData.path}} {{AdminCaptchaEnableConfigData.value}} " stepKey="enableAdminCaptcha"/> - </after> <!-- First attempt to reset password --> <actionGroup ref="AdminOpenForgotPasswordPageActionGroup" stepKey="openAdminForgotPasswordPage1"/> @@ -29,7 +23,7 @@ <argument name="email" value="customer@example.com"/> </actionGroup> <actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordForm1"/> - <actionGroup ref="AssertAdminLoginPageMessageActionGroup" stepKey="seeSuccessMessage"> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeSuccessMessage"> <argument name="messageType" value="success"/> <argument name="message" value="We'll email you a link to reset your password."/> </actionGroup> @@ -40,7 +34,7 @@ <argument name="email" value="customer@example.com"/> </actionGroup> <actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordForm2"/> - <actionGroup ref="AssertAdminLoginPageMessageActionGroup" stepKey="seeErrorMessage"> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeErrorMessage"> <argument name="messageType" value="error"/> <argument name="message" value="We received too many requests for password resets. Please wait and try again later or contact hello@example.com."/> </actionGroup> From 3ab170807acf688d3e835075c4be6d6f478336e4 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 19 Apr 2019 11:12:03 -0500 Subject: [PATCH 420/585] Minor fixes for magento/magento-functional-tests-migration#387: Convert ResetUserPasswordFailedTest to MFTF --- .../User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml index e3889b7396a2c..4b48c65a18994 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml @@ -13,6 +13,7 @@ <features value="User"/> <title value="Admin user should not be able to trigger the password reset procedure twice"/> <description value="Admin user should not be able to trigger the password reset procedure twice"/> + <testCaseId value="MC-14389" /> <group value="security"/> <group value="mtf_migrated"/> </annotations> From 1ec6304f1b03e35229bbae28c957b0790381ac7d Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Fri, 19 Apr 2019 13:06:35 -0500 Subject: [PATCH 421/585] GraphQL-604: [Test coverage] End to tests for customer checkout workflow --- .../Quote/Customer/CheckoutEndToEndTest.php | 530 +++++++++++++++ .../Quote/Customer/CreateEmptyCartTest.php | 34 +- .../Quote/Customer/EndToEndCheckoutTest.php | 623 ------------------ .../GraphQl/Quote/Customer/PlaceOrderTest.php | 1 - .../Quote/Guest/CheckoutEndToEndTest.php | 441 +++++++++++++ .../Quote/Guest/CreateEmptyCartTest.php | 34 +- 6 files changed, 989 insertions(+), 674 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php delete mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php new file mode 100644 index 0000000000000..8592a986c5dce --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -0,0 +1,530 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Registry; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\ResourceModel\Order\CollectionFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * End to checkout tests for customer + */ +class CheckoutEndToEndTest extends GraphQlAbstract +{ + /** + * @var Registry + */ + private $registry; + + /** + * @var QuoteCollectionFactory + */ + private $quoteCollectionFactory; + + /** + * @var QuoteResource + */ + private $quoteResource; + + /** + * @var QuoteIdMaskFactory + */ + private $quoteIdMaskFactory; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @var CollectionFactory + */ + private $orderCollectionFactory; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var array + */ + private $headers = []; + + protected function setUp() + { + parent::setUp(); + + $objectManager = Bootstrap::getObjectManager(); + $this->registry = $objectManager->get(Registry::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); + $this->quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); + $this->customerRepository = Bootstrap::getObjectManager()->get(CustomerRepositoryInterface::class); + $this->orderCollectionFactory = $objectManager->get(CollectionFactory::class); + $this->orderRepository = $objectManager->get(OrderRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutWorkflow() + { + $qty = 2; + + $this->createCustomer(); + $token = $this->loginCustomer(); + $this->headers = ['Authorization' => 'Bearer ' . $token]; + + $sku = $this->findProduct(); + $cartId = $this->createEmptyCart(); + $this->addProductToCart($cartId, $qty, $sku); + + $this->setBillingAddress($cartId); + $shippingAddress = $this->setShippingAddress($cartId); + + $shippingMethod = current($shippingAddress['available_shipping_methods']); + $paymentMethod = $this->setShippingMethod($cartId, $shippingAddress['address_id'], $shippingMethod); + $this->setPaymentMethod($cartId, $paymentMethod); + + $orderId = $this->placeOrder($cartId); + $this->checkOrderInHistory($orderId); + } + + /** + * @return void + */ + private function createCustomer(): void + { + $query = <<<QUERY +mutation { + createCustomer( + input: { + firstname: "endto" + lastname: "endtester" + email: "customer@example.com" + password: "123123Qa" + } + ) { + customer { + id + } + } +} +QUERY; + $this->graphQlMutation($query); + } + + /** + * @return string + */ + private function loginCustomer(): string + { + $query = <<<QUERY +mutation { + generateCustomerToken( + email: "customer@example.com" + password: "123123Qa" + ) { + token + } +} +QUERY; + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('generateCustomerToken', $response); + self::assertArrayHasKey('token', $response['generateCustomerToken']); + self::assertNotEmpty($response['generateCustomerToken']['token']); + + return $response['generateCustomerToken']['token']; + } + + /** + * @return string + */ + private function findProduct(): string + { + $query = <<<QUERY +{ + products ( + filter: { + sku: { + like:"simple%" + } + } + pageSize: 1 + currentPage: 1 + ) { + items { + sku + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('products', $response); + self::assertArrayHasKey('items', $response['products']); + self::assertCount(1, $response['products']['items']); + + $product = current($response['products']['items']); + self::assertArrayHasKey('sku', $product); + self::assertNotEmpty($product['sku']); + + return $product['sku']; + } + + /** + * @return string + */ + private function createEmptyCart(): string + { + $query = <<<QUERY +mutation { + createEmptyCart +} +QUERY; + $response = $this->graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); + + return $response['createEmptyCart']; + } + + /** + * @param string $cartId + * @param float $qty + * @param string $sku + * @return void + */ + private function addProductToCart(string $cartId, float $qty, string $sku): void + { + $query = <<<QUERY +mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$cartId}" + cartItems: [ + { + data: { + qty: {$qty} + sku: "{$sku}" + } + } + ] + } + ) { + cart { + items { + qty + product { + sku + } + } + } + } +} +QUERY; + $this->graphQlMutation($query, [], '', $this->headers); + } + + /** + * @param string $cartId + * @param array $auth + * @return array + */ + private function setBillingAddress(string $cartId): void + { + $query = <<<QUERY +mutation { + setBillingAddressOnCart( + input: { + cart_id: "{$cartId}" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + postcode: "887766" + telephone: "88776655" + region: "TX" + country_code: "US" + save_in_address_book: false + } + } + } + ) { + cart { + billing_address { + address_type + } + } + } +} +QUERY; + $this->graphQlMutation($query, [], '', $this->headers); + } + + /** + * @param string $cartId + * @return array + */ + private function setShippingAddress(string $cartId): array + { + $query = <<<QUERY +mutation { + setShippingAddressesOnCart( + input: { + cart_id: "$cartId" + shipping_addresses: [ + { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + region: "TX" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: false + } + } + ] + } + ) { + cart { + shipping_addresses { + address_id + available_shipping_methods { + carrier_code + method_code + amount + } + } + } + } +} +QUERY; + $response = $this->graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('setShippingAddressesOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingAddressesOnCart']['cart']); + self::assertCount(1, $response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('address_id', $shippingAddress); + self::assertNotEmpty($shippingAddress['address_id']); + self::assertArrayHasKey('available_shipping_methods', $shippingAddress); + self::assertCount(1, $shippingAddress['available_shipping_methods']); + + $availableShippingMethod = current($shippingAddress['available_shipping_methods']); + self::assertArrayHasKey('carrier_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['carrier_code']); + + self::assertArrayHasKey('method_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['method_code']); + + self::assertArrayHasKey('amount', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['amount']); + + return $shippingAddress; + } + + /** + * @param string $cartId + * @param int $addressId + * @param array $method + * @return array + */ + private function setShippingMethod(string $cartId, int $addressId, array $method): array + { + $query = <<<QUERY +mutation { + setShippingMethodsOnCart(input: { + cart_id: "{$cartId}", + shipping_methods: [ + { + cart_address_id: {$addressId} + carrier_code: "{$method['carrier_code']}" + method_code: "{$method['method_code']}" + } + ] + }) { + cart { + available_payment_methods { + code + title + } + } + } +} +QUERY; + $response = $this->graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('available_payment_methods', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + + $availablePaymentMethod = current($response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + self::assertArrayHasKey('code', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['code']); + self::assertArrayHasKey('title', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['title']); + + return $availablePaymentMethod; + } + + /** + * @param string $cartId + * @param array $method + * @return void + */ + private function setPaymentMethod(string $cartId, array $method): void + { + $query = <<<QUERY +mutation { + setPaymentMethodOnCart( + input: { + cart_id: "{$cartId}" + payment_method: { + code: "{$method['code']}" + } + } + ) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + $this->graphQlMutation($query, [], '', $this->headers); + } + + /** + * @param string $cartId + * @return string + */ + private function placeOrder(string $cartId): string + { + $query = <<<QUERY +mutation { + placeOrder( + input: { + cart_id: "{$cartId}" + } + ) { + order { + order_id + } + } +} +QUERY; + $response = $this->graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('placeOrder', $response); + self::assertArrayHasKey('order', $response['placeOrder']); + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertNotEmpty($response['placeOrder']['order']['order_id']); + + return $response['placeOrder']['order']['order_id']; + } + + /** + * @param string $orderId + * @return void + */ + private function checkOrderInHistory(string $orderId): void + { + $query = <<<QUERY +{ + customerOrders { + items { + increment_id + grand_total + } + } +} +QUERY; + $response = $this->graphQlQuery($query, [], '', $this->headers); + self::assertArrayHasKey('customerOrders', $response); + self::assertArrayHasKey('items', $response['customerOrders']); + self::assertCount(1, $response['customerOrders']['items']); + + $order = current($response['customerOrders']['items']); + self::assertArrayHasKey('increment_id', $order); + self::assertEquals($orderId, $order['increment_id']); + + self::assertArrayHasKey('grand_total', $order); + } + + public function tearDown() + { + $this->deleteCustomer(); + $this->deleteQuote(); + $this->deleteOrder(); + parent::tearDown(); + } + + /** + * @return void + */ + private function deleteCustomer(): void + { + $email = 'customer@example.com'; + try { + $customer = $this->customerRepository->get($email); + } catch (\Exception $exception) { + return; + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + $this->customerRepository->delete($customer); + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + } + + /** + * @return void + */ + private function deleteQuote(): void + { + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { + $this->quoteResource->delete($quote); + + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quote->getId()) + ->delete(); + } + } + + /** + * @return void + */ + private function deleteOrder() + { + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + + $orderCollection = $this->orderCollectionFactory->create(); + foreach ($orderCollection as $order) { + $this->orderRepository->delete($order); + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php index fc66e4647e576..56ef78811dd1f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php @@ -8,9 +8,8 @@ namespace Magento\GraphQl\Quote\Customer; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -32,38 +31,27 @@ class CreateEmptyCartTest extends GraphQlAbstract private $customerTokenService; /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory + * @var QuoteCollectionFactory */ - private $quoteFactory; + private $quoteCollectionFactory; /** - * @var MaskedQuoteIdToQuoteIdInterface + * @var QuoteResource */ - private $maskedQuoteIdToQuoteId; + private $quoteResource; /** * @var QuoteIdMaskFactory */ private $quoteIdMaskFactory; - /** - * @var string - */ - private $maskedQuoteId; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); } @@ -79,7 +67,6 @@ public function testCreateEmptyCart() self::assertNotEmpty($response['createEmptyCart']); $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); @@ -138,15 +125,12 @@ private function getHeaderMapWithCustomerToken( public function tearDown() { - if (null !== $this->maskedQuoteId) { - $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); - - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $quoteId); + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { $this->quoteResource->delete($quote); $quoteIdMask = $this->quoteIdMaskFactory->create(); - $quoteIdMask->setQuoteId($quoteId) + $quoteIdMask->setQuoteId($quote->getId()) ->delete(); } parent::tearDown(); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php deleted file mode 100644 index 0354356d6927c..0000000000000 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php +++ /dev/null @@ -1,623 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQl\Quote\Customer; - -use Magento\TestFramework\TestCase\GraphQlAbstract; - -/** - * End to checkout tests for customers and guests - */ -class EndToEndCheckoutTest extends GraphQlAbstract -{ - /** - * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php - */ - public function testCheckoutAsCustomer() - { - $email = 'e2e_1@example.com'; - - $this->graphQlMutation($this->buildCreateCustomerMutation($email)); - $authHeader = $this->createAuthHeader($email); - - $cartId = $this->createEmptyCart($authHeader); - $cart = $this->configureQuote($cartId, $authHeader); - - $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId), [], '', $authHeader); - $orderId = $placeOrderResult['placeOrder']['order']['order_id']; - $this->assertNotEmpty($orderId); - - $order = $this->getOrderFromHistory($orderId, $authHeader); - $this->assertEquals($cart['prices']['grand_total']['value'], $order['grand_total']); - //TODO: Make additional assertions when order properties are added - } - - /** - * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php - */ - public function testCheckoutAsGuest() - { - $email = 'e2e_2@example.com'; - $cartId = $this->createEmptyCart(); - $this->graphQlMutation($this->buildSetGuestEmailOnCartMutation($cartId, $email)); - $this->configureQuote($cartId); - - $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId)); - $orderId = $placeOrderResult['placeOrder']['order']['order_id']; - - $this->assertNotEmpty($orderId); - } - - /** - * Configures cart with order placement requirements - * - * @param string $cartId - * @param array $headers - * @return array - */ - private function configureQuote(string $cartId, array $headers = []): array - { - $expectedTotal = 5.99; - $expectedQty = 1; - - $sku = $this->getSku($headers); - $addToCartResult = $this->graphQlMutation($this->buildAddToCartMutation($cartId, $expectedQty, $sku), [], '', $headers); - $cart = $addToCartResult['addSimpleProductsToCart']['cart']; - $this->assertGrandTotal($expectedTotal, $cart); - - $address = $this->setShippingAddress($cartId, $headers); - $shippingMethod = $this->extractFirstAvailableShippingMethod($address); - - $cart = $this->setShippingMethod($cartId, $shippingMethod, $address, $headers); - $expectedTotal += $shippingMethod['amount']; - $this->assertGrandTotal($expectedTotal, $cart); - $this->assertSelectedShippingMethod($shippingMethod, $cart); - - $setBillingAddressResult = $this->graphQlMutation($this->buildSetNewBillingAddressMutation($cartId), [], '', $headers); - $cart = $setBillingAddressResult['setBillingAddressOnCart']['cart']; - $paymentMethod = $this->extractFirstAvailablePaymentMethod($cart); - - $setPaymentResult = $this->graphQlMutation($this->buildSetPaymentMethodMutation($cartId, $paymentMethod), [], '', $headers); - $cart = $setPaymentResult['setPaymentMethodOnCart']['cart']; - $this->assertPaymentMethod($paymentMethod, $cart); - $this->assertGrandTotal($expectedTotal, $cart); - - return $cart; - } - - /** - * Generates customer authentication header for restricted requests - * - * @param string $email - * @return array - */ - private function createAuthHeader(string $email): array - { - $result = $this->graphQlMutation($this->buildLoginMutation($email)); - $token = $result['generateCustomerToken']['token']; - - return ['Authorization' => 'Bearer ' . $token]; - } - - /** - * Creates empty cart for customer or guest - * - * @param array $auth - * @return string - */ - private function createEmptyCart(array $auth = []): string - { - $query = <<<QUERY -mutation { - createEmptyCart -} -QUERY; - - $result = $this->graphQlMutation($query, [], '', $auth); - - return $result['createEmptyCart']; - } - - /** - * Get first SKU returned by catalog search - * - * @param array $auth - * @return string - */ - private function getSku(array $auth): string - { - $result = $this->graphQlQuery($this->buildProductSearchQuery('simple'), [], '', $auth); - $items = $result['products']['items']; - $item = current($items); - - return $item['sku']; - } - - /** - * Set cart shipping address - * - * @param string $cartId - * @param array $auth - * @return array - */ - private function setShippingAddress(string $cartId, array $auth): array - { - $result = $this->graphQlMutation($this->buildSetNewShippingAddressMutation($cartId), [], '', $auth); - $addresses = $result['setShippingAddressesOnCart']['cart']['shipping_addresses']; - - return current($addresses); - } - - /** - * Set cart shipping method - * - * @param string $cartId - * @param array $method - * @param array $address - * @param array $auth - * @return array - */ - private function setShippingMethod(string $cartId, array $method, array $address, array $auth): array - { - $result = $this->graphQlMutation($this->buildSetShippingMethodMutation($cartId, $method, $address), [], '', $auth); - - return $result['setShippingMethodsOnCart']['cart']; - } - - /** - * Get order from history by increment id - * - * @param string $orderId - * @param array $auth - * @return array - */ - private function getOrderFromHistory(string $orderId, array $auth): array - { - $query = <<<QUERY -{ - customerOrders { - items { - increment_id - grand_total - } - } -} -QUERY; - - $result = $this->graphQlQuery($query, [], '', $auth); - $orders = $result['customerOrders']['items']; - - foreach ($orders as $order) { - if ($order['increment_id'] === $orderId) { - return $order; - } - } - - $this->fail(sprintf('No order with increment_id: %s', $orderId)); - } - - /** - * Get first shipping method available from address - * @param array $address - * @return array - */ - private function extractFirstAvailableShippingMethod(array $address): array - { - $methods = $address['available_shipping_methods']; - - return current($methods); - } - - /** - * Get first payment method available from cart - * - * @param array $cart - * @return array - */ - private function extractFirstAvailablePaymentMethod(array $cart): array - { - $methods = $cart['available_payment_methods']; - - return current($methods); - } - - /** - * Assert cart grand total - * - * @param float $expected - * @param array $cart - */ - private function assertGrandTotal(float $expected, array $cart): void - { - $this->assertEquals($expected, $cart['prices']['grand_total']['value']); - } - - /** - * Assert cart payment method - * @param array $method - * @param array $cart - */ - private function assertPaymentMethod(array $method, array $cart): void - { - $this->assertEquals($method['code'], $cart['selected_payment_method']['code']); - } - - /** - * Assert cart shipping method - * - * @param array $expectedMethod - * @param array $cart - */ - private function assertSelectedShippingMethod(array $expectedMethod, array $cart): void - { - $address = current($cart['shipping_addresses']); - $selectedMethod = $address['selected_shipping_method']; - - $this->assertEquals($expectedMethod['carrier_code'], $selectedMethod['carrier_code']); - $this->assertEquals($expectedMethod['method_code'], $selectedMethod['method_code']); - } - - /** - * Build createCustomer mutation - * - * @param string $email - * @return string - */ - private function buildCreateCustomerMutation(string $email): string - { - return <<<QUERY -mutation { - createCustomer( - input: { - firstname: "endto" - lastname: "endtester" - email: "{$email}" - password: "123123Qr" - } - ) { - customer { - id - firstname - lastname - email - } - } -} -QUERY; - } - - /** - * Build generateCustomerToken mutation - * - * @param string $email - * @return string - */ - private function buildLoginMutation(string $email): string - { - return <<<QUERY -mutation { - generateCustomerToken( - email: "{$email}" - password: "123123Qr" - ){ - token - } -} -QUERY; - } - - /** - * Build product search mutation - * - * @param string $term - * @return string - */ - private function buildProductSearchQuery(string $term): string - { - return <<<QUERY -{ - products ( - filter: { - sku: { - like:"{$term}%" - } - } - pageSize: 20 - currentPage: 1 - ) { - items { - sku - } - } -} -QUERY; - } - - /** - * Build addSimpleProductsToCart mutation - * - * @param string $cartId - * @param float $qty - * @param string $sku - * @return string - */ - private function buildAddToCartMutation(string $cartId, float $qty, string $sku): string - { - return <<<QUERY -mutation { - addSimpleProductsToCart( - input: { - cart_id: "{$cartId}" - cartItems: [ - { - data: { - qty: {$qty} - sku: "{$sku}" - } - } - ] - } - ) { - cart { - items { - qty - product { - sku - } - } - prices { - grand_total { - value, - currency - } - } - } - } -} -QUERY; - } - - /** - * Build setShippingAddressesOnCart mutation - * - * @param string $cartId - * @param bool $save - * @return string - */ - private function buildSetNewShippingAddressMutation(string $cartId, bool $save = false): string - { - $save = json_encode($save); - return <<<QUERY -mutation { - setShippingAddressesOnCart( - input: { - cart_id: "$cartId" - shipping_addresses: [ - { - address: { - firstname: "test firstname" - lastname: "test lastname" - company: "test company" - street: ["test street 1", "test street 2"] - city: "test city" - region: "TX" - postcode: "887766" - country_code: "US" - telephone: "88776655" - save_in_address_book: {$save} - } - } - ] - } - ) { - cart { - shipping_addresses { - address_id - available_shipping_methods { - carrier_code - method_code - amount - } - } - } - } -} -QUERY; - } - - /** - * Build setShippingMethodsOnCart mutation - * - * @param string $cartId - * @param array $method - * @param array $address - * @return string - */ - private function buildSetShippingMethodMutation(string $cartId, array $method, array $address): string - { - return <<<QUERY -mutation { - setShippingMethodsOnCart(input: { - cart_id: "{$cartId}", - shipping_methods: [ - { - cart_address_id: {$address['address_id']} - carrier_code: "{$method['carrier_code']}" - method_code: "{$method['method_code']}" - } - ] - }) { - cart { - prices { - grand_total { - value, - currency - } - } - shipping_addresses { - selected_shipping_method { - carrier_code - method_code - } - } - } - } -} -QUERY; - - } - - /** - * Build setBillingAddressOnCart mutation - * - * @param string $cartId - * @param bool $save - * @return string - */ - private function buildSetNewBillingAddressMutation(string $cartId, bool $save = false): string - { - $save = json_encode($save); - return <<<QUERY -mutation { - setBillingAddressOnCart( - input: { - cart_id: "{$cartId}" - billing_address: { - address: { - firstname: "test firstname" - lastname: "test lastname" - street: ["test street 1", "test street 2"] - city: "test city" - region: "TX" - postcode: "887766" - country_code: "US" - telephone: "88776655" - save_in_address_book: {$save} - } - } - } - ) { - cart { - available_payment_methods { - code - title - } - billing_address { - firstname - lastname - company - street - city - postcode - telephone - country { - code - label - } - address_type - } - } - } -} -QUERY; - } - - /** - * Build setPaymentMethodOnCart mutation - * - * @param string $cartId - * @param array $payment - * @return string - */ - private function buildSetPaymentMethodMutation(string $cartId, array $payment): string - { - return <<<QUERY -mutation { - setPaymentMethodOnCart( - input: { - cart_id: "{$cartId}" - payment_method: { - code: "{$payment['code']}" - } - } - ) { - cart { - items { - qty - product { - sku - } - } - shipping_addresses { - selected_shipping_method { - carrier_code - method_code - } - } - selected_payment_method { - code - } - prices { - grand_total { - value - currency - } - } - } - } -} -QUERY; - } - - /** - * Build setGuestEmailOnCart mutation - * - * @param string $cartId - * @param string $email - * @return string - */ - private function buildSetGuestEmailOnCartMutation(string $cartId, string $email): string - { - return <<<QUERY -mutation { - setGuestEmailOnCart( - input: { - cart_id: "{$cartId}" - email: "{$email}" - } - ) { - cart { - email - } - } -} -QUERY; - } - - /** - * Build placeOrder mutation - * - * @param string $cartId - * @return string - */ - private function buildPlaceOrderMutation(string $cartId): string - { - return <<<QUERY -mutation { - placeOrder( - input: { - cart_id: "{$cartId}" - } - ) { - order { - order_id - } - } -} -QUERY; - } -} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php index b7d3b546ba194..47d0d661fb33c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php @@ -7,7 +7,6 @@ namespace Magento\GraphQl\Quote\Customer; -use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Registry; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\Integration\Api\CustomerTokenServiceInterface; diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php new file mode 100644 index 0000000000000..f5114b9253a40 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -0,0 +1,441 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\Framework\Registry; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\ResourceModel\Order\CollectionFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * End to checkout tests for guest + */ +class CheckoutEndToEndTest extends GraphQlAbstract +{ + /** + * @var Registry + */ + private $registry; + + /** + * @var QuoteCollectionFactory + */ + private $quoteCollectionFactory; + + /** + * @var QuoteResource + */ + private $quoteResource; + + /** + * @var QuoteIdMaskFactory + */ + private $quoteIdMaskFactory; + + /** + * @var CollectionFactory + */ + private $orderCollectionFactory; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + protected function setUp() + { + parent::setUp(); + + $objectManager = Bootstrap::getObjectManager(); + $this->registry = $objectManager->get(Registry::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); + $this->quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); + $this->orderCollectionFactory = $objectManager->get(CollectionFactory::class); + $this->orderRepository = $objectManager->get(OrderRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutWorkflow() + { + $qty = 2; + + $sku = $this->findProduct(); + $cartId = $this->createEmptyCart(); + $this->setGuestEmailOnCart($cartId); + $this->addProductToCart($cartId, $qty, $sku); + + $this->setBillingAddress($cartId); + $shippingAddress = $this->setShippingAddress($cartId); + + $shippingMethod = current($shippingAddress['available_shipping_methods']); + $paymentMethod = $this->setShippingMethod($cartId, $shippingAddress['address_id'], $shippingMethod); + $this->setPaymentMethod($cartId, $paymentMethod); + + $this->placeOrder($cartId); + } + + /** + * @return string + */ + private function findProduct(): string + { + $query = <<<QUERY +{ + products ( + filter: { + sku: { + like:"simple%" + } + } + pageSize: 1 + currentPage: 1 + ) { + items { + sku + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('products', $response); + self::assertArrayHasKey('items', $response['products']); + self::assertCount(1, $response['products']['items']); + + $product = current($response['products']['items']); + self::assertArrayHasKey('sku', $product); + self::assertNotEmpty($product['sku']); + + return $product['sku']; + } + + /** + * @return string + */ + private function createEmptyCart(): string + { + $query = <<<QUERY +mutation { + createEmptyCart +} +QUERY; + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); + + return $response['createEmptyCart']; + } + + /** + * @param string $cartId + * @return void + */ + private function setGuestEmailOnCart(string $cartId): void + { + $query = <<<QUERY +mutation { + setGuestEmailOnCart( + input: { + cart_id: "{$cartId}" + email: "customer@example.com" + } + ) { + cart { + email + } + } +} +QUERY; + $this->graphQlMutation($query); + } + + /** + * @param string $cartId + * @param float $qty + * @param string $sku + * @return void + */ + private function addProductToCart(string $cartId, float $qty, string $sku): void + { + $query = <<<QUERY +mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$cartId}" + cartItems: [ + { + data: { + qty: {$qty} + sku: "{$sku}" + } + } + ] + } + ) { + cart { + items { + qty + product { + sku + } + } + } + } +} +QUERY; + $this->graphQlMutation($query); + } + + /** + * @param string $cartId + * @param array $auth + * @return array + */ + private function setBillingAddress(string $cartId): void + { + $query = <<<QUERY +mutation { + setBillingAddressOnCart( + input: { + cart_id: "{$cartId}" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + postcode: "887766" + telephone: "88776655" + region: "TX" + country_code: "US" + save_in_address_book: false + } + } + } + ) { + cart { + billing_address { + address_type + } + } + } +} +QUERY; + $this->graphQlMutation($query); + } + + /** + * @param string $cartId + * @return array + */ + private function setShippingAddress(string $cartId): array + { + $query = <<<QUERY +mutation { + setShippingAddressesOnCart( + input: { + cart_id: "$cartId" + shipping_addresses: [ + { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + region: "TX" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: false + } + } + ] + } + ) { + cart { + shipping_addresses { + address_id + available_shipping_methods { + carrier_code + method_code + amount + } + } + } + } +} +QUERY; + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('setShippingAddressesOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingAddressesOnCart']['cart']); + self::assertCount(1, $response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('address_id', $shippingAddress); + self::assertNotEmpty($shippingAddress['address_id']); + self::assertArrayHasKey('available_shipping_methods', $shippingAddress); + self::assertCount(1, $shippingAddress['available_shipping_methods']); + + $availableShippingMethod = current($shippingAddress['available_shipping_methods']); + self::assertArrayHasKey('carrier_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['carrier_code']); + + self::assertArrayHasKey('method_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['method_code']); + + self::assertArrayHasKey('amount', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['amount']); + + return $shippingAddress; + } + + /** + * @param string $cartId + * @param int $addressId + * @param array $method + * @return array + */ + private function setShippingMethod(string $cartId, int $addressId, array $method): array + { + $query = <<<QUERY +mutation { + setShippingMethodsOnCart(input: { + cart_id: "{$cartId}", + shipping_methods: [ + { + cart_address_id: {$addressId} + carrier_code: "{$method['carrier_code']}" + method_code: "{$method['method_code']}" + } + ] + }) { + cart { + available_payment_methods { + code + title + } + } + } +} +QUERY; + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('available_payment_methods', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + + $availablePaymentMethod = current($response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + self::assertArrayHasKey('code', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['code']); + self::assertArrayHasKey('title', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['title']); + + return $availablePaymentMethod; + } + + /** + * @param string $cartId + * @param array $method + * @return void + */ + private function setPaymentMethod(string $cartId, array $method): void + { + $query = <<<QUERY +mutation { + setPaymentMethodOnCart( + input: { + cart_id: "{$cartId}" + payment_method: { + code: "{$method['code']}" + } + } + ) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + $this->graphQlMutation($query); + } + + /** + * @param string $cartId + * @return void + */ + private function placeOrder(string $cartId): void + { + $query = <<<QUERY +mutation { + placeOrder( + input: { + cart_id: "{$cartId}" + } + ) { + order { + order_id + } + } +} +QUERY; + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('placeOrder', $response); + self::assertArrayHasKey('order', $response['placeOrder']); + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertNotEmpty($response['placeOrder']['order']['order_id']); + } + + public function tearDown() + { + $this->deleteQuote(); + $this->deleteOrder(); + parent::tearDown(); + } + + /** + * @return void + */ + private function deleteQuote(): void + { + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { + $this->quoteResource->delete($quote); + + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quote->getId()) + ->delete(); + } + } + + /** + * @return void + */ + private function deleteOrder() + { + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + + $orderCollection = $this->orderCollectionFactory->create(); + foreach ($orderCollection as $order) { + $this->orderRepository->delete($order); + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php index adb2879e186b1..ddce2cfbffbcb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php @@ -7,9 +7,8 @@ namespace Magento\GraphQl\Quote\Guest; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -26,37 +25,26 @@ class CreateEmptyCartTest extends GraphQlAbstract private $guestCartRepository; /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory + * @var QuoteCollectionFactory */ - private $quoteFactory; + private $quoteCollectionFactory; /** - * @var MaskedQuoteIdToQuoteIdInterface + * @var QuoteResource */ - private $maskedQuoteIdToQuoteId; + private $quoteResource; /** * @var QuoteIdMaskFactory */ private $quoteIdMaskFactory; - /** - * @var string - */ - private $maskedQuoteId; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); } @@ -69,7 +57,6 @@ public function testCreateEmptyCart() self::assertNotEmpty($response['createEmptyCart']); $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertNull($guestCart->getCustomer()->getId()); @@ -110,15 +97,12 @@ private function getQuery(): string public function tearDown() { - if (null !== $this->maskedQuoteId) { - $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); - - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $quoteId); + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { $this->quoteResource->delete($quote); $quoteIdMask = $this->quoteIdMaskFactory->create(); - $quoteIdMask->setQuoteId($quoteId) + $quoteIdMask->setQuoteId($quote->getId()) ->delete(); } parent::tearDown(); From 26a3573d8993499f0b8ba31936f9d26b1e33b654 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Fri, 19 Apr 2019 13:12:43 -0500 Subject: [PATCH 422/585] GraphQL-595,600,598:code refactored for the integretaion tests --- .../Controller/Catalog/CategoriesWithProductsCacheTest.php | 1 + .../GraphQlCache/Controller/Catalog/ProductsCacheTest.php | 1 + .../Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php | 1 + 3 files changed, 3 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php index bcd3b7fecad58..621030650ac6c 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php @@ -18,6 +18,7 @@ * * @magentoAppArea graphql * @magentoCache full_page enabled + * @magentoDbIsolation disabled */ class CategoriesWithProductsCacheTest extends AbstractGraphqlCacheTest { diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php index 4cfd74ee49b81..7fd7002142de2 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php @@ -17,6 +17,7 @@ * * @magentoAppArea graphql * @magentoCache full_page enabled + * @magentoDbIsolation disabled */ class ProductsCacheTest extends AbstractGraphqlCacheTest { diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index bc436b8f35782..8fa84505f1476 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -17,6 +17,7 @@ * * @magentoAppArea graphql * @magentoCache full_page enabled + * @magentoDbIsolation disabled */ class CmsPageCacheTest extends AbstractGraphqlCacheTest { From b82d771f40a9cfa660e8c9f577e28408168edfc2 Mon Sep 17 00:00:00 2001 From: anzin <andrii.zinkevych@smile-ukraine.com> Date: Sat, 13 Apr 2019 17:56:48 +0300 Subject: [PATCH 423/585] magento/graphql-ce#607: Expanded "createdEmptyCart" mutation with not required parameter "cart_id" --- app/code/Magento/Quote/etc/frontend/di.xml | 2 +- .../Model/Resolver/CreateEmptyCart.php | 35 ++++++++++++++++--- .../Plugin/MaskAlreadySetException.php | 33 +++++++++++++++++ .../Magento/QuoteGraphQl/etc/graphql/di.xml | 3 ++ .../Magento/QuoteGraphQl/etc/schema.graphqls | 6 +++- 5 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php diff --git a/app/code/Magento/Quote/etc/frontend/di.xml b/app/code/Magento/Quote/etc/frontend/di.xml index ecad94fbbc249..cb19d73797c4b 100644 --- a/app/code/Magento/Quote/etc/frontend/di.xml +++ b/app/code/Magento/Quote/etc/frontend/di.xml @@ -19,6 +19,6 @@ <plugin name="update_quote_store_after_switch_store_view" type="Magento\Quote\Plugin\UpdateQuoteStore"/> </type> <type name="Magento\Customer\Model\ResourceModel\Customer"> - <plugin name="cart_recollect_on_group_change" type="Magento\Quote\Plugin\RecollectOnGroupChange"/> + <plugin name="cart_recollect_on_group_change" type="Magento\Quote\Plugin\MaskAlreadySetException"/> </type> </config> diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php index 06123abe615e6..b67db1fa0dc2b 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php @@ -8,6 +8,8 @@ namespace Magento\QuoteGraphQl\Model\Resolver; use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\CartManagementInterface; @@ -64,18 +66,43 @@ public function __construct( public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { $customerId = $context->getUserId(); + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $maskedQuoteId = null; + + if (isset($args['input']['cart_id'])) { + $maskedQuoteId = $args['input']['cart_id']; + + if ($quoteIdMask->load($maskedQuoteId, 'masked_id') && $quoteIdMask->getQuoteId()) { + throw new GraphQlAlreadyExistsException(__('Specified "cart_id" already exists')); + } + + if (strlen($maskedQuoteId) > 32) { + throw new GraphQlInputException(__('Specified "cart_id" max size is 32')); + } + } if (0 !== $customerId && null !== $customerId) { $quoteId = $this->cartManagement->createEmptyCartForCustomer($customerId); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quoteId); + $existsMaskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quoteId); + + if (empty($existsMaskedQuoteId)) { + if (null !== $maskedQuoteId) { + $quoteIdMask->setMaskedId($maskedQuoteId); + } - if (empty($maskedQuoteId)) { - $quoteIdMask = $this->quoteIdMaskFactory->create(); $quoteIdMask->setQuoteId($quoteId)->save(); $maskedQuoteId = $quoteIdMask->getMaskedId(); } } else { - $maskedQuoteId = $this->guestCartManagement->createEmptyCart(); + if (null !== $maskedQuoteId) { + $cartId = $this->cartManagement->createEmptyCart(); + $quoteIdMask + ->setQuoteId($cartId) + ->setMaskedId($maskedQuoteId) + ->save(); + } else { + $maskedQuoteId = $this->guestCartManagement->createEmptyCart(); + } } return $maskedQuoteId; diff --git a/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php b/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php new file mode 100644 index 0000000000000..2ed364f6f4beb --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Plugin; + +use Magento\Quote\Model\QuoteIdMask; + +/** + * Don't proceed beforeSave method if masked id already set. + */ +class MaskAlreadySetException +{ + /** + * @param \Magento\Quote\Model\QuoteIdMask $subject + * @param \Closure $proceed + * + * @return \Magento\Quote\Model\QuoteIdMask + */ + public function aroundBeforeSave(QuoteIdMask $subject, \Closure $proceed) + { + $maskedId = $subject->getMaskedId(); + + if (!$maskedId) { + $proceed(); + } + + return $subject; + } +} diff --git a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml index c7389cf667845..7aa6ce77bfbdf 100644 --- a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml @@ -10,4 +10,7 @@ type="Magento\QuoteGraphQl\Model\Cart\SetShippingAddressesOnCart"/> <preference for="Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCartInterface" type="Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCart"/> + <type name="Magento\Quote\Model\QuoteIdMask"> + <plugin name="mask_already_set_exception" type="Magento\QuoteGraphQl\Plugin\MaskAlreadySetException"/> + </type> </config> diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 711e6cbc7f5f6..a9784e97c8952 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -6,7 +6,7 @@ type Query { } type Mutation { - createEmptyCart: String @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CreateEmptyCart") @doc(description:"Creates an empty shopping cart for a guest or logged in user") + createEmptyCart(input: createEmptyCartInput): String @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CreateEmptyCart") @doc(description:"Creates an empty shopping cart for a guest or logged in user") addSimpleProductsToCart(input: AddSimpleProductsToCartInput): AddSimpleProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart") addVirtualProductsToCart(input: AddVirtualProductsToCartInput): AddVirtualProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart") applyCouponToCart(input: ApplyCouponToCartInput): ApplyCouponToCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ApplyCouponToCart") @@ -21,6 +21,10 @@ type Mutation { placeOrder(input: PlaceOrderInput): PlaceOrderOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\PlaceOrder") } +input createEmptyCartInput { + cart_id: String +} + input AddSimpleProductsToCartInput { cart_id: String! cartItems: [SimpleProductCartItemInput!]! From 38f473c565baab39e4b2c81ee79f5ab8b9224aca Mon Sep 17 00:00:00 2001 From: anzin <andrii.zinkevych@smile-ukraine.com> Date: Sat, 13 Apr 2019 18:10:17 +0300 Subject: [PATCH 424/585] magento/graphql-ce#607: Fixed own mistake --- app/code/Magento/Quote/etc/frontend/di.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Quote/etc/frontend/di.xml b/app/code/Magento/Quote/etc/frontend/di.xml index cb19d73797c4b..ecad94fbbc249 100644 --- a/app/code/Magento/Quote/etc/frontend/di.xml +++ b/app/code/Magento/Quote/etc/frontend/di.xml @@ -19,6 +19,6 @@ <plugin name="update_quote_store_after_switch_store_view" type="Magento\Quote\Plugin\UpdateQuoteStore"/> </type> <type name="Magento\Customer\Model\ResourceModel\Customer"> - <plugin name="cart_recollect_on_group_change" type="Magento\Quote\Plugin\MaskAlreadySetException"/> + <plugin name="cart_recollect_on_group_change" type="Magento\Quote\Plugin\RecollectOnGroupChange"/> </type> </config> From 9009ccc8c3011324dccc9d168b30e3bfd11cd948 Mon Sep 17 00:00:00 2001 From: Harniuk Bohdan <bohar@smile.fr> Date: Tue, 16 Apr 2019 13:42:16 +0300 Subject: [PATCH 425/585] GraphQl-607: Expand createEmptyCart mutation --- .../Model/Resolver/CreateEmptyCart.php | 6 +- .../Quote/Customer/CreateEmptyCartTest.php | 105 ++++++++++++++++++ 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php index b67db1fa0dc2b..ba5e1dea42727 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php @@ -73,11 +73,11 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $maskedQuoteId = $args['input']['cart_id']; if ($quoteIdMask->load($maskedQuoteId, 'masked_id') && $quoteIdMask->getQuoteId()) { - throw new GraphQlAlreadyExistsException(__('Specified "cart_id" already exists')); + throw new GraphQlAlreadyExistsException(__('Specified parameter "cart_id" is non unique.')); } - if (strlen($maskedQuoteId) > 32) { - throw new GraphQlInputException(__('Specified "cart_id" max size is 32')); + if (mb_strlen($maskedQuoteId) > 32) { + throw new GraphQlInputException(__('"cart_id" length have to be less than or equal to 32.')); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php index fc66e4647e576..575edbd1885f1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php @@ -15,6 +15,10 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; use Magento\Quote\Api\GuestCartRepositoryInterface; +use Magento\Framework\Math\Random as RandomDataGenerator; +use Magento\Framework\Exception\AuthenticationException; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Exception\LocalizedException; /** * Test for empty cart creation mutation for customer @@ -56,6 +60,11 @@ class CreateEmptyCartTest extends GraphQlAbstract */ private $maskedQuoteId; + /** + * @var RandomDataGenerator + */ + private $randomDataGenerator; + protected function setUp() { $objectManager = Bootstrap::getObjectManager(); @@ -65,10 +74,14 @@ protected function setUp() $this->quoteFactory = $objectManager->get(QuoteFactory::class); $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); + $this->randomDataGenerator = $objectManager->get(RandomDataGenerator::class); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php + * + * @throws AuthenticationException + * @throws NoSuchEntityException */ public function testCreateEmptyCart() { @@ -86,6 +99,29 @@ public function testCreateEmptyCart() self::assertEquals('default', $guestCart->getStore()->getCode()); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * + * @throws LocalizedException + * @throws NoSuchEntityException + */ + public function testCreateEmptyCartWithCartId() + { + $uniqueHash = $this->randomDataGenerator->getUniqueHash(); + + $query = $this->getQueryWithCartId('cart_id : "' . $uniqueHash . '"'); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); + + self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); + + $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); + $this->maskedQuoteId = $response['createEmptyCart']; + + self::assertNotNull($guestCart->getId()); + self::assertEquals(1, $guestCart->getCustomer()->getId()); + } + /** * @magentoApiDataFixture Magento/Store/_files/second_store.php * @magentoApiDataFixture Magento/Customer/_files/customer.php @@ -110,6 +146,24 @@ public function testCreateEmptyCartWithNotDefaultStore() self::assertEquals('fixture_second_store', $guestCart->getStore()->getCode()); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @dataProvider dataProviderValidateCreateEmptyCartWithSpecifiedCartId + * @param string $input + * @param string $message + * @throws \Exception + */ + public function testValidateCreateEmptyCartWithSpecifiedCartId(string $input, string $message) + { + $input = str_replace('provide_non_unique_id', $this->addEmptyCartWithCartId(), $input); + $input = str_replace('provide_hash_with_prefix', $this->randomDataGenerator->getUniqueHash('prefix'), $input); + + $query = $this->getQueryWithCartId($input); + + $this->expectExceptionMessage($message); + $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); + } + /** * @return string */ @@ -122,10 +176,28 @@ private function getQuery(): string QUERY; } + /** + * @param string $input + * @return string + */ + private function getQueryWithCartId(string $input): string + { + return <<<QUERY +mutation { + createEmptyCart( + input : { + {$input} + } + ) +} +QUERY; + } + /** * @param string $username * @param string $password * @return array + * @throws AuthenticationException */ private function getHeaderMapWithCustomerToken( string $username = 'customer@example.com', @@ -151,4 +223,37 @@ public function tearDown() } parent::tearDown(); } + + /** + * Return masked id for created empty cart. + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @return mixed + * @throws LocalizedException + */ + private function addEmptyCartWithCartId() + { + $uniqueHash = $this->randomDataGenerator->getUniqueHash(); + $query = $this->getQueryWithCartId('cart_id : "' . $uniqueHash . '"'); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); + + return $response['createEmptyCart']; + } + + /** + * @return array + */ + public function dataProviderValidateCreateEmptyCartWithSpecifiedCartId(): array + { + return [ + 'cart_id_unique_checking' => [ + 'cart_id: "provide_non_unique_id"', + 'Specified parameter "cart_id" is non unique.' + ], + 'cart_id_length_checking' => [ + 'cart_id: "provide_hash_with_prefix"', + '"cart_id" length have to be less than or equal to 32.' + ], + ]; + } } From e80423cd565a3f1194261059a4620bfa18450019 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 19 Apr 2019 14:27:35 -0500 Subject: [PATCH 426/585] Minor fixes for magento/magento-functional-tests-migration#323: Convert AccessAdminWithStoreCodeInUrlTest to MFTF --- ...ml => AssertAdminDashboardPageIsVisibleActionGroup.xml} | 2 +- .../Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml | 3 ++- ...p.xml => AssertStorefrontStoreCodeInUrlActionGroup.xml} | 7 +++++-- .../Test/Mftf/Data/StoreConfigData.xml} | 0 .../Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml | 3 ++- .../ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml | 6 +++--- 6 files changed, 13 insertions(+), 8 deletions(-) rename app/code/Magento/Backend/Test/Mftf/ActionGroup/{AdminAssertDashboardPageIsVisibleActionGroup.xml => AssertAdminDashboardPageIsVisibleActionGroup.xml} (89%) rename app/code/Magento/Store/Test/Mftf/ActionGroup/{StorefrontAssertStoreCodeInUrlActionGroup.xml => AssertStorefrontStoreCodeInUrlActionGroup.xml} (53%) rename app/code/Magento/{Backend/Test/Mftf/Data/BackendConfigData.xml => Store/Test/Mftf/Data/StoreConfigData.xml} (100%) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminDashboardPageIsVisibleActionGroup.xml similarity index 89% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminDashboardPageIsVisibleActionGroup.xml index df22bb27d6b88..1c86a736ac2f1 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminDashboardPageIsVisibleActionGroup.xml @@ -8,7 +8,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminAssertDashboardPageIsVisibleActionGroup"> + <actionGroup name="AssertAdminDashboardPageIsVisibleActionGroup"> <seeInCurrentUrl url="{{AdminDashboardPage.url}}" stepKey="seeDashboardUrl"/> <see userInput="Dashboard" selector="{{AdminHeaderSection.pageTitle}}" stepKey="seeDashboardTitle"/> </actionGroup> diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml index 51ba1a142803d..5485dcaea33ee 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml @@ -13,6 +13,7 @@ <features value="Backend"/> <title value="Admin panel should be accessible with Add Store Code to URL setting enabled"/> <description value="Admin panel should be accessible with Add Store Code to URL setting enabled"/> + <testCaseId value="MC-14279" /> <group value="backend"/> <group value="mtf_migrated"/> </annotations> @@ -24,6 +25,6 @@ </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <actionGroup ref="AdminAssertDashboardPageIsVisibleActionGroup" stepKey="seeDashboardPage"/> + <actionGroup ref="AssertAdminDashboardPageIsVisibleActionGroup" stepKey="seeDashboardPage"/> </test> </tests> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreCodeInUrlActionGroup.xml similarity index 53% rename from app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml rename to app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreCodeInUrlActionGroup.xml index 974526afbf21c..3daa1c25a1737 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreCodeInUrlActionGroup.xml @@ -7,7 +7,10 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="StorefrontAssertStoreCodeInUrlActionGroup"> - <seeInCurrentUrl url="{{StorefrontHomePage.url}}{{_defaultStore.code}}" stepKey="seeStoreCodeInURL"/> + <actionGroup name="AssertStorefrontStoreCodeInUrlActionGroup"> + <arguments> + <argument name="storeCode" type="string" defaultValue="{{_defaultStore.code}}" /> + </arguments> + <seeInCurrentUrl url="{{StorefrontHomePage.url}}{{storeCode}}" stepKey="seeStoreCodeInURL"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml b/app/code/Magento/Store/Test/Mftf/Data/StoreConfigData.xml similarity index 100% rename from app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml rename to app/code/Magento/Store/Test/Mftf/Data/StoreConfigData.xml diff --git a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml index 7bee46da1a226..95f5a9cd2d669 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml @@ -13,6 +13,7 @@ <features value="Backend"/> <title value="Store code should be added to storefront URL if the corresponding configuration is enabled"/> <description value="Store code should be added to storefront URL if the corresponding configuration is enabled"/> + <testCaseId value="MC-15944" /> <group value="store"/> <group value="mtf_migrated"/> </annotations> @@ -24,6 +25,6 @@ </after> <actionGroup ref="StorefrontClickOnHeaderLogoActionGroup" stepKey="clickOnStorefrontHeaderLogo"/> - <actionGroup ref="StorefrontAssertStoreCodeInUrlActionGroup" stepKey="seeStoreCodeInUrl"/> + <actionGroup ref="AssertStorefrontStoreCodeInUrlActionGroup" stepKey="seeStoreCodeInUrl"/> </test> </tests> diff --git a/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml b/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml index 6e45429b9e1e8..cd4117a4cfa6e 100644 --- a/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml +++ b/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml @@ -8,9 +8,9 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontClickOnHeaderLogoActionGroup"> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="gotToHomePage"/> - <waitForPageLoad stepKey="waitForHomePageLoaded1"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePage"/> + <waitForPageLoad stepKey="waitForHomePageLoaded"/> <click selector="{{StorefrontHeaderSection.logoLink}}" stepKey="clickOnLogo"/> - <waitForPageLoad stepKey="waitForHomePageLoaded2"/> + <waitForPageLoad stepKey="waitForHomePageLoadedAfterClickOnLogo"/> </actionGroup> </actionGroups> From 81acb65a8f701533f7c44ed05e2281885a5f1e6c Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 19 Apr 2019 14:36:56 -0500 Subject: [PATCH 427/585] GraphQL-577: Test coverage for tag cache generation - Refactor graphql test framework for caching --- .../TestFramework/TestCase/GraphQl/Client.php | 39 +++++- .../TestCase/GraphQlAbstract.php | 8 +- .../TestCase/HttpClient/CurlClient.php | 9 +- .../GraphQl/PageCache/CacheTagTest.php | 122 ++++++++++-------- .../GraphQl/PageCache/Cms/BlockCacheTest.php | 58 ++++----- .../Controller/AbstractGraphqlCacheTest.php | 2 +- .../Controller/Cms/BlockCacheTest.php | 1 + 7 files changed, 137 insertions(+), 102 deletions(-) diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php index d5a33cfe281fc..cdc9d5e8a4c9c 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php @@ -122,29 +122,33 @@ private function processResponse(string $response) } /** - * Process the header information from response + * Perform HTTP GET request, return response data and headers * * @param string $query * @param array $variables * @param string $operationName * @param array $headers - * @return mixed + * @return array */ - public function getQueryResponseHeaders( + public function getWithResponseHeaders( string $query, array $variables = [], string $operationName = '', array $headers = [] - ) { + ): array { $url = $this->getEndpointUrl(); $requestArray = [ 'query' => $query, 'variables' => $variables ? $this->json->jsonEncode($variables) : null, 'operationName' => !empty($operationName) ? $operationName : null ]; + array_filter($requestArray); + + $response = $this->curlClient->getWithFullResponse($url, $requestArray, $headers); + $responseBody = $this->processResponse($response['body']); + $responseHeaders = !empty($response['header']) ? $this->processResponseHeaders($response['header']) : []; - $responseHeader = $this->curlClient->getHttpHeaders($url, $requestArray, $headers); - return $responseHeader; + return ['headers' => $responseHeaders, 'body' => $responseBody]; } /** @@ -191,4 +195,27 @@ public function getEndpointUrl() { return rtrim(TESTS_BASE_URL, '/') . '/graphql'; } + + /** + * Parse response headers into associative array + * + * @param string $headers + * @return array + */ + private function processResponseHeaders(string $headers): array + { + $headersArray = []; + + $headerLines = preg_split('/((\r?\n)|(\r\n?))/', $headers); + foreach ($headerLines as $headerLine) { + $headerParts = preg_split('/:/', $headerLine); + if (count($headerParts) == 2) { + $headersArray[trim($headerParts[0])] = trim($headerParts[1]); + } elseif (preg_match('/HTTP\/[\.0-9]+/', $headerLine)) { + $headersArray[trim('Status-Line')] = trim($headerLine); + } + } + + return $headersArray; + } } diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php index f8aa950619264..94eb5ddec8604 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php @@ -84,15 +84,15 @@ public function graphQlMutation( * @param array $variables * @param string $operationName * @param array $headers - * @return mixed + * @return array */ - public function graphQlQueryForHttpHeaders( + public function graphQlQueryWithResponseHeaders( string $query, array $variables = [], string $operationName = '', array $headers = [] - ) { - return $this->getGraphQlClient()->getQueryResponseHeaders( + ): array { + return $this->getGraphQlClient()->getWithResponseHeaders( $query, $variables, $operationName, diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php index 0a24e64297e10..67691a3c909be 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/HttpClient/CurlClient.php @@ -33,14 +33,14 @@ public function get($url, $data = [], $headers = []) } /** - * Perform a HTTP GET request and returns just the response headers + * Perform a HTTP GET request and return the full response * * @param string $url * @param array $data * @param array $headers - * @return mixed + * @return array */ - public function getHttpHeaders($url, $data = [], $headers = []) + public function getWithFullResponse($url, $data = [], $headers = []): array { if (!empty($data)) { $url .= '?' . http_build_query($data); @@ -48,8 +48,7 @@ public function getHttpHeaders($url, $data = [], $headers = []) $curlOpts = []; $curlOpts[CURLOPT_CUSTOMREQUEST] = \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET; - $resp = $this->invokeApi($url, $curlOpts, $headers); - return $resp["header"]; + return $this->invokeApi($url, $curlOpts, $headers); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index 824f29cf0b1e8..e9ff8d93177ce 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -28,7 +28,7 @@ protected function setUp() } /** - * Tests if Magento cache tags and debug headers for products are generated properly + * Test if Magento cache tags and debug headers for products are generated properly * * @magentoApiDataFixture Magento/Catalog/_files/multiple_products.php */ @@ -49,35 +49,38 @@ public function testCacheTagsAndCacheDebugHeaderForProducts() } QUERY; - /** cache-debug should be a MISS when product is queried for first time */ - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); + // Cache-debug should be a MISS when product is queried for first time + $responseMiss = $this->graphQlQueryWithResponseHeaders($query); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseMiss['headers']); + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); - /** cache-debug should be a HIT for the second round */ - $responseHitHeaders = $this->graphQlQueryForHttpHeaders($query); - //preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseHitHeaders, $matchesHit); - $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHitHeaders); + // Cache-debug should be a HIT for the second round + $responseHit = $this->graphQlQueryWithResponseHeaders($query); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseHit['headers']); + $this->assertEquals('HIT', $responseHit['headers']['X-Magento-Cache-Debug']); /** @var ProductRepositoryInterface $productRepository */ $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); /** @var Product $product */ - $product =$productRepository->get($productSku, false, null, true); - /** update the price attribute for the product in test */ + $product = $productRepository->get($productSku, false, null, true); $product->setPrice(15); - $product->save(); - /** Cache invalidation happens and cache-debug header value is a MISS after product update */ - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); - - /** checks if cache tags for products are correctly displayed in the response header */ - preg_match('/X-Magento-Tags: (.*?)\n/', $responseMissHeaders, $headerCacheTags); - $actualCacheTags = explode(',', rtrim($headerCacheTags[1], "\r")); - $expectedCacheTags=['cat_p','cat_p_' . $product->getId(),'FPC']; - $this->assertEquals($expectedCacheTags, $actualCacheTags); + $productRepository->save($product); + // Cache invalidation happens and cache-debug header value is a MISS after product update + $responseMiss = $this->graphQlQueryWithResponseHeaders($query); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseMiss['headers']); + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); + $this->assertArrayHasKey('X-Magento-Tags', $responseMiss['headers']); + $expectedCacheTags = ['cat_p','cat_p_' . $product->getId(),'FPC']; + $actualCacheTags = explode(',', $responseMiss['headers']['X-Magento-Tags']); + foreach ($expectedCacheTags as $expectedCacheTag) { + $this->assertContains($expectedCacheTag, $actualCacheTags); + } } /** - * Tests if X-Magento-Tags for categories are generated properly. Also tests the use case for cache invalidation + * Test if X-Magento-Tags for categories are generated properly + * + * Also tests the use case for cache invalidation * * @magentoApiDataFixture Magento/Catalog/_files/product_in_multiple_categories.php */ @@ -86,7 +89,15 @@ public function testCacheTagForCategoriesWithProduct() $firstProductSku = 'simple333'; $secondProductSku = 'simple444'; $categoryId ='4'; - $variables =[ + + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + /** @var Product $firstProduct */ + $firstProduct = $productRepository->get($firstProductSku, false, null, true); + /** @var Product $secondProduct */ + $secondProduct = $productRepository->get($secondProductSku, false, null, true); + + $categoryQueryVariables =[ 'id' => $categoryId, 'pageSize'=> 10, 'currentPage' => 1 @@ -95,49 +106,46 @@ public function testCacheTagForCategoriesWithProduct() $product1Query = $this->getProductQuery($firstProductSku); $product2Query =$this->getProductQuery($secondProductSku); $categoryQuery = $this->getCategoryQuery(); - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($categoryQuery, $variables); - - /** cache-debug header value should be a MISS when category is loaded first time */ - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); - - /** @var ProductRepositoryInterface $productRepository */ - $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); - /** @var Product $firstProduct */ - $firstProduct = $productRepository->get($firstProductSku, false, null, true); - /** @var Product $secondProduct */ - $secondProduct = $productRepository->get($secondProductSku, false, null, true); - /** checks to see if the X-Magento-Tags for category is displayed correctly */ - preg_match('/X-Magento-Tags: (.*?)\n/', $responseMissHeaders, $headerCacheTags); - $actualCacheTags = explode(',', rtrim($headerCacheTags[1], "\r")); + // cache-debug header value should be a MISS when category is loaded first time + $responseMiss = $this->graphQlQueryWithResponseHeaders($categoryQuery, $categoryQueryVariables); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseMiss['headers']); + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); + $this->assertArrayHasKey('X-Magento-Tags', $responseMiss['headers']); + $actualCacheTags = explode(',', $responseMiss['headers']['X-Magento-Tags']); $expectedCacheTags = - ['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $firstProduct->getId(), - 'cat_p_' .$secondProduct->getId(),'FPC' - ]; + [ + 'cat_c', + 'cat_c_' . $categoryId, + 'cat_p', + 'cat_p_' . $firstProduct->getId(), + 'cat_p_' . $secondProduct->getId(), + 'FPC' + ]; $this->assertEquals($expectedCacheTags, $actualCacheTags); // Cache-debug header should be a MISS for product 1 on first request - $responseHeadersFirstProduct = $this->graphQlQueryForHttpHeaders($product1Query); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHeadersFirstProduct); - + $responseFirstProduct = $this->graphQlQueryWithResponseHeaders($product1Query); + $this->assertEquals('MISS', $responseFirstProduct['headers']['X-Magento-Cache-Debug']); // Cache-debug header should be a MISS for product 2 during first load - $responseHeadersSecondProduct = $this->graphQlQueryForHttpHeaders($product2Query); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHeadersSecondProduct); + $responseSecondProduct = $this->graphQlQueryWithResponseHeaders($product2Query); + $this->assertEquals('MISS', $responseSecondProduct['headers']['X-Magento-Cache-Debug']); - /** Cache-debug header value should be MISS after updating product1 and reloading the Category */ $firstProduct->setPrice(20); - $firstProduct->save(); - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($categoryQuery, $variables); - preg_match('/X-Magento-Cache-Debug: (.*?)\n/', $responseMissHeaders, $matchesMiss); - $this->assertEquals('MISS', rtrim($matchesMiss[1], "\r")); - - /** Cache-debug should be a MISS for product 1 after it is updated - cache invalidation */ - $responseHeadersFirstProduct = $this->graphQlQueryForHttpHeaders($product1Query); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHeadersFirstProduct); - - // Cach-debug header should be a HIT for prod 2 during second load since prod 2 is fetched from cache. - $responseHeadersSecondProduct = $this->graphQlQueryForHttpHeaders($product2Query); - $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHeadersSecondProduct); + $productRepository->save($firstProduct); + // cache-debug header value should be MISS after updating product1 and reloading the Category + $responseMissCategory = $this->graphQlQueryWithResponseHeaders($categoryQuery, $categoryQueryVariables); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseMissCategory['headers']); + $this->assertEquals('MISS', $responseMissCategory['headers']['X-Magento-Cache-Debug']); + + // cache-debug should be a MISS for product 1 after it is updated - cache invalidation + $responseMissFirstProduct = $this->graphQlQueryWithResponseHeaders($product1Query); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseMissFirstProduct['headers']); + $this->assertEquals('MISS', $responseMissFirstProduct['headers']['X-Magento-Cache-Debug']); + // Cache-debug header should be a HIT for product 2 + $responseHitSecondProduct = $this->graphQlQueryWithResponseHeaders($product2Query); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseHitSecondProduct['headers']); + $this->assertEquals('HIT', $responseHitSecondProduct['headers']['X-Magento-Cache-Debug']); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php index aed568b0d5d7c..3e8c3e0c9b47e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php @@ -41,11 +41,11 @@ public function testCacheTagsHaveExpectedValue() $query = $this->getBlockQuery([$blockIdentifier]); //cache-debug should be a MISS on first request - $responseHeaders = $this->graphQlQueryForHttpHeaders($query); - preg_match('/X-Magento-Tags: (.*)/', $responseHeaders, $matches); - $this->assertNotEmpty($matches[1]); - $actualTags = explode(',', $matches[1]); - $expectedTags = ["cms_b_{$blockIdentifier}", "cms_b_{$blockId}"]; + $response = $this->graphQlQueryWithResponseHeaders($query); + + $this->assertArrayHasKey('X-Magento-Tags', $response['headers']); + $actualTags = explode(',', $response['headers']['X-Magento-Tags']); + $expectedTags = ["cms_b", "cms_b_{$blockIdentifier}", "cms_b_{$blockId}", "FPC"]; foreach ($expectedTags as $expectedTag) { $this->assertContains($expectedTag, $actualTags); } @@ -62,17 +62,18 @@ public function testCacheIsUsedOnSecondRequest() $query = $this->getBlockQuery([$blockIdentifier]); //cache-debug should be a MISS on first request - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($query); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); + $responseMiss = $this->graphQlQueryWithResponseHeaders($query); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseMiss['headers']); + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); //cache-debug should be a HIT on second request - $responseHitHeaders = $this->graphQlQueryForHttpHeaders($query); - $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHitHeaders); - + $responseHit = $this->graphQlQueryWithResponseHeaders($query); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseHit['headers']); + $this->assertEquals('HIT', $responseHit['headers']['X-Magento-Cache-Debug']); //cached data should be correct - $blockQueryData = $this->graphQlQuery($query); - $blocks = $blockQueryData['cmsBlocks']['items']; - $this->assertArrayNotHasKey('errors', $blockQueryData); + $this->assertNotEmpty($responseHit['body']); + $this->assertArrayNotHasKey('errors', $responseHit['body']); + $blocks = $responseHit['body']['cmsBlocks']['items']; $this->assertEquals($blockIdentifier, $blocks[0]['identifier']); $this->assertEquals('CMS Block Title', $blocks[0]['title']); } @@ -91,30 +92,29 @@ public function testCacheIsInvalidatedOnBlockUpdate() $enabledBlockQuery = $this->getBlockQuery([$enabledBlockIdentifier]); //cache-debug should be a MISS on first request - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($fixtureBlockQuery); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($enabledBlockQuery); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); + $fixtureBlockMiss = $this->graphQlQueryWithResponseHeaders($fixtureBlockQuery); + $this->assertEquals('MISS', $fixtureBlockMiss['headers']['X-Magento-Cache-Debug']); + $enabledBlockMiss = $this->graphQlQueryWithResponseHeaders($enabledBlockQuery); + $this->assertEquals('MISS', $enabledBlockMiss['headers']['X-Magento-Cache-Debug']); //cache-debug should be a HIT on second request - $responseHitHeaders = $this->graphQlQueryForHttpHeaders($fixtureBlockQuery); - $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHitHeaders); - $responseHitHeaders = $this->graphQlQueryForHttpHeaders($enabledBlockQuery); - $this->assertContains('X-Magento-Cache-Debug: HIT', $responseHitHeaders); + $fixtureBlockHit = $this->graphQlQueryWithResponseHeaders($fixtureBlockQuery); + $this->assertEquals('HIT', $fixtureBlockHit['headers']['X-Magento-Cache-Debug']); + $enabledBlockHit = $this->graphQlQueryWithResponseHeaders($enabledBlockQuery); + $this->assertEquals('HIT', $enabledBlockHit['headers']['X-Magento-Cache-Debug']); $newBlockContent = 'New block content!!!'; $this->updateBlockContent($fixtureBlockIdentifier, $newBlockContent); //cache-debug should be a MISS after update the block - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($fixtureBlockQuery); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); - $responseHitHeaders = $this->graphQlQueryForHttpHeaders($enabledBlockQuery); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseHitHeaders); - + $fixtureBlockMiss = $this->graphQlQueryWithResponseHeaders($fixtureBlockQuery); + $this->assertEquals('MISS', $fixtureBlockMiss['headers']['X-Magento-Cache-Debug']); + $enabledBlockHit = $this->graphQlQueryWithResponseHeaders($enabledBlockQuery); + $this->assertEquals('HIT', $enabledBlockHit['headers']['X-Magento-Cache-Debug']); //updated block data should be correct - $blockQueryData = $this->graphQlQuery($fixtureBlockQuery); - $blocks = $blockQueryData['cmsBlocks']['items']; - $this->assertArrayNotHasKey('errors', $blockQueryData); + $this->assertNotEmpty($fixtureBlockMiss['body']); + $blocks = $fixtureBlockMiss['body']['cmsBlocks']['items']; + $this->assertArrayNotHasKey('errors', $fixtureBlockMiss['body']); $this->assertEquals($fixtureBlockIdentifier, $blocks[0]['identifier']); $this->assertEquals('CMS Block Title', $blocks[0]['title']); $this->assertEquals($newBlockContent, $blocks[0]['content']); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php index d2e853c2aa0ea..4cc46a8e745e8 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php @@ -14,7 +14,7 @@ /** * Abstract test class for Graphql cache tests */ -class AbstractGraphqlCacheTest extends TestCase +abstract class AbstractGraphqlCacheTest extends TestCase { /** * @var ObjectManager diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php index 005007fce58fb..58e665c057f03 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php @@ -17,6 +17,7 @@ * * @magentoAppArea graphql * @magentoCache full_page enabled + * @magentoDbIsolation disabled */ class BlockCacheTest extends AbstractGraphqlCacheTest { From 980cba8bfef16c7c23241377ff3b92f5aeb283a4 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Fri, 19 Apr 2019 15:03:17 -0500 Subject: [PATCH 428/585] GraphQl:598 Cache Tag generation test changes added --- .../Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index 8fa84505f1476..bb358d32278cb 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -10,6 +10,7 @@ use Magento\Cms\Model\GetPageByIdentifier; use Magento\Framework\App\Request\Http; use Magento\GraphQl\Controller\GraphQl; +use Magento\Framework\App\ResponseInterface; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; /** @@ -18,6 +19,7 @@ * @magentoAppArea graphql * @magentoCache full_page enabled * @magentoDbIsolation disabled + * */ class CmsPageCacheTest extends AbstractGraphqlCacheTest { @@ -74,6 +76,7 @@ public function testToCheckCmsPageRequestCacheTags(): void $result = $this->graphqlController->dispatch($this->request); /** @var \Magento\Framework\App\Response\Http $response */ $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ $result->renderResult($response); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); From 66d1c70c06d9f93c9dfdc73f9d4a6cac28a6e4e2 Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Fri, 19 Apr 2019 15:16:40 -0500 Subject: [PATCH 429/585] 230: Implement cache tag generation for GraphQL queries - Fixed static tests --- .../Framework/GraphQl/_files/query_array_output.php | 9 +++++---- .../Catalog/CategoriesWithProductsCacheTest.php | 1 - .../Controller/Catalog/CategoryCacheTest.php | 1 - .../Controller/Catalog/ProductsCacheTest.php | 1 - 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php index f7c2597fe5710..adfe03cdd3212 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php @@ -31,11 +31,12 @@ ], 'required' => false, 'isList' => false, - 'resolver' => 'Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata', + 'resolver' => Magento\EavGraphQl\Model\Resolver\CustomAttributeMetadata::class, 'description' => 'Returns the attribute type, given an attribute code and entity type', 'cache' => [ 'cacheTag' => 'cat_test', - 'cacheIdentityResolver' => 'Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata' + 'cacheIdentityResolver' => + Magento\EavGraphQl\Model\Resolver\CustomAttributeMetadata::class ] ], 'products' => [ @@ -99,7 +100,7 @@ ], 'required' => false, 'isList' => false, - 'resolver' => 'Magento\\CatalogGraphQl\\Model\\Resolver\\Products', + 'resolver' => Magento\CatalogGraphQl\Model\Resolver\Products::class, 'description' => 'comment for products fields' ] ] @@ -278,7 +279,7 @@ ] ], - 'typeResolver' => 'Magento\\CatalogGraphQl\\Model\\ProductLinkTypeResolverComposite', + 'typeResolver' => Magento\CatalogGraphQl\Model\ProductLinkTypeResolverComposite::class, 'description' => 'description for ProductLinksInterface' ] ]; diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php index 621030650ac6c..f137a2aca8d4c 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php @@ -105,4 +105,3 @@ public function testToCheckRequestCacheTagsForCategoryWithProducts(): void $this->assertEquals($expectedCacheTags, $actualCacheTags); } } - diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php index 06d9fc1ff5965..3c2f46e1474b9 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php @@ -74,4 +74,3 @@ public function testToCheckRequestCacheTagsForForCategory(): void $this->assertEquals($expectedCacheTags, $actualCacheTags); } } - diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php index 7fd7002142de2..b9f3a4c9a3956 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php @@ -85,4 +85,3 @@ public function testToCheckRequestCacheTagsForProducts(): void $this->assertEquals($expectedCacheTags, $actualCacheTags); } } - From a6cb82926e832e47890cac166497d646da852682 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Fri, 19 Apr 2019 15:27:30 -0500 Subject: [PATCH 430/585] GraphQL-607: Expand `createEmptyCart` mutation --- app/code/Magento/Quote/Model/QuoteIdMask.php | 5 +- .../Model/Cart/CreateEmptyCartForCustomer.php | 67 ++++++++ .../Model/Cart/CreateEmptyCartForGuest.php | 66 +++++++ .../Model/Resolver/CreateEmptyCart.php | 111 ++++++------ .../Plugin/MaskAlreadySetException.php | 33 ---- .../Magento/QuoteGraphQl/etc/graphql/di.xml | 3 - .../Quote/Customer/CreateEmptyCartTest.php | 161 ++++++------------ .../Quote/Guest/CreateEmptyCartTest.php | 93 +++++++--- 8 files changed, 306 insertions(+), 233 deletions(-) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php delete mode 100644 app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php diff --git a/app/code/Magento/Quote/Model/QuoteIdMask.php b/app/code/Magento/Quote/Model/QuoteIdMask.php index 7950ab47c3665..47b02db7650df 100644 --- a/app/code/Magento/Quote/Model/QuoteIdMask.php +++ b/app/code/Magento/Quote/Model/QuoteIdMask.php @@ -53,11 +53,14 @@ protected function _construct() * Initialize quote identifier before save * * @return $this + * @throws \Magento\Framework\Exception\LocalizedException */ public function beforeSave() { parent::beforeSave(); - $this->setMaskedId($this->randomDataGenerator->getUniqueHash()); + if (empty($this->getMaskedId())) { + $this->setMaskedId($this->randomDataGenerator->getUniqueHash()); + } return $this; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php new file mode 100644 index 0000000000000..142542e7b6aa5 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Model\Cart; + +use Magento\Quote\Api\CartManagementInterface; +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\QuoteIdMask as QuoteIdMaskResourceModel; + +/** + * Create empty cart for customer + */ +class CreateEmptyCartForCustomer +{ + /** + * @var CartManagementInterface + */ + private $cartManagement; + + /** + * @var QuoteIdMaskFactory + */ + private $quoteIdMaskFactory; + + /** + * @var QuoteIdMaskResourceModel + */ + private $quoteIdMaskResourceModel; + + /** + * @param CartManagementInterface $cartManagement + * @param QuoteIdMaskFactory $quoteIdMaskFactory + * @param QuoteIdMaskResourceModel $quoteIdMaskResourceModel + */ + public function __construct( + CartManagementInterface $cartManagement, + QuoteIdMaskFactory $quoteIdMaskFactory, + QuoteIdMaskResourceModel $quoteIdMaskResourceModel + ) { + $this->cartManagement = $cartManagement; + $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->quoteIdMaskResourceModel = $quoteIdMaskResourceModel; + } + + /** + * @param string|null $predefinedMaskedQuoteId + * @return string + */ + public function execute(int $customerId, string $predefinedMaskedQuoteId = null): string + { + $quoteId = $this->cartManagement->createEmptyCartForCustomer($customerId); + + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quoteId); + + if (isset($predefinedMaskedQuoteId)) { + $quoteIdMask->setMaskedId($predefinedMaskedQuoteId); + } + + $this->quoteIdMaskResourceModel->save($quoteIdMask); + return $quoteIdMask->getMaskedId(); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php new file mode 100644 index 0000000000000..99eef31e64a47 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Model\Cart; + +use Magento\Quote\Api\GuestCartManagementInterface; +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\QuoteIdMask as QuoteIdMaskResourceModel; + +/** + * Create empty cart for guest + */ +class CreateEmptyCartForGuest +{ + /** + * @var GuestCartManagementInterface + */ + private $guestCartManagement; + + /** + * @var QuoteIdMaskFactory + */ + private $quoteIdMaskFactory; + + /** + * @var QuoteIdMaskResourceModel + */ + private $quoteIdMaskResourceModel; + + /** + * @param GuestCartManagementInterface $guestCartManagement + * @param QuoteIdMaskFactory $quoteIdMaskFactory + * @param QuoteIdMaskResourceModel $quoteIdMaskResourceModel + */ + public function __construct( + GuestCartManagementInterface $guestCartManagement, + QuoteIdMaskFactory $quoteIdMaskFactory, + QuoteIdMaskResourceModel $quoteIdMaskResourceModel + ) { + $this->guestCartManagement = $guestCartManagement; + $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->quoteIdMaskResourceModel = $quoteIdMaskResourceModel; + } + + /** + * @param string|null $predefinedMaskedQuoteId + * @return string + */ + public function execute(string $predefinedMaskedQuoteId = null): string + { + $maskedQuoteId = $this->guestCartManagement->createEmptyCart(); + + if (isset($predefinedMaskedQuoteId)) { + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $this->quoteIdMaskResourceModel->load($quoteIdMask, $maskedQuoteId, 'masked_id'); + + $quoteIdMask->setMaskedId($predefinedMaskedQuoteId); + $this->quoteIdMaskResourceModel->save($quoteIdMask); + } + return $predefinedMaskedQuoteId ?? $maskedQuoteId; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php index ba5e1dea42727..9a559eda6ee64 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php @@ -7,15 +7,15 @@ namespace Magento\QuoteGraphQl\Model\Resolver; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Quote\Api\CartManagementInterface; -use Magento\Quote\Api\GuestCartManagementInterface; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; +use Magento\QuoteGraphQl\Model\Cart\CreateEmptyCartForCustomer; +use Magento\QuoteGraphQl\Model\Cart\CreateEmptyCartForGuest; /** * @inheritdoc @@ -23,41 +23,33 @@ class CreateEmptyCart implements ResolverInterface { /** - * @var CartManagementInterface + * @var CreateEmptyCartForCustomer */ - private $cartManagement; + private $createEmptyCartForCustomer; /** - * @var GuestCartManagementInterface + * @var CreateEmptyCartForGuest */ - private $guestCartManagement; + private $createEmptyCartForGuest; /** - * @var QuoteIdToMaskedQuoteIdInterface + * @var MaskedQuoteIdToQuoteIdInterface */ - private $quoteIdToMaskedId; + private $maskedQuoteIdToQuoteId; /** - * @var QuoteIdMaskFactory - */ - private $quoteIdMaskFactory; - - /** - * @param CartManagementInterface $cartManagement - * @param GuestCartManagementInterface $guestCartManagement - * @param QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedId - * @param QuoteIdMaskFactory $quoteIdMaskFactory + * @param CreateEmptyCartForCustomer $createEmptyCartForCustomer + * @param CreateEmptyCartForGuest $createEmptyCartForGuest + * @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId */ public function __construct( - CartManagementInterface $cartManagement, - GuestCartManagementInterface $guestCartManagement, - QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedId, - QuoteIdMaskFactory $quoteIdMaskFactory + CreateEmptyCartForCustomer $createEmptyCartForCustomer, + CreateEmptyCartForGuest $createEmptyCartForGuest, + MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId ) { - $this->cartManagement = $cartManagement; - $this->guestCartManagement = $guestCartManagement; - $this->quoteIdToMaskedId = $quoteIdToMaskedId; - $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->createEmptyCartForCustomer = $createEmptyCartForCustomer; + $this->createEmptyCartForGuest = $createEmptyCartForGuest; + $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; } /** @@ -66,45 +58,46 @@ public function __construct( public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { $customerId = $context->getUserId(); - $quoteIdMask = $this->quoteIdMaskFactory->create(); - $maskedQuoteId = null; + $predefinedMaskedQuoteId = null; if (isset($args['input']['cart_id'])) { - $maskedQuoteId = $args['input']['cart_id']; - - if ($quoteIdMask->load($maskedQuoteId, 'masked_id') && $quoteIdMask->getQuoteId()) { - throw new GraphQlAlreadyExistsException(__('Specified parameter "cart_id" is non unique.')); - } - - if (mb_strlen($maskedQuoteId) > 32) { - throw new GraphQlInputException(__('"cart_id" length have to be less than or equal to 32.')); - } + $predefinedMaskedQuoteId = $args['input']['cart_id']; + $this->validateMaskedId($predefinedMaskedQuoteId); } - if (0 !== $customerId && null !== $customerId) { - $quoteId = $this->cartManagement->createEmptyCartForCustomer($customerId); - $existsMaskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quoteId); + $maskedQuoteId = (0 === $customerId || null === $customerId) + ? $this->createEmptyCartForGuest->execute($predefinedMaskedQuoteId) + : $this->createEmptyCartForCustomer->execute($customerId, $predefinedMaskedQuoteId); + return $maskedQuoteId; + } - if (empty($existsMaskedQuoteId)) { - if (null !== $maskedQuoteId) { - $quoteIdMask->setMaskedId($maskedQuoteId); - } + /** + * @param string $maskedId + * @throws GraphQlAlreadyExistsException + * @throws GraphQlInputException + */ + private function validateMaskedId(string $maskedId): void + { + if (mb_strlen($maskedId) != 32) { + throw new GraphQlInputException(__('Cart ID length should to be 32 symbols.')); + } - $quoteIdMask->setQuoteId($quoteId)->save(); - $maskedQuoteId = $quoteIdMask->getMaskedId(); - } - } else { - if (null !== $maskedQuoteId) { - $cartId = $this->cartManagement->createEmptyCart(); - $quoteIdMask - ->setQuoteId($cartId) - ->setMaskedId($maskedQuoteId) - ->save(); - } else { - $maskedQuoteId = $this->guestCartManagement->createEmptyCart(); - } + if ($this->isQuoteWithSuchMaskedIdAlreadyExists($maskedId)) { + throw new GraphQlAlreadyExistsException(__('Cart with ID "%1" already exists.', $maskedId)); } + } - return $maskedQuoteId; + /** + * @param string $maskedId + * @return bool + */ + private function isQuoteWithSuchMaskedIdAlreadyExists(string $maskedId): bool + { + try { + $this->maskedQuoteIdToQuoteId->execute($maskedId); + return true; + } catch (NoSuchEntityException $e) { + return false; + } } } diff --git a/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php b/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php deleted file mode 100644 index 2ed364f6f4beb..0000000000000 --- a/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\QuoteGraphQl\Plugin; - -use Magento\Quote\Model\QuoteIdMask; - -/** - * Don't proceed beforeSave method if masked id already set. - */ -class MaskAlreadySetException -{ - /** - * @param \Magento\Quote\Model\QuoteIdMask $subject - * @param \Closure $proceed - * - * @return \Magento\Quote\Model\QuoteIdMask - */ - public function aroundBeforeSave(QuoteIdMask $subject, \Closure $proceed) - { - $maskedId = $subject->getMaskedId(); - - if (!$maskedId) { - $proceed(); - } - - return $subject; - } -} diff --git a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml index 7aa6ce77bfbdf..c7389cf667845 100644 --- a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml @@ -10,7 +10,4 @@ type="Magento\QuoteGraphQl\Model\Cart\SetShippingAddressesOnCart"/> <preference for="Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCartInterface" type="Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCart"/> - <type name="Magento\Quote\Model\QuoteIdMask"> - <plugin name="mask_already_set_exception" type="Magento\QuoteGraphQl\Plugin\MaskAlreadySetException"/> - </type> </config> diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php index 575edbd1885f1..fbd0cf19740d7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php @@ -8,17 +8,12 @@ namespace Magento\GraphQl\Quote\Customer; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; use Magento\Quote\Api\GuestCartRepositoryInterface; -use Magento\Framework\Math\Random as RandomDataGenerator; -use Magento\Framework\Exception\AuthenticationException; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Framework\Exception\LocalizedException; /** * Test for empty cart creation mutation for customer @@ -36,52 +31,32 @@ class CreateEmptyCartTest extends GraphQlAbstract private $customerTokenService; /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory + * @var QuoteCollectionFactory */ - private $quoteFactory; + private $quoteCollectionFactory; /** - * @var MaskedQuoteIdToQuoteIdInterface + * @var QuoteResource */ - private $maskedQuoteIdToQuoteId; + private $quoteResource; /** * @var QuoteIdMaskFactory */ private $quoteIdMaskFactory; - /** - * @var string - */ - private $maskedQuoteId; - - /** - * @var RandomDataGenerator - */ - private $randomDataGenerator; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); - $this->randomDataGenerator = $objectManager->get(RandomDataGenerator::class); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * - * @throws AuthenticationException - * @throws NoSuchEntityException */ public function testCreateEmptyCart() { @@ -92,7 +67,6 @@ public function testCreateEmptyCart() self::assertNotEmpty($response['createEmptyCart']); $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); @@ -100,95 +74,95 @@ public function testCreateEmptyCart() } /** + * @magentoApiDataFixture Magento/Store/_files/second_store.php * @magentoApiDataFixture Magento/Customer/_files/customer.php - * - * @throws LocalizedException - * @throws NoSuchEntityException */ - public function testCreateEmptyCartWithCartId() + public function testCreateEmptyCartWithNotDefaultStore() { - $uniqueHash = $this->randomDataGenerator->getUniqueHash(); + $query = $this->getQuery(); - $query = $this->getQueryWithCartId('cart_id : "' . $uniqueHash . '"'); - $response = $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); + $headerMap = $this->getHeaderMapWithCustomerToken(); + $headerMap['Store'] = 'fixture_second_store'; + $response = $this->graphQlMutation($query, [], '', $headerMap); self::assertArrayHasKey('createEmptyCart', $response); self::assertNotEmpty($response['createEmptyCart']); + /* guestCartRepository is used for registered customer to get the cart hash */ $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); + self::assertEquals('fixture_second_store', $guestCart->getStore()->getCode()); } /** - * @magentoApiDataFixture Magento/Store/_files/second_store.php * @magentoApiDataFixture Magento/Customer/_files/customer.php */ - public function testCreateEmptyCartWithNotDefaultStore() + public function testCreateEmptyCartWithPredefinedCartId() { - $query = $this->getQuery(); + $predefinedCartId = '572cda51902b5b517c0e1a2b2fd004b4'; - $headerMap = $this->getHeaderMapWithCustomerToken(); - $headerMap['Store'] = 'fixture_second_store'; - $response = $this->graphQlMutation($query, [], '', $headerMap); + $query = <<<QUERY +mutation { + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) +} +QUERY; + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); self::assertArrayHasKey('createEmptyCart', $response); - self::assertNotEmpty($response['createEmptyCart']); + self::assertEquals($predefinedCartId, $response['createEmptyCart']); - /* guestCartRepository is used for registered customer to get the cart hash */ $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; - self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); - self::assertEquals('fixture_second_store', $guestCart->getStore()->getCode()); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @dataProvider dataProviderValidateCreateEmptyCartWithSpecifiedCartId - * @param string $input - * @param string $message - * @throws \Exception + * + * @expectedException \Exception + * @expectedExceptionMessage Cart with ID "572cda51902b5b517c0e1a2b2fd004b4" already exists. */ - public function testValidateCreateEmptyCartWithSpecifiedCartId(string $input, string $message) + public function testCreateEmptyCartIfPredefinedCartIdAlreadyExists() { - $input = str_replace('provide_non_unique_id', $this->addEmptyCartWithCartId(), $input); - $input = str_replace('provide_hash_with_prefix', $this->randomDataGenerator->getUniqueHash('prefix'), $input); - - $query = $this->getQueryWithCartId($input); + $predefinedCartId = '572cda51902b5b517c0e1a2b2fd004b4'; - $this->expectExceptionMessage($message); + $query = <<<QUERY +mutation { + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) +} +QUERY; + $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); } /** - * @return string + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * + * @expectedException \Exception + * @expectedExceptionMessage Cart ID length should to be 32 symbols. */ - private function getQuery(): string + public function testCreateEmptyCartWithWrongPredefinedCartId() { - return <<<QUERY + $predefinedCartId = '572'; + + $query = <<<QUERY mutation { - createEmptyCart + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) } QUERY; + $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); } /** - * @param string $input * @return string */ - private function getQueryWithCartId(string $input): string + private function getQuery(): string { return <<<QUERY mutation { - createEmptyCart( - input : { - {$input} - } - ) + createEmptyCart } QUERY; } @@ -197,7 +171,6 @@ private function getQueryWithCartId(string $input): string * @param string $username * @param string $password * @return array - * @throws AuthenticationException */ private function getHeaderMapWithCustomerToken( string $username = 'customer@example.com', @@ -210,50 +183,14 @@ private function getHeaderMapWithCustomerToken( public function tearDown() { - if (null !== $this->maskedQuoteId) { - $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); - - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $quoteId); + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { $this->quoteResource->delete($quote); $quoteIdMask = $this->quoteIdMaskFactory->create(); - $quoteIdMask->setQuoteId($quoteId) + $quoteIdMask->setQuoteId($quote->getId()) ->delete(); } parent::tearDown(); } - - /** - * Return masked id for created empty cart. - * - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @return mixed - * @throws LocalizedException - */ - private function addEmptyCartWithCartId() - { - $uniqueHash = $this->randomDataGenerator->getUniqueHash(); - $query = $this->getQueryWithCartId('cart_id : "' . $uniqueHash . '"'); - $response = $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); - - return $response['createEmptyCart']; - } - - /** - * @return array - */ - public function dataProviderValidateCreateEmptyCartWithSpecifiedCartId(): array - { - return [ - 'cart_id_unique_checking' => [ - 'cart_id: "provide_non_unique_id"', - 'Specified parameter "cart_id" is non unique.' - ], - 'cart_id_length_checking' => [ - 'cart_id: "provide_hash_with_prefix"', - '"cart_id" length have to be less than or equal to 32.' - ], - ]; - } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php index adb2879e186b1..6ed91d21f0ae2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php @@ -7,9 +7,8 @@ namespace Magento\GraphQl\Quote\Guest; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -26,37 +25,26 @@ class CreateEmptyCartTest extends GraphQlAbstract private $guestCartRepository; /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory + * @var QuoteCollectionFactory */ - private $quoteFactory; + private $quoteCollectionFactory; /** - * @var MaskedQuoteIdToQuoteIdInterface + * @var QuoteResource */ - private $maskedQuoteIdToQuoteId; + private $quoteResource; /** * @var QuoteIdMaskFactory */ private $quoteIdMaskFactory; - /** - * @var string - */ - private $maskedQuoteId; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); } @@ -69,7 +57,6 @@ public function testCreateEmptyCart() self::assertNotEmpty($response['createEmptyCart']); $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertNull($guestCart->getCustomer()->getId()); @@ -96,6 +83,65 @@ public function testCreateEmptyCartWithNotDefaultStore() self::assertSame('fixture_second_store', $guestCart->getStore()->getCode()); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + */ + public function testCreateEmptyCartWithPredefinedCartId() + { + $predefinedCartId = '572cda51902b5b517c0e1a2b2fd004b4'; + + $query = <<<QUERY +mutation { + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) +} +QUERY; + $response = $this->graphQlMutation($query); + + self::assertArrayHasKey('createEmptyCart', $response); + self::assertEquals($predefinedCartId, $response['createEmptyCart']); + + $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); + self::assertNotNull($guestCart->getId()); + self::assertNull($guestCart->getCustomer()->getId()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * + * @expectedException \Exception + * @expectedExceptionMessage Cart with ID "572cda51902b5b517c0e1a2b2fd004b4" already exists. + */ + public function testCreateEmptyCartIfPredefinedCartIdAlreadyExists() + { + $predefinedCartId = '572cda51902b5b517c0e1a2b2fd004b4'; + + $query = <<<QUERY +mutation { + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) +} +QUERY; + $this->graphQlMutation($query); + $this->graphQlMutation($query); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * + * @expectedException \Exception + * @expectedExceptionMessage Cart ID length should to be 32 symbols. + */ + public function testCreateEmptyCartWithWrongPredefinedCartId() + { + $predefinedCartId = '572'; + + $query = <<<QUERY +mutation { + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) +} +QUERY; + $this->graphQlMutation($query); + } + /** * @return string */ @@ -110,15 +156,12 @@ private function getQuery(): string public function tearDown() { - if (null !== $this->maskedQuoteId) { - $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); - - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $quoteId); + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { $this->quoteResource->delete($quote); $quoteIdMask = $this->quoteIdMaskFactory->create(); - $quoteIdMask->setQuoteId($quoteId) + $quoteIdMask->setQuoteId($quote->getId()) ->delete(); } parent::tearDown(); From 453ceabeedc0343db221637dd60645a522ba574b Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Fri, 19 Apr 2019 16:17:23 -0500 Subject: [PATCH 431/585] GraphlQL:597 Cart - No Cache Test (Api-functional Test for Tag Cache Generation) No cache tags tests are added --- .../PageCache/Quote/Guest/CartCacheTest.php | 1 + .../Controller/Catalog/ProductsCacheTest.php | 39 ++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php index 0ef60e1fbde36..814cc0779401b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php @@ -109,6 +109,7 @@ private function addSimpleProductToCart($maskedCartId, $qty, $sku) } /** + * Get Check Cart query * * @param string $maskedQuoteId * @return string diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php index 7fd7002142de2..d0b95b20656c6 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php @@ -40,6 +40,7 @@ protected function setUp(): void $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); $this->request = $this->objectManager->create(Http::class); } + /** * Test request is dispatched and response is checked for debug headers and cache tags * @@ -84,5 +85,41 @@ public function testToCheckRequestCacheTagsForProducts(): void $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; $this->assertEquals($expectedCacheTags, $actualCacheTags); } -} + /** + * Test request is checked for debug headers and no cache tags for not existing product + */ + public function testToCheckRequestNoTagsForProducts(): void + { + $query + = <<<QUERY + { + products(filter: {sku: {eq: "simple10"}}) + { + items { + id + name + sku + description { + html + } + } + } + } + +QUERY; + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphqlController->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = [ 'FPC']; + $this->assertEquals($expectedCacheTags, $actualCacheTags); + } +} From 962ad5e055717c22af8c8f6414d49bc178aaaee3 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 19 Apr 2019 16:30:51 -0500 Subject: [PATCH 432/585] Issue-230: Implement cache tag generation for GraphQL queries - Refactor IdentityInterface --- ...ityResolver.php => CategoriesIdentity.php} | 6 +-- ...yResolver.php => CategoryTreeIdentity.php} | 6 +-- .../{IdentityResolver.php => Identity.php} | 6 +-- .../CatalogGraphQl/etc/schema.graphqls | 8 +-- .../{IdentityResolver.php => Identity.php} | 8 +-- .../{IdentityResolver.php => Identity.php} | 6 +-- .../Magento/CmsGraphQl/etc/schema.graphqls | 4 +- .../Model/CacheableQueryHandler.php | 19 +++---- .../Model/IdentityResolverPool.php | 49 ------------------- .../Model/Resolver/IdentityPool.php | 49 +++++++++++++++++++ .../Unit/Model/CacheableQueryHandlerTest.php | 30 ++++++------ .../GraphQl/_files/query_array_output.php | 2 +- .../Framework/GraphQl/_files/schemaC.graphqls | 2 +- .../IdentityInterface.php} | 8 +-- .../MetaReader/CacheTagReader.php | 4 +- 15 files changed, 104 insertions(+), 103 deletions(-) rename app/code/Magento/CatalogGraphQl/Model/Resolver/Category/{CategoriesIdentityResolver.php => CategoriesIdentity.php} (74%) rename app/code/Magento/CatalogGraphQl/Model/Resolver/Category/{CategoryTreeIdentityResolver.php => CategoryTreeIdentity.php} (69%) rename app/code/Magento/CatalogGraphQl/Model/Resolver/Product/{IdentityResolver.php => Identity.php} (74%) rename app/code/Magento/CmsGraphQl/Model/Resolver/Block/{IdentityResolver.php => Identity.php} (75%) rename app/code/Magento/CmsGraphQl/Model/Resolver/Page/{IdentityResolver.php => Identity.php} (73%) delete mode 100644 app/code/Magento/GraphQlCache/Model/IdentityResolverPool.php create mode 100644 app/code/Magento/GraphQlCache/Model/Resolver/IdentityPool.php rename lib/internal/Magento/Framework/GraphQl/Query/{IdentityResolverInterface.php => Resolver/IdentityInterface.php} (53%) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php similarity index 74% rename from app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php rename to app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php index 1fad463ddee19..d81f6db574a3d 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentityResolver.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php @@ -7,12 +7,12 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Category; -use Magento\Framework\GraphQl\Query\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface; /** * Identity for multiple resolved categories */ -class CategoriesIdentityResolver implements IdentityResolverInterface +class CategoriesIdentity implements IdentityInterface { /** * Get category IDs from resolved data @@ -20,7 +20,7 @@ class CategoriesIdentityResolver implements IdentityResolverInterface * @param array $resolvedData * @return array */ - public function getIdentifiers(array $resolvedData): array + public function getIdentities(array $resolvedData): array { $ids = []; if (!empty($resolvedData)) { diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentityResolver.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php similarity index 69% rename from app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentityResolver.php rename to app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php index 0bfe6d2e4699a..8cc77b53c5aaa 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentityResolver.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php @@ -7,12 +7,12 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Category; -use Magento\Framework\GraphQl\Query\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface; /** * Identity for resolved category */ -class CategoryTreeIdentityResolver implements IdentityResolverInterface +class CategoryTreeIdentity implements IdentityInterface { /** * Get category ID from resolved data @@ -20,7 +20,7 @@ class CategoryTreeIdentityResolver implements IdentityResolverInterface * @param array $resolvedData * @return array */ - public function getIdentifiers(array $resolvedData): array + public function getIdentities(array $resolvedData): array { return empty($resolvedData['id']) ? [] : [$resolvedData['id']]; } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php similarity index 74% rename from app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php rename to app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php index eece587eb4299..bbb0057befc7a 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/IdentityResolver.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php @@ -7,12 +7,12 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Product; -use Magento\Framework\GraphQl\Query\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface; /** * Identity for resolved products */ -class IdentityResolver implements IdentityResolverInterface +class Identity implements IdentityInterface { /** * Get product ids for cache tag @@ -20,7 +20,7 @@ class IdentityResolver implements IdentityResolverInterface * @param array $resolvedData * @return array */ - public function getIdentifiers(array $resolvedData): array + public function getIdentities(array $resolvedData): array { $ids = []; $items = $resolvedData['items'] ?? []; diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index eece33fc26583..08066e5fdfed3 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -9,11 +9,11 @@ type Query { currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") ): Products - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cacheTag: "cat_p", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\IdentityResolver") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cacheTag: "cat_p", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Identity") category ( id: Int @doc(description: "Id of the category") ): CategoryTree - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cacheTag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentityResolver") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cacheTag: "cat_c", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentity") } enum CurrencyEnum @doc(description: "The list of available currency codes") { @@ -275,7 +275,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available") manufacturer: Int @doc(description: "A number representing the product's manufacturer") - categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @cache(cacheTag: "cat_c", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoriesIdentityResolver") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") + categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @cache(cacheTag: "cat_c", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoriesIdentity") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") canonical_url: String @doc(description: "Canonical URL") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\CanonicalUrl") } @@ -396,7 +396,7 @@ interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."), currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") - ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cacheTag: "cat_p", cacheIdentityResolver: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\IdentityResolver") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") + ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cacheTag: "cat_p", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Identity") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") breadcrumbs: [Breadcrumb] @doc(description: "Breadcrumbs, parent categories info") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Breadcrumbs") } diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php similarity index 75% rename from app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php rename to app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php index 5f18bce21f378..9431d20692187 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/IdentityResolver.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php @@ -8,20 +8,20 @@ namespace Magento\CmsGraphQl\Model\Resolver\Block; use Magento\Cms\Api\Data\BlockInterface; -use Magento\Framework\GraphQl\Query\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface; /** * Identity for resolved CMS block */ -class IdentityResolver implements IdentityResolverInterface +class Identity implements IdentityInterface { /** - * Get block identifiers from resolved data + * Get block identities from resolved data * * @param array $resolvedData * @return array */ - public function getIdentifiers(array $resolvedData): array + public function getIdentities(array $resolvedData): array { $ids = []; $items = $resolvedData['items'] ?? []; diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php similarity index 73% rename from app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php rename to app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php index d139cb383233f..5a11587f4b1e5 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Page/IdentityResolver.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php @@ -8,12 +8,12 @@ namespace Magento\CmsGraphQl\Model\Resolver\Page; use Magento\Cms\Api\Data\PageInterface; -use Magento\Framework\GraphQl\Query\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface; /** * Identity for resolved CMS page */ -class IdentityResolver implements IdentityResolverInterface +class Identity implements IdentityInterface { /** * Get page ID from resolved data @@ -21,7 +21,7 @@ class IdentityResolver implements IdentityResolverInterface * @param array $resolvedData * @return array */ - public function getIdentifiers(array $resolvedData): array + public function getIdentities(array $resolvedData): array { return empty($resolvedData[PageInterface::PAGE_ID]) ? [] : [$resolvedData[PageInterface::PAGE_ID]]; } diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index 1734cf80afd64..04d2efa4c7cde 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -13,10 +13,10 @@ type StoreConfig @doc(description: "The type contains information about a store type Query { cmsPage ( id: Int @doc(description: "Id of the CMS page") - ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cacheTag: "cms_p", cacheIdentityResolver: "Magento\\CmsGraphQl\\Model\\Resolver\\Page\\IdentityResolver") + ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cacheTag: "cms_p", cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Page\\Identity") cmsBlocks ( identifiers: [String] @doc(description: "Identifiers of the CMS blocks") - ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cacheTag: "cms_b", cacheIdentityResolver: "Magento\\CmsGraphQl\\Model\\Resolver\\Block\\IdentityResolver") + ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cacheTag: "cms_b", cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Block\\Identity") } type CmsPage @doc(description: "CMS page defines all CMS page information") { diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php index 326c53b589911..7e624845f5682 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -9,6 +9,7 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\App\RequestInterface; +use Magento\GraphQlCache\Model\Resolver\IdentityPool; /** * Handler of collecting tagging on cache. @@ -29,23 +30,23 @@ class CacheableQueryHandler private $request; /** - * @var IdentityResolverPool + * @var IdentityPool */ - private $identityResolverPool; + private $identityPool; /** * @param CacheableQuery $cacheableQuery * @param RequestInterface $request - * @param IdentityResolverPool $identityResolverPool + * @param IdentityPool $identityPool */ public function __construct( CacheableQuery $cacheableQuery, RequestInterface $request, - IdentityResolverPool $identityResolverPool + IdentityPool $identityPool ) { $this->cacheableQuery = $cacheableQuery; $this->request = $request; - $this->identityResolverPool = $identityResolverPool; + $this->identityPool = $identityPool; } /** @@ -58,15 +59,15 @@ public function __construct( public function handleCacheFromResolverResponse(array $resolvedValue, Field $field) : void { $cache = $field->getCache(); - $cacheIdentityResolverClass = $cache['cacheIdentityResolver'] ?? ''; + $cacheIdentityClass = $cache['cacheIdentity'] ?? ''; $cacheable = $cache['cacheable'] ?? true; $cacheTag = $cache['cacheTag'] ?? null; $cacheTags = []; if ($cacheTag && $this->request->isGet()) { - if (!empty($cacheIdentityResolverClass)) { - $cacheIdentityResolver = $this->identityResolverPool->get($cacheIdentityResolverClass); - $cacheTagIds = $cacheIdentityResolver->getIdentifiers($resolvedValue); + if (!empty($cacheIdentityClass)) { + $cacheIdentity = $this->identityPool->get($cacheIdentityClass); + $cacheTagIds = $cacheIdentity->getIdentities($resolvedValue); if (!empty($cacheTagIds)) { $cacheTags[] = $cacheTag; foreach ($cacheTagIds as $cacheTagId) { diff --git a/app/code/Magento/GraphQlCache/Model/IdentityResolverPool.php b/app/code/Magento/GraphQlCache/Model/IdentityResolverPool.php deleted file mode 100644 index da97e5ba4f2e2..0000000000000 --- a/app/code/Magento/GraphQlCache/Model/IdentityResolverPool.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQlCache\Model; - -use Magento\Framework\ObjectManagerInterface; -use Magento\Framework\GraphQl\Query\IdentityResolverInterface; - -/** - * Pool of IdentityResolverInterface objects - */ -class IdentityResolverPool -{ - /** - * @var IdentityResolverInterface[] - */ - private $identityResolvers = []; - - /** - * @var ObjectManagerInterface - */ - private $objectManager; - - /** - * @param ObjectManagerInterface $objectManager - */ - public function __construct(ObjectManagerInterface $objectManager) - { - $this->objectManager = $objectManager; - } - - /** - * Get an identity resolver by class name - * - * @param string $identityResolverClass - * @return IdentityResolverInterface - */ - public function get(string $identityResolverClass): IdentityResolverInterface - { - if (!isset($this->identityResolvers[$identityResolverClass])) { - $this->identityResolvers[$identityResolverClass] = $this->objectManager->create($identityResolverClass); - } - return $this->identityResolvers[$identityResolverClass]; - } -} diff --git a/app/code/Magento/GraphQlCache/Model/Resolver/IdentityPool.php b/app/code/Magento/GraphQlCache/Model/Resolver/IdentityPool.php new file mode 100644 index 0000000000000..00ef8762c28ef --- /dev/null +++ b/app/code/Magento/GraphQlCache/Model/Resolver/IdentityPool.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Model\Resolver; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface; + +/** + * Pool of IdentityInterface objects + */ +class IdentityPool +{ + /** + * @var IdentityInterface[] + */ + private $identityInstances = []; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @param ObjectManagerInterface $objectManager + */ + public function __construct(ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * Get an identity resolver by class name + * + * @param string $identityClass + * @return IdentityInterface + */ + public function get(string $identityClass): IdentityInterface + { + if (!isset($this->identityInstances[$identityClass])) { + $this->identityInstances[$identityClass] = $this->objectManager->create($identityClass); + } + return $this->identityInstances[$identityClass]; + } +} diff --git a/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php b/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php index c595881472e58..9c1be89928215 100644 --- a/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php +++ b/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php @@ -9,9 +9,9 @@ use Magento\Framework\App\Request\Http; use Magento\Framework\GraphQl\Config\Element\Field; -use Magento\Framework\GraphQl\Query\IdentityResolverInterface; +use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface; use Magento\GraphQlCache\Model\CacheableQueryHandler; -use Magento\GraphQlCache\Model\IdentityResolverPool; +use Magento\GraphQlCache\Model\Resolver\IdentityPool; use Magento\GraphQlCache\Model\CacheableQuery; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use PHPUnit\Framework\TestCase; @@ -28,50 +28,50 @@ class CacheableQueryHandlerTest extends TestCase private $requestMock; - private $identityResolverPoolMock; + private $identityPoolMock; protected function setup(): void { $objectManager = new ObjectManager($this); $this->cacheableQueryMock = $this->createMock(CacheableQuery::class); $this->requestMock = $this->createMock(Http::class); - $this->identityResolverPoolMock = $this->createMock(IdentityResolverPool::class); + $this->identityPoolMock = $this->createMock(IdentityPool::class); $this->cacheableQueryHandler = $objectManager->getObject( CacheableQueryHandler::class, [ 'cacheableQuery' => $this->cacheableQueryMock, 'request' => $this->requestMock, - 'identityResolverPool' => $this->identityResolverPoolMock + 'identityPool' => $this->identityPoolMock ] ); } /** * @param array $resolvedData - * @param array $resolvedIdentities + * @param array $identities * @dataProvider resolvedDataProvider */ public function testhandleCacheFromResolverResponse( array $resolvedData, - array $resolvedIdentities, + array $identities, array $expectedCacheTags ): void { $cacheData = [ - 'cacheIdentityResolver' => IdentityResolverInterface::class, + 'cacheIdentity' => IdentityInterface::class, 'cacheTag' => 'cat_p' ]; $fieldMock = $this->createMock(Field::class); - $mockIdentityResolver = $this->getMockBuilder($cacheData['cacheIdentityResolver']) - ->setMethods(['getIdentifiers']) + $mockIdentity = $this->getMockBuilder($cacheData['cacheIdentity']) + ->setMethods(['getIdentities']) ->getMockForAbstractClass(); $this->requestMock->expects($this->once())->method('isGet')->willReturn(true); - $this->identityResolverPoolMock->expects($this->once())->method('get')->willReturn($mockIdentityResolver); + $this->identityPoolMock->expects($this->once())->method('get')->willReturn($mockIdentity); $fieldMock->expects($this->once())->method('getCache')->willReturn($cacheData); - $mockIdentityResolver->expects($this->once()) - ->method('getIdentifiers') + $mockIdentity->expects($this->once()) + ->method('getIdentities') ->with($resolvedData) - ->willReturn($resolvedIdentities); + ->willReturn($identities); $this->cacheableQueryMock->expects($this->once())->method('addCacheTags')->with($expectedCacheTags); $this->cacheableQueryMock->expects($this->once())->method('isCacheable')->willReturn(true); $this->cacheableQueryMock->expects($this->once())->method('setCacheValidity')->with(true); @@ -91,7 +91,7 @@ public function resolvedDataProvider(): array "name" => "TesName", "sku" => "TestSku" ], - "resolvedIdentities" => [10], + "identities" => [10], "expectedCacheTags" => ["cat_p", "cat_p_10"] ] ]; diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php index f7c2597fe5710..c7c9c04c5eac9 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php @@ -35,7 +35,7 @@ 'description' => 'Returns the attribute type, given an attribute code and entity type', 'cache' => [ 'cacheTag' => 'cat_test', - 'cacheIdentityResolver' => 'Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata' + 'cacheIdentity' => 'Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata' ] ], 'products' => [ diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/schemaC.graphqls b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/schemaC.graphqls index 895185bc6dd2f..92682468c42be 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/schemaC.graphqls +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/schemaC.graphqls @@ -1,6 +1,6 @@ type Query { customAttributeMetadata(attributes: [AttributeInput!]!): CustomAttributeMetadata @resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata") - @doc(description: "Returns the attribute type, given an attribute code and entity type") @cache(cacheTag: "cat_test", cacheIdentityResolver: "Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata") + @doc(description: "Returns the attribute type, given an attribute code and entity type") @cache(cacheTag: "cat_test", cacheIdentity: "Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata") } type CustomAttributeMetadata { diff --git a/lib/internal/Magento/Framework/GraphQl/Query/IdentityResolverInterface.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php similarity index 53% rename from lib/internal/Magento/Framework/GraphQl/Query/IdentityResolverInterface.php rename to lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php index 588052c8df6e7..b0cad2f133a7e 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/IdentityResolverInterface.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php @@ -5,16 +5,16 @@ */ declare(strict_types=1); -namespace Magento\Framework\GraphQl\Query; +namespace Magento\Framework\GraphQl\Query\Resolver; -interface IdentityResolverInterface +interface IdentityInterface { /** - * Get identifiers from resolved data + * Get identities from resolved data * * @param array $resolvedData * @return array */ - public function getIdentifiers(array $resolvedData) : array; + public function getIdentities(array $resolvedData) : array; } diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php index ae7ee4a1ec385..666dfa8d3e8a9 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php @@ -36,10 +36,10 @@ public function read(\GraphQL\Language\AST\NodeList $directives) : array ["cacheable" => $directiveArgument->value->value] ); } - if ($directiveArgument->name->value == 'cacheIdentityResolver') { + if ($directiveArgument->name->value == 'cacheIdentity') { $argMap = array_merge( $argMap, - ["cacheIdentityResolver" => $directiveArgument->value->value] + ["cacheIdentity" => $directiveArgument->value->value] ); } } From 67fc3e3ed7eaeff5d6075a611e0693cce9c18c9a Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 19 Apr 2019 16:31:29 -0500 Subject: [PATCH 433/585] GraphQL-597: Test coverage for cart-not cached test - refactor test --- .../PageCache/Quote/Guest/CartCacheTest.php | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php index 0ef60e1fbde36..34cc50e891dcb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php @@ -10,16 +10,15 @@ use Magento\TestFramework\TestCase\GraphQlAbstract; /** - * End to end test which creates an empty cart and add product to the cart and load the cart. - * Validates that the cache-debug header is a MISS for any subsequent cart requests + * Test cart queries are note cached * * @magentoApiDataFixture Magento/Catalog/_files/products.php */ class CartCacheTest extends GraphQlAbstract { - /** @var string */ - private $maskedQuoteId; - + /** + * @inheritdoc + */ protected function setUp() { $this->markTestSkipped( @@ -27,26 +26,22 @@ protected function setUp() ); } - /** - * Tests that X-Magento-Tags are correct - */ public function testCartIsNotCached() { $qty = 2; $sku = 'simple'; $cartId = $this->createEmptyCart(); $this->addSimpleProductToCart($cartId, $qty, $sku); - $getCartQuery = $this->checkCart($cartId); - $response = $this->graphQlQuery($getCartQuery); - self::assertArrayHasKey('cart', $response); - self::assertArrayHasKey('items', $response['cart']); - $responseMissHeaders = $this->graphQlQueryForHttpHeaders($getCartQuery); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeaders); + $getCartQuery = $this->getCartQuery($cartId); + $responseMiss = $this->graphQlQueryWithResponseHeaders($getCartQuery); + $this->assertArrayHasKey('cart', $responseMiss['body']); + $this->assertArrayHasKey('items', $responseMiss['body']['cart']); + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); /** Cache debug header value is still a MISS for any subsequent request */ - $responseMissHeadersNext = $this->graphQlQueryForHttpHeaders($getCartQuery); - $this->assertContains('X-Magento-Cache-Debug: MISS', $responseMissHeadersNext); + $responseMissNext = $this->graphQlQueryWithResponseHeaders($getCartQuery); + $this->assertEquals('MISS', $responseMissNext['headers']['X-Magento-Cache-Debug']); } /** @@ -65,12 +60,13 @@ private function createEmptyCart(): string QUERY; $response = $this->graphQlMutation($query); - $this->maskedQuoteId = $response['createEmptyCart']; - return $this->maskedQuoteId; + $maskedQuoteId = $response['createEmptyCart']; + return $maskedQuoteId; } /** * Add simple product to the cart using the maskedQuoteId + * * @param $maskedCartId * @param $qty * @param $sku @@ -109,11 +105,12 @@ private function addSimpleProductToCart($maskedCartId, $qty, $sku) } /** + * Get cart query string * * @param string $maskedQuoteId * @return string */ - private function checkCart(string $maskedQuoteId): string + private function getCartQuery(string $maskedQuoteId): string { return <<<QUERY { From a5164575500ecfba67b2929aab219f11be43dcd0 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Fri, 19 Apr 2019 17:04:17 -0500 Subject: [PATCH 434/585] Updated test changes for the CartCacheTest and ProductsCacheTest --- .../PageCache/Quote/Guest/CartCacheTest.php | 4 +- .../Controller/Catalog/ProductsCacheTest.php | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php index a40912fa1bb59..176fa0dff2f07 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php @@ -38,7 +38,7 @@ public function testCartIsNotCached() $this->assertArrayHasKey('cart', $responseMiss['body']); $this->assertArrayHasKey('items', $responseMiss['body']['cart']); $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); - + /** Cache debug header value is still a MISS for any subsequent request */ $responseMissNext = $this->graphQlQueryWithResponseHeaders($getCartQuery); $this->assertEquals('MISS', $responseMissNext['headers']['X-Magento-Cache-Debug']); @@ -105,7 +105,7 @@ private function addSimpleProductToCart($maskedCartId, $qty, $sku) } /** - * Get Check Cart query + * Get cart query string * * @param string $maskedQuoteId * @return string diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php index a544e53554544..d0b95b20656c6 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php @@ -17,6 +17,7 @@ * * @magentoAppArea graphql * @magentoCache full_page enabled + * @magentoDbIsolation disabled */ class ProductsCacheTest extends AbstractGraphqlCacheTest { @@ -39,6 +40,7 @@ protected function setUp(): void $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); $this->request = $this->objectManager->create(Http::class); } + /** * Test request is dispatched and response is checked for debug headers and cache tags * @@ -83,4 +85,41 @@ public function testToCheckRequestCacheTagsForProducts(): void $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; $this->assertEquals($expectedCacheTags, $actualCacheTags); } + + /** + * Test request is checked for debug headers and no cache tags for not existing product + */ + public function testToCheckRequestNoTagsForProducts(): void + { + $query + = <<<QUERY + { + products(filter: {sku: {eq: "simple10"}}) + { + items { + id + name + sku + description { + html + } + } + } + } + +QUERY; + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + /** @var \Magento\Framework\Controller\Result\Json $result */ + $result = $this->graphqlController->dispatch($this->request); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); + /** @var $registry \Magento\Framework\Registry */ + $result->renderResult($response); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = [ 'FPC']; + $this->assertEquals($expectedCacheTags, $actualCacheTags); + } } From 9205c6fa88e3de4ac09e48a85cd193507d47e1f7 Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Fri, 19 Apr 2019 12:19:00 +0300 Subject: [PATCH 435/585] PUT /V1/products/:sku/media/:entryId does not change the file --- .../Catalog/Model/Product/Gallery/GalleryManagement.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php b/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php index 0e08b0af92862..9e5cf084c25a1 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php @@ -105,7 +105,10 @@ public function update($sku, ProductAttributeMediaGalleryEntryInterface $entry) if ($existingEntry->getId() == $entry->getId()) { $found = true; - if ($entry->getFile()) { + + $file = $entry->getContent(); + + if ($file && $file->getBase64EncodedData() || $entry->getFile()) { $entry->setId(null); } $existingMediaGalleryEntries[$key] = $entry; From 0ef9ba0678f387b8b74ee23e4487a2200176ecee Mon Sep 17 00:00:00 2001 From: eugene-shab <dev.eugene.shab@gmail.com> Date: Sat, 20 Apr 2019 14:13:13 +0300 Subject: [PATCH 436/585] Update cartAddressId through cart billing address. --- .../QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php index fccda9e28c11e..d4e3923846b36 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php @@ -60,9 +60,8 @@ public function execute(ContextInterface $context, CartInterface $cart, array $s } $methodCode = $shippingMethodInput['method_code']; -// $quoteAddress = $this->getQuoteAddress->execute($cart, $context->getUserId()); -// $this->assignShippingMethodToCart->execute($cart, $quoteAddress, $carrierCode, $methodCode); - $quoteAddress = $cart->getShippingAddress(); + $cartAddressId = $cart->getBillingAddress()->getId(); + $quoteAddress = $this->getQuoteAddress->execute($cart, $cartAddressId, $context->getUserId()); $this->assignShippingMethodToCart->execute($cart, $quoteAddress, $carrierCode, $methodCode); } } From 0c1ffcd398d09adf28abcfd5d3c5d3d253a4b2d4 Mon Sep 17 00:00:00 2001 From: Yannis Livasov <ilib@mail.ru> Date: Tue, 9 Apr 2019 02:40:24 +0300 Subject: [PATCH 437/585] Shortening currency list in Configuration->General use isset array_flip --- .../Model/Config/Source/Locale/Currency.php | 64 ++++++++++++++++--- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Config/Model/Config/Source/Locale/Currency.php b/app/code/Magento/Config/Model/Config/Source/Locale/Currency.php index b3474674cf76d..5beff0d043ade 100644 --- a/app/code/Magento/Config/Model/Config/Source/Locale/Currency.php +++ b/app/code/Magento/Config/Model/Config/Source/Locale/Currency.php @@ -4,12 +4,15 @@ * See COPYING.txt for license details. */ -/** - * Locale currency source - */ namespace Magento\Config\Model\Config\Source\Locale; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Locale\ListsInterface; + /** + * Locale currency source. + * * @api * @since 100.0.2 */ @@ -21,27 +24,70 @@ class Currency implements \Magento\Framework\Option\ArrayInterface protected $_options; /** - * @var \Magento\Framework\Locale\ListsInterface + * @var ListsInterface */ protected $_localeLists; /** - * @param \Magento\Framework\Locale\ListsInterface $localeLists + * @var ScopeConfigInterface */ - public function __construct(\Magento\Framework\Locale\ListsInterface $localeLists) - { + private $config; + + /** + * @var array + */ + private $installedCurrencies; + + /** + * @param ListsInterface $localeLists + * @param ScopeConfigInterface $config + */ + public function __construct( + ListsInterface $localeLists, + ScopeConfigInterface $config = null + ) { $this->_localeLists = $localeLists; + $this->config = $config ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class); } /** - * @return array + * @inheritdoc */ public function toOptionArray() { if (!$this->_options) { $this->_options = $this->_localeLists->getOptionCurrencies(); } - $options = $this->_options; + + $selected = array_flip($this->getInstalledCurrencies()); + + $options = array_filter( + $this->_options, + function ($option) use ($selected) { + return isset($selected[$option['value']]); + } + ); + return $options; } + + /** + * Retrieve Installed Currencies. + * + * @return array + */ + private function getInstalledCurrencies() + { + if (!$this->installedCurrencies) { + $this->installedCurrencies = explode( + ',', + $this->config->getValue( + 'system/currency/installed', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ) + ); + } + + return $this->installedCurrencies; + } } From c7da38b4b8d364235871919d5e1fbf21cbcc95b5 Mon Sep 17 00:00:00 2001 From: eugene-shab <dev.eugene.shab@gmail.com> Date: Sat, 20 Apr 2019 20:07:14 +0300 Subject: [PATCH 438/585] Updates. --- .../Quote/Guest/SetOfflineShippingMethodsOnCartTest.php | 9 ++------- .../GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php | 5 +---- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php index 2c1333aa77326..a89419b51df44 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php @@ -56,13 +56,11 @@ protected function setUp() public function testSetOfflineShippingMethod(string $carrierCode, string $methodCode, float $amount, string $label) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $response = $this->graphQlMutation($query); @@ -103,14 +101,12 @@ public function offlineShippingMethodDataProvider(): array * @param string $maskedQuoteId * @param string $shippingMethodCode * @param string $shippingCarrierCode - * @param int $shippingAddressId * @return string */ private function getQuery( string $maskedQuoteId, string $shippingMethodCode, - string $shippingCarrierCode, - int $shippingAddressId + string $shippingCarrierCode ): string { return <<<QUERY mutation { @@ -118,7 +114,6 @@ private function getQuery( { cart_id: "$maskedQuoteId", shipping_methods: [{ - cart_address_id: $shippingAddressId carrier_code: "$shippingCarrierCode" method_code: "$shippingMethodCode" }] diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php index 59f53d2ad6856..06cf3d0c9698c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php @@ -51,13 +51,11 @@ public function testSetShippingMethodOnCartWithSimpleProduct() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $carrierCode = 'flatrate'; $methodCode = 'flatrate'; - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $response = $this->graphQlMutation($query); @@ -425,7 +423,6 @@ private function getQuery( { cart_id: "$maskedQuoteId", shipping_methods: [{ - cart_address_id: $shippingAddressId carrier_code: "$shippingCarrierCode" method_code: "$shippingMethodCode" }] From f22e16b6f7bd84303cfd22dd5dc17d9a58b8101b Mon Sep 17 00:00:00 2001 From: Pieter Hoste <hoste.pieter@gmail.com> Date: Sun, 21 Apr 2019 17:56:28 +0200 Subject: [PATCH 439/585] Removes usage of classes which don't exist from DB migration scripts. --- app/code/Magento/Catalog/Setup/CategorySetup.php | 3 --- .../Patch/Data/MigrateStoresAllowedCountriesToWebsite.php | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Setup/CategorySetup.php b/app/code/Magento/Catalog/Setup/CategorySetup.php index 271387932829b..581a5bf489194 100644 --- a/app/code/Magento/Catalog/Setup/CategorySetup.php +++ b/app/code/Magento/Catalog/Setup/CategorySetup.php @@ -10,7 +10,6 @@ use Magento\Catalog\Block\Adminhtml\Category\Helper\Pricestep; use Magento\Catalog\Block\Adminhtml\Category\Helper\Sortby\Available; use Magento\Catalog\Block\Adminhtml\Category\Helper\Sortby\DefaultSortby; -use Magento\Catalog\Block\Adminhtml\Product\Helper\Form\BaseImage; use Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Category as CategoryFormHelper; use Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Weight as WeightFormHelper; use Magento\Catalog\Model\Attribute\Backend\Customlayoutupdate; @@ -593,7 +592,6 @@ public function getDefaultEntities() 'label' => 'Base Image', 'input' => 'media_image', 'frontend' => ImageFrontendModel::class, - 'input_renderer' => BaseImage::class, 'required' => false, 'sort_order' => 0, 'global' => ScopedAttributeInterface::SCOPE_STORE, @@ -626,7 +624,6 @@ public function getDefaultEntities() 'type' => 'varchar', 'label' => 'Media Gallery', 'input' => 'gallery', - 'backend' => Media::class, 'required' => false, 'sort_order' => 4, 'group' => 'Images', diff --git a/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php b/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php index 7488f3fd4a920..8ed940250e213 100644 --- a/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php +++ b/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php @@ -8,7 +8,6 @@ use Magento\Directory\Model\AllowedCountries; use Magento\Framework\Setup\ModuleDataSetupInterface; -use Magento\Directory\Model\AllowedCountriesFactory; use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\Framework\Setup\Patch\DataPatchInterface; @@ -27,7 +26,7 @@ class MigrateStoresAllowedCountriesToWebsite implements DataPatchInterface, Patc private $storeManager; /** - * @var AllowedCountriesFactory + * @var AllowedCountries */ private $allowedCountries; From eaafea1d9edf324170ac2f74eba9d82679eb5457 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Sun, 21 Apr 2019 16:01:33 -0500 Subject: [PATCH 440/585] Minor fixes for magento/magento-functional-tests-migration#581: Convert DeleteCustomerGroupEntityTest to MFTF --- ...AdminOpenNewProductFormPageActionGroup.xml | 19 ++++ .../Test/Mftf/Data/AttributeSetData.xml | 16 ++++ ...AdminProductFormAdvancedPricingSection.xml | 1 + ...NewCatalogPriceRuleFormPageActionGroup.xml | 14 +++ ...upNotOnCatalogPriceRuleFormActionGroup.xml | 20 +++++ .../Test/Mftf/Page/CatalogRuleNewPage.xml | 14 +++ .../Mftf/Test/DeleteCustomerGroupTest.xml | 17 ++++ .../AdminOpenCustomerEditPageActionGroup.xml | 17 ++++ ...ssertCustomerGroupNotInGridActionGroup.xml | 20 +++++ ...stomerGroupNotOnProductFormActionGroup.xml | 23 +++++ ...CustomerGroupOnCustomerFormActionGroup.xml | 18 ++++ .../Customer/Test/Mftf/Data/CustomerData.xml | 13 +++ .../Mftf/Test/DeleteCustomerGroupTest.xml | 89 +++++-------------- ...penNewCartPriceRuleFormPageActionGroup.xml | 14 +++ ...GroupNotOnCartPriceRuleFormActionGroup.xml | 20 +++++ .../AdminCartPriceRulesFormSection.xml | 1 + .../Mftf/Test/DeleteCustomerGroupTest.xml | 17 ++++ .../DeleteCustomerGroupEntityTest.xml | 1 + 18 files changed, 267 insertions(+), 67 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenNewProductFormPageActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Data/AttributeSetData.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminOpenNewCatalogPriceRuleFormPageActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Page/CatalogRuleNewPage.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminOpenCustomerEditPageActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotInGridActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnProductFormActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupOnCustomerFormActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminOpenNewCartPriceRuleFormPageActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCartPriceRuleFormActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenNewProductFormPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenNewProductFormPageActionGroup.xml new file mode 100644 index 0000000000000..fe859fab52667 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenNewProductFormPageActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenNewProductFormPageActionGroup"> + <arguments> + <argument name="productType" type="string" defaultValue="simple" /> + <argument name="attributeSetId" type="string" defaultValue="{{defaultAttributeSet.attribute_set_id}}" /> + </arguments> + + <amOnPage url="{{AdminProductCreatePage.url(attributeSetId, productType)}}" stepKey="openProductNewPage" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/AttributeSetData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/AttributeSetData.xml new file mode 100644 index 0000000000000..6e1b25fb9cdc4 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/AttributeSetData.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="defaultAttributeSet"> + <data key="attribute_set_id">4</data> + <data key="attribute_set_name">Default</data> + <data key="sort_order">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml index 697648cedb7ba..3ef78a3fe8f41 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml @@ -14,6 +14,7 @@ <element name="advancedPricingCloseButton" type="button" selector=".product_form_product_form_advanced_pricing_modal button.action-close" timeout="30"/> <element name="productTierPriceWebsiteSelect" type="select" selector="[name='product[tier_price][{{var1}}][website_id]']" parameterized="true"/> <element name="productTierPriceCustGroupSelect" type="select" selector="[name='product[tier_price][{{var1}}][cust_group]']" parameterized="true"/> + <element name="productTierPriceCustGroupSelectOptions" type="select" selector="[name='product[tier_price][{{var1}}][cust_group]'] option" parameterized="true"/> <element name="productTierPriceQtyInput" type="input" selector="[name='product[tier_price][{{var1}}][price_qty]']" parameterized="true"/> <element name="productTierPriceValueTypeSelect" type="select" selector="[name='product[tier_price][{{var1}}][value_type]']" parameterized="true"/> <element name="productTierPriceFixedPriceInput" type="input" selector="[name='product[tier_price][{{var1}}][price]']" parameterized="true"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminOpenNewCatalogPriceRuleFormPageActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminOpenNewCatalogPriceRuleFormPageActionGroup.xml new file mode 100644 index 0000000000000..072e8b24b0336 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminOpenNewCatalogPriceRuleFormPageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenNewCatalogPriceRuleFormPageActionGroup"> + <amOnPage url="{{CatalogRuleNewPage.url}}" stepKey="openNewCatalogPriceRulePage" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup.xml new file mode 100644 index 0000000000000..93a2a8a610951 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup"> + <arguments> + <argument name="customerGroup" type="entity" /> + </arguments> + <grabMultiple selector="{{AdminNewCatalogPriceRule.customerGroupsOptions}}" stepKey="customerGroups" /> + <assertNotContains stepKey="assertCustomerGroupNotInOptions"> + <actualResult type="variable">customerGroups</actualResult> + <expectedResult type="string">{{customerGroup.code}}</expectedResult> + </assertNotContains> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Page/CatalogRuleNewPage.xml b/app/code/Magento/CatalogRule/Test/Mftf/Page/CatalogRuleNewPage.xml new file mode 100644 index 0000000000000..ad3e40b37c5b0 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Page/CatalogRuleNewPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="CatalogRuleNewPage" url="catalog_rule/promo_catalog/new/" module="Magento_CatalogRule" area="admin"> + <section name="AdminNewCatalogPriceRule"/> + </page> +</pages> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml new file mode 100644 index 0000000000000..75223fcfc4c4b --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="DeleteCustomerGroupTest"> + <actionGroup ref="AdminOpenNewCatalogPriceRuleFormPageActionGroup" stepKey="openNewCatalogPriceRuleForm" /> + <actionGroup ref="AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup" stepKey="assertCustomerGroupNotOnCatalogPriceRuleForm"> + <argument name="customerGroup" value="$$customerGroup$$" /> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminOpenCustomerEditPageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminOpenCustomerEditPageActionGroup.xml new file mode 100644 index 0000000000000..8e6b56b19d674 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminOpenCustomerEditPageActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenCustomerEditPageActionGroup"> + <arguments> + <argument name="customerId" type="string" /> + </arguments> + <amOnPage url="{{AdminEditCustomerPage.url(customerId)}}" stepKey="openCustomerEditPage" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotInGridActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotInGridActionGroup.xml new file mode 100644 index 0000000000000..26c4f23fc9a77 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotInGridActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCustomerGroupNotInGridActionGroup"> + <arguments> + <argument name="customerGroup" type="entity" /> + </arguments> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="cleanFilters"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openFiltersSectionOnCustomerGroupIndexPage"/> + <fillField userInput="{{customerGroup.code}}" selector="{{AdminDataGridHeaderSection.filterFieldInput('customer_group_code')}}" stepKey="fillNameFieldOnFiltersSection"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickApplyFiltersButton"/> + <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnProductFormActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnProductFormActionGroup.xml new file mode 100644 index 0000000000000..94e01db5c1ff8 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnProductFormActionGroup.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCustomerGroupNotOnProductFormActionGroup"> + <arguments> + <argument name="customerGroup" type="entity" /> + </arguments> + <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickOnAdvancedPricingButton"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForCustomerGroupPriceAddButton"/> + <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="addCustomerGroupAllGroupsQty1PriceDiscountAnd10percent"/> + <grabMultiple selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelectOptions('0')}}" stepKey="customerGroups" /> + <assertNotContains stepKey="assertCustomerGroupNotInOptions"> + <actualResult type="variable">customerGroups</actualResult> + <expectedResult type="string">{{customerGroup.code}}</expectedResult> + </assertNotContains> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupOnCustomerFormActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupOnCustomerFormActionGroup.xml new file mode 100644 index 0000000000000..2c8e0081e5e90 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupOnCustomerFormActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCustomerGroupOnCustomerFormActionGroup"> + <arguments> + <argument name="customerGroup" type="entity" /> + </arguments> + <click selector="{{AdminCustomerAccountInformationSection.accountInformationTab}}" stepKey="clickOnAccountInfoTab" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + <seeOptionIsSelected userInput="{{customerGroup.code}}" selector="{{AdminCustomerAccountInformationSection.group}}" stepKey="verifyNeededCustomerGroupSelected" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index 06c23a2864984..f561e413a01f1 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -46,6 +46,19 @@ <data key="website_id">0</data> <requiredEntity type="address">US_Address_TX</requiredEntity> </entity> + <entity name="UsCustomerAssignedToNewCustomerGroup" type="customer"> + <var key="group_id" entityKey="id" entityType="customerGroup" /> + <data key="default_billing">true</data> + <data key="default_shipping">true</data> + <data key="email" unique="prefix">John.Doe@example.com</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="fullname">John Doe</data> + <data key="password">pwdTest123!</data> + <data key="store_id">0</data> + <data key="website_id">0</data> + <requiredEntity type="address">US_Address_TX</requiredEntity> + </entity> <entity name="Simple_US_Customer_Incorrect_Name" type="customer"> <data key="group_id">1</data> <data key="default_billing">true</data> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml index c7c40d8170f3b..a085a67167f60 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml @@ -8,93 +8,48 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="DeleteCustomerGroup"> + <test name="DeleteCustomerGroupTest"> <annotations> - <title value="Delete customer group group"/> + <title value="Delete customer group entity test"/> <description value="Delete a customer group"/> <stories value="Delete Customer Group"/> + <testCaseId value="MC-14590" /> <group value="customers"/> <group value="mtf_migrated"/> </annotations> <before> - <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + <createData entity="CustomCustomerGroup" stepKey="customerGroup" /> + <createData entity="UsCustomerAssignedToNewCustomerGroup" stepKey="customer"> + <requiredEntity createDataKey="customerGroup" /> + </createData> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <actionGroup ref="logout" stepKey="logout"/> </after> - <actionGroup ref="AdminCreateCustomerGroupActionGroup" stepKey="createCustomerGroup"> - <argument name="groupName" value="{{CustomerGroupChange.code}}"/> - <argument name="taxClass" value="{{CustomerGroupChange.tax_class_name}}"/> - </actionGroup> - <actionGroup ref="NavigateToAllCustomerPage" stepKey="navToCustomersCreate"/> - <actionGroup ref="AdminFilterCustomerByName" stepKey="filterCustomer"> - <argument name="customerName" value="{{Simple_US_Customer.fullname}}"/> - </actionGroup> - <actionGroup ref="AdminSelectCustomerByEmail" stepKey="selectCustomer"> - <argument name="customerEmail" value="$$createCustomer.email$$"/> - </actionGroup> - <actionGroup ref="SetCustomerGroupForSelectedCustomersViaGrid" stepKey="setCustomerGroup"> - <argument name="groupName" value="{{CustomerGroupChange.code}}"/> - </actionGroup> - <actionGroup ref="AdminFilterCustomerByName" stepKey="filterCustomerAfterGroupChange"> - <argument name="customerName" value="{{Simple_US_Customer.fullname}}"/> - </actionGroup> - <actionGroup ref="VerifyCustomerGroupForCustomer" stepKey="verifyCustomerGroupSet"> - <argument name="customerEmail" value="$$createCustomer.email$$"/> - <argument name="groupName" value="{{CustomerGroupChange.code}}"/> - </actionGroup> <!--Customer Group success delete message--> <actionGroup ref="AdminDeleteCustomerGroupActionGroup" stepKey="deleteCustomerGroup"> - <argument name="customerGroupName" value="{{CustomerGroupChange.code}}"/> + <argument name="customerGroupName" value="$$customerGroup.code$$"/> + </actionGroup> + <actionGroup ref="AssertCustomerGroupNotInGridActionGroup" stepKey="assertCustomerGroupNotInGrid"> + <argument name="customerGroup" value="$$customerGroup$$" /> </actionGroup> - <!--Customer Group is not in grid--> - <actionGroup ref="NavigateToCustomerGroupPage" stepKey="navToCustomerGroupPage"/> - - <!--Customer Group changed to "General" on customer form--> - <actionGroup ref="NavigateToAllCustomerPage" stepKey="navToCustomers"/> - <actionGroup ref="AdminFilterCustomerByName" stepKey="filterCustomerAfterGroupDelete"> - <argument name="customerName" value="{{Simple_US_Customer.fullname}}"/> + <actionGroup ref="AdminOpenCustomerEditPageActionGroup" stepKey="openCustomerEditPage"> + <argument name="customerId" value="$$customer.id$$" /> </actionGroup> - <actionGroup ref="AdminSelectCustomerByEmail" stepKey="selectCustomerAfterGroupDelete"> - <argument name="customerEmail" value="$$createCustomer.email$$"/> + + <actionGroup ref="AssertCustomerGroupOnCustomerFormActionGroup" stepKey="assertCustomerGroupOnCustomerForm"> + <argument name="customerGroup" value="GeneralCustomerGroup" /> </actionGroup> - <actionGroup ref="VerifyCustomerGroupForCustomer" stepKey="verifyGeneralGroupSet"> - <argument name="customerEmail" value="$$createCustomer.email$$"/> - <argument name="groupName" value="{{GeneralCustomerGroup.code}}"/> + + <actionGroup ref="AdminOpenNewProductFormPageActionGroup" stepKey="openNewProductForm" /> + + <actionGroup ref="AssertCustomerGroupNotOnProductFormActionGroup" stepKey="assertCustomerGroupNotOnProductForm"> + <argument name="customerGroup" value="$$customerGroup$$" /> </actionGroup> - - <!--Go to New Product page, add check custom customer group values--> - <amOnPage url="{{AdminProductCreatePage.url('4', 'simple')}}" stepKey="goToCreateSimpleProductPage"/> - <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickOnAdvancedPricingButton"/> - <waitForElement selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" - stepKey="waitForCustomerGroupPriceAddButton"/> - <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" - stepKey="addCustomerGroupAllGroupsQty1PriceDiscountAnd10percent"/> - <waitForElement selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" - stepKey="waitForSelectCustomerGroupNameAttribute2"/> - <dontSee selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" - userInput="{{CustomerGroupChange.code}}" - stepKey="seeProductTierPriceCustomerGroupInput"/> - - <!--Go to Catalog price rule page, add check custom customer group values--> - <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> - <waitForPageLoad stepKey="waitForPriceRulePage"/> - <click stepKey="addNewRule" selector="{{AdminGridMainControls.add}}"/> - <dontSee selector="{{AdminNewCatalogPriceRule.customerGroups}}" - userInput="{{CustomerGroupChange.code}}" - stepKey="dontSeeCatalogPriceRuleCustomerGroups"/> - - <!--Go to Cart price rule page, add check custom customer group values--> - <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> - <waitForPageLoad stepKey="waitForRulesPage"/> - <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> - <dontSee selector="{{AdminCartPriceRulesFormSection.customerGroups}}" - userInput="{{CustomerGroupChange.code}}" - stepKey="dontSeeCartPriceRuleCustomerGroups"/> </test> </tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminOpenNewCartPriceRuleFormPageActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminOpenNewCartPriceRuleFormPageActionGroup.xml new file mode 100644 index 0000000000000..8cb958c9d9304 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminOpenNewCartPriceRuleFormPageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenNewCartPriceRuleFormPageActionGroup"> + <amOnPage url="{{PriceRuleNewPage.url}}" stepKey="openNewCartPriceRulePage" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCartPriceRuleFormActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCartPriceRuleFormActionGroup.xml new file mode 100644 index 0000000000000..98a094aea77ac --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCartPriceRuleFormActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCustomerGroupNotOnCartPriceRuleFormActionGroup"> + <arguments> + <argument name="customerGroup" type="entity" /> + </arguments> + <grabMultiple selector="{{AdminCartPriceRulesFormSection.customerGroupsOptions}}" stepKey="customerGroups" /> + <assertNotContains stepKey="assertCustomerGroupNotInOptions"> + <actualResult type="variable">customerGroups</actualResult> + <expectedResult type="string">{{customerGroup.code}}</expectedResult> + </assertNotContains> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml index c8da82407457d..8af28a7fcb33e 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml @@ -18,6 +18,7 @@ <element name="ruleName" type="input" selector="input[name='name']"/> <element name="websites" type="multiselect" selector="select[name='website_ids']"/> <element name="customerGroups" type="multiselect" selector="select[name='customer_group_ids']"/> + <element name="customerGroupsOptions" type="multiselect" selector="select[name='customer_group_ids'] option"/> <element name="coupon" type="select" selector="select[name='coupon_type']"/> <element name="couponCode" type="input" selector="input[name='coupon_code']"/> <element name="useAutoGeneration" type="checkbox" selector="input[name='use_auto_generation']"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml new file mode 100644 index 0000000000000..77ee270b3bcaa --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="DeleteCustomerGroupTest"> + <actionGroup ref="AdminOpenNewCartPriceRuleFormPageActionGroup" stepKey="openNewCartPriceRuleForm" /> + <actionGroup ref="AssertCustomerGroupNotOnCartPriceRuleFormActionGroup" stepKey="assertCustomerGroupNotOnCartPriceRuleForm"> + <argument name="customerGroup" value="$$customerGroup$$" /> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.xml index cffbbca8ad5cb..4251a1c5ee9c5 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Customer\Test\TestCase\DeleteCustomerGroupEntityTest" summary="Delete Customer Group" ticketId="MAGETWO-25243"> <variation name="DeleteCustomerGroupEntityTestVariation1"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="customer/dataset" xsi:type="string">customer_with_new_customer_group</data> <data name="customer/data/group_id/dataset" xsi:type="string">default</data> <data name="defaultCustomerGroup/dataset" xsi:type="string">General</data> From 26412e9c5c3905b85bd3e94ea8aa82b0d172b529 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Sun, 21 Apr 2019 23:40:21 -0500 Subject: [PATCH 441/585] GraphQL-604: [Test coverage] End to tests for customer checkout workflow --- .../QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php | 3 +++ .../QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php | 2 ++ .../Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php index 142542e7b6aa5..481bad090dac1 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php @@ -47,6 +47,9 @@ public function __construct( } /** + * Create empty cart for customer + * + * @param int $customerId * @param string|null $predefinedMaskedQuoteId * @return string */ diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php index 99eef31e64a47..a6396ed6352ab 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php @@ -47,6 +47,8 @@ public function __construct( } /** + * Create empty cart for guest + * * @param string|null $predefinedMaskedQuoteId * @return string */ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php index 9a559eda6ee64..f020527d958e4 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php @@ -72,6 +72,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } /** + * Validate masked id + * * @param string $maskedId * @throws GraphQlAlreadyExistsException * @throws GraphQlInputException @@ -88,6 +90,8 @@ private function validateMaskedId(string $maskedId): void } /** + * Check is quote with such maskedId already exists + * * @param string $maskedId * @return bool */ From c4e4cbd105515d9207d5f802ae5ee32aa448babf Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Mon, 22 Apr 2019 12:37:37 +0300 Subject: [PATCH 442/585] magento/magento2#21787: Static test fix. --- app/code/Magento/Quote/Model/QuoteManagement.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php index a7a9bf4efde84..0ad99ffe759f6 100644 --- a/app/code/Magento/Quote/Model/QuoteManagement.php +++ b/app/code/Magento/Quote/Model/QuoteManagement.php @@ -299,6 +299,7 @@ public function assignCustomer($cartId, $customerId, $storeId) throw new StateException( __("The customer can't be assigned to the cart because the customer already has an active cart.") ); + // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { } @@ -653,12 +654,14 @@ private function rollbackAddresses( 'exception' => $e, ] ); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Exception $consecutiveException) { $message = sprintf( "An exception occurred on 'sales_model_service_quote_submit_failure' event: %s", $consecutiveException->getMessage() ); + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception($message, 0, $e); } } From 1a5cb909c6d92ef262afa85675647bc29c20cb49 Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Mon, 22 Apr 2019 14:50:14 +0300 Subject: [PATCH 443/585] MC-11925: Update Product from Mini Shopping Cart --- .../UpdateProductFromMiniShoppingCartEntityTest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.xml index b4c97a11b9145..4b99de09f2a7b 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.xml @@ -26,7 +26,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertCustomerIsRedirectedToCheckoutFromCart" /> </variation> <variation name="UpdateProductFromMiniShoppingCartEntityTestVariation2" summary="Update Configurable and verify previous product was updated to new one in shopping cart and mini shopping cart"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes, severity:S0</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, severity:S0</data> <data name="originalProduct/0" xsi:type="string">configurableProduct::default</data> <data name="checkoutData/dataset" xsi:type="string">configurable_update_mini_shopping_cart</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartItemsOptions" /> @@ -35,7 +35,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertProductOptionsAbsentInShoppingCart" /> </variation> <variation name="UpdateProductFromMiniShoppingCartEntityTestVariation3" summary="Update Bundle and verify previous product was updated to new one in shopping cart and mini shopping cart"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes, severity:S0</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, severity:S0</data> <data name="originalProduct/0" xsi:type="string">bundleProduct::bundle_fixed_product</data> <data name="checkoutData/dataset" xsi:type="string">bundle_update_mini_shopping_cart</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartItemsOptions" /> @@ -44,7 +44,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertProductOptionsAbsentInShoppingCart" /> </variation> <variation name="UpdateProductFromMiniShoppingCartEntityTestVariation4" summary="Update Downloadable and check previous link was updated to new one in shopping cart and mini shopping cart"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes, severity:S1</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, severity:S1</data> <data name="originalProduct/0" xsi:type="string">downloadableProduct::with_two_separately_links</data> <data name="checkoutData/dataset" xsi:type="string">downloadable_update_mini_shopping_cart</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartItemsOptions" /> @@ -53,7 +53,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertProductOptionsAbsentInShoppingCart" /> </variation> <variation name="UpdateProductFromMiniShoppingCartEntityTestVariation5" summary="Update Virtual product in mini shopping cart"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes, severity:S1</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, severity:S1</data> <data name="originalProduct/0" xsi:type="string">catalogProductVirtual::default</data> <data name="checkoutData/dataset" xsi:type="string">virtual_update_mini_shopping_cart</data> <constraint name="Magento\Checkout\Test\Constraint\AssertProductDataInMiniShoppingCart" /> From 24580ee3eb4c87cca94d73b9e377621750708234 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Mon, 22 Apr 2019 16:00:04 +0300 Subject: [PATCH 444/585] magento/magento2#22424: Static test fix. --- .../Magento/Catalog/Model/Product/Gallery/GalleryManagement.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php b/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php index 9e5cf084c25a1..c993e51c8bc09 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php @@ -71,8 +71,10 @@ public function create($sku, ProductAttributeMediaGalleryEntryInterface $entry) $product->setMediaGalleryEntries($existingMediaGalleryEntries); try { $product = $this->productRepository->save($product); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (InputException $inputException) { throw $inputException; + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Exception $e) { throw new StateException(__("The product can't be saved.")); } From 63c5db6ffeddefe8368e5ad7a2ba73b4dcba1afb Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 22 Apr 2019 16:02:53 +0300 Subject: [PATCH 445/585] MC-15406: [FT] [MFTF] StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest fails because of bad design --- .../Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml index f1e15aa5750dc..fda92810a13be 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml @@ -35,6 +35,13 @@ <remove keyForRemoval="seeSavedMessage"/> </actionGroup> + <!--Save the Store view--> + <actionGroup name="AdminCreateStoreViewActionSaveGroup"> + <waitForLoadingMaskToDisappear stepKey="waitForGridLoad"/> + <waitForElementVisible selector="{{AdminStoresGridSection.websiteFilterTextField}}" stepKey="waitForStoreGridToReload2"/> + <see userInput="You saved the store view." stepKey="seeSavedMessage" /> + </actionGroup> + <actionGroup name="navigateToAdminContentManagementPage"> <amOnPage url="{{AdminContentManagementPage.url}}" stepKey="navigateToConfigurationPage"/> <waitForPageLoad stepKey="waitForPageLoad1"/> @@ -58,4 +65,4 @@ <waitForElementVisible selector="{{errorMessageSelector}}" stepKey="waitForErrorMessage"/> <see selector="{{errorMessageSelector}}" userInput="{{errorMessage}}" stepKey="seeErrorMessage"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> From 27e048ff422c5d5b82b4b428ecabf4f1ac3622bf Mon Sep 17 00:00:00 2001 From: hiren pandya <hiren.pandya@krishtechnolabs.com> Date: Mon, 22 Apr 2019 18:52:15 +0530 Subject: [PATCH 446/585] Fixed issue of drop-down arrow direction in cart price rule --- app/design/adminhtml/Magento/backend/web/css/styles-old.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/web/css/styles-old.less b/app/design/adminhtml/Magento/backend/web/css/styles-old.less index 2dbe68ef96eec..c9e56abbba8d4 100644 --- a/app/design/adminhtml/Magento/backend/web/css/styles-old.less +++ b/app/design/adminhtml/Magento/backend/web/css/styles-old.less @@ -820,7 +820,7 @@ padding-right: 44px; - &:focus { + &:active { background-image+: url('../images/arrows-bg.svg'); background-position+: ~'calc(100% - 12px)' 13px; From dd7cb583b112f82ba58ef87d612631ac0eb1c57c Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Mon, 22 Apr 2019 08:38:54 -0500 Subject: [PATCH 447/585] MAGETWO-99307: Authorize.net Transaction Fails but Order goes through --- .../TransactionResponseValidator.php | 10 +++--- .../TransactionResponseValidatorTest.php | 35 +++++++++++++------ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/AuthorizenetAcceptjs/Gateway/Validator/TransactionResponseValidator.php b/app/code/Magento/AuthorizenetAcceptjs/Gateway/Validator/TransactionResponseValidator.php index 93b5f2bb62a7d..326f4fb29ac84 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/Gateway/Validator/TransactionResponseValidator.php +++ b/app/code/Magento/AuthorizenetAcceptjs/Gateway/Validator/TransactionResponseValidator.php @@ -54,7 +54,7 @@ public function validate(array $validationSubject): ResultInterface if (isset($transactionResponse['messages']['message']['code'])) { $errorCodes[] = $transactionResponse['messages']['message']['code']; $errorMessages[] = $transactionResponse['messages']['message']['text']; - } elseif ($transactionResponse['messages']['message']) { + } elseif (isset($transactionResponse['messages']['message'])) { foreach ($transactionResponse['messages']['message'] as $message) { $errorCodes[] = $message['code']; $errorMessages[] = $message['description']; @@ -62,7 +62,7 @@ public function validate(array $validationSubject): ResultInterface } elseif (isset($transactionResponse['errors'])) { foreach ($transactionResponse['errors'] as $message) { $errorCodes[] = $message['errorCode']; - $errorMessages[] = $message['errorCode']; + $errorMessages[] = $message['errorText']; } } @@ -85,8 +85,10 @@ private function isResponseCodeAnError(array $transactionResponse): bool ?? $transactionResponse['errors'][0]['errorCode'] ?? null; - return in_array($transactionResponse['responseCode'], [self::RESPONSE_CODE_APPROVED, self::RESPONSE_CODE_HELD]) - && $code + return !in_array($transactionResponse['responseCode'], [ + self::RESPONSE_CODE_APPROVED, self::RESPONSE_CODE_HELD + ]) + || $code && !in_array( $code, [ diff --git a/app/code/Magento/AuthorizenetAcceptjs/Test/Unit/Gateway/Validator/TransactionResponseValidatorTest.php b/app/code/Magento/AuthorizenetAcceptjs/Test/Unit/Gateway/Validator/TransactionResponseValidatorTest.php index cef7883bd5dbc..1188c9c4107d2 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/Test/Unit/Gateway/Validator/TransactionResponseValidatorTest.php +++ b/app/code/Magento/AuthorizenetAcceptjs/Test/Unit/Gateway/Validator/TransactionResponseValidatorTest.php @@ -19,9 +19,11 @@ class TransactionResponseValidatorTest extends TestCase { private const RESPONSE_CODE_APPROVED = 1; private const RESPONSE_CODE_HELD = 4; + private const RESPONSE_CODE_DENIED = 2; private const RESPONSE_REASON_CODE_APPROVED = 1; private const RESPONSE_REASON_CODE_PENDING_REVIEW_AUTHORIZED = 252; private const RESPONSE_REASON_CODE_PENDING_REVIEW = 253; + private const ERROR_CODE_AVS_MISMATCH = 27; /** * @var ResultInterfaceFactory|MockObject @@ -86,16 +88,6 @@ public function testValidateScenarios($transactionResponse, $isValid, $errorCode public function scenarioProvider() { return [ - // This validator only cares about successful edge cases so test for default behavior - [ - [ - 'responseCode' => 'foo', - ], - true, - [], - [] - ], - // Test for acceptable reason codes [ [ @@ -208,6 +200,29 @@ public function scenarioProvider() ['foo'], ['bar'] ], + [ + [ + 'responseCode' => self::RESPONSE_CODE_DENIED, + 'errors' => [ + [ + 'errorCode' => self::ERROR_CODE_AVS_MISMATCH, + 'errorText' => 'bar' + ] + ] + ], + false, + [self::ERROR_CODE_AVS_MISMATCH], + ['bar'] + ], + // This validator only cares about successful edge cases so test for default behavior + [ + [ + 'responseCode' => 'foo', + ], + false, + [], + [] + ], ]; } } From 8674fa400070f036ebaaa72557afaa5ca778f0c0 Mon Sep 17 00:00:00 2001 From: Iryna Lagno <ilagno@adobe.com> Date: Fri, 19 Apr 2019 14:01:45 -0500 Subject: [PATCH 448/585] MAGETWO-99210: Magento\Install\Test\TestCase\InstallTest is failing on php 7.1 -revert MQE-1352: bug fix in dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php --- .../lib/Magento/Mtf/Util/Command/File/Export/Reader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php index 79dd435ada7e6..d7336b51a18e2 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php @@ -74,7 +74,7 @@ private function getFiles() $serializedFiles = $this->transport->read(); $this->transport->close(); // phpcs:ignore Magento2.Security.InsecureFunction - return unserialize($serializedFiles); + return unserialize($serializedFiles, ['allowed_classes' => false]); } /** From c8569b54a7735c6c0f627aa6856d64e7f7405f25 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Mon, 22 Apr 2019 12:47:46 +0300 Subject: [PATCH 449/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Uskiped related integration test; --- .../integration/testsuite/Magento/Ups/Model/CarrierTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php b/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php index fe4067cdc49f5..b3ced0b84e27b 100644 --- a/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php +++ b/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php @@ -8,6 +8,9 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\Quote\Model\Quote\Address\RateRequestFactory; +/** + * Integration tests for Carrier model class + */ class CarrierTest extends \PHPUnit\Framework\TestCase { /** @@ -64,12 +67,12 @@ public function testGetShipConfirmUrlLive() /** * @magentoConfigFixture current_store carriers/ups/active 1 + * @magentoConfigFixture current_store carriers/ups/type UPS * @magentoConfigFixture current_store carriers/ups/allowed_methods 1DA,GND * @magentoConfigFixture current_store carriers/ups/free_method GND */ public function testCollectFreeRates() { - $this->markTestSkipped('Test is blocked by MAGETWO-97467.'); $rateRequest = Bootstrap::getObjectManager()->get(RateRequestFactory::class)->create(); $rateRequest->setDestCountryId('US'); $rateRequest->setDestRegionId('CA'); From 56ff6ac73308a66084ffe72b980680bba88f6d9d Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Mon, 22 Apr 2019 09:50:26 -0500 Subject: [PATCH 450/585] MC-15917: Create 'applyCouponToCart' and 'removeCouponFromCart' scenarios for benchmark --- setup/performance-toolkit/benchmark.jmx | 1157 +++++++++++++++++------ 1 file changed, 877 insertions(+), 280 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 55cdf7379cc5e..5521f7024722b 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -374,6 +374,11 @@ <stringProp name="Argument.value">${__P(graphqlAddSimpleProductToCartPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> + <elementProp name="graphqlApplyCouponToCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlApplyCouponToCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlApplyCouponToCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> <elementProp name="graphqlCatalogBrowsingByGuestPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlCatalogBrowsingByGuestPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlCatalogBrowsingByGuestPercentage,0)}</stringProp> @@ -449,6 +454,11 @@ <stringProp name="Argument.value">${__P(graphqlRemoveConfigurableProductFromCartPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> + <elementProp name="graphqlRemoveCouponFromCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlRemoveCouponFromCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlRemoveCouponFromCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> <elementProp name="graphqlRemoveSimpleProductFromCartPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlRemoveSimpleProductFromCartPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlRemoveSimpleProductFromCartPercentage,0)}</stringProp> @@ -41121,7 +41131,649 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Empty Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1901638450">{"data":{"cart":{"items":[]}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Billing Address On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_billing_address_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"BILLING"}}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Add Simple Product To Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlAddSimpleProductToCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "GraphQL Add Simple Product To Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addSimpleProductsToCart</stringProp> + <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Add Configurable Product To Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlAddConfigurableProductToCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "GraphQL Add Configurable Product To Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> + <stringProp name="VAR">product_option</stringProp> + <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> + <stringProp name="675049292">"sku":"${product_option}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Update Simple Product Qty In Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlUpdateSimpleProductQtyInCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "GraphQL Update Simple Product Qty In Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addSimpleProductsToCart</stringProp> + <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -41146,27 +41798,35 @@ vars.putObject("randomIntGenerator", random); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_empty_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1901638450">{"data":{"cart":{"items":[]}}}</stringProp> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">8</intProp> + <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Billing Address On Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41185,12 +41845,12 @@ vars.putObject("randomIntGenerator", random); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_billing_address_on_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_simple_product_qty_in_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"BILLING"}}}}}</stringProp> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -41201,11 +41861,11 @@ vars.putObject("randomIntGenerator", random); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Add Simple Product To Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Update Configurable Product Qty In Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlAddSimpleProductToCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlUpdateConfigurableProductQtyInCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -41226,7 +41886,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Add Simple Product To Cart"); + vars.put("testLabel", "GraphQL Update Configurable Product Qty In Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -41311,13 +41971,13 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; Random random = vars.getObject("randomIntGenerator"); -number = random.nextInt(props.get("simple_products_list").size()); -product = props.get("simple_products_list").get(number); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); vars.put("product_url_key", product.get("url_key")); vars.put("product_id", product.get("id")); @@ -41328,16 +41988,16 @@ vars.put("product_sku", product.get("sku")); <stringProp name="BeanShellSampler.filename"/> <stringProp name="BeanShellSampler.parameters"/> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41356,93 +42016,36 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1421843282">addSimpleProductsToCart</stringProp> - <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - </hashTree> - </hashTree> - - - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Add Configurable Product To Cart" enabled="true"> - <intProp name="ThroughputController.style">1</intProp> - <boolProp name="ThroughputController.perThread">false</boolProp> - <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlAddConfigurableProductToCartPercentage}</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> - <hashTree> - <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> - <stringProp name="script"> -var testLabel = "${testLabel}" ? " (${testLabel})" : ""; -if (testLabel - && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' -) { - if (sampler.getName().indexOf(testLabel) == -1) { - sampler.setName(sampler.getName() + testLabel); - } -} else if (sampler.getName().indexOf("SetUp - ") == -1) { - sampler.setName("SetUp - " + sampler.getName()); -} - </stringProp> - <stringProp name="scriptLanguage">javascript</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> - <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Add Configurable Product To Cart"); - </stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - </BeanShellSampler> - <hashTree/> - <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> - <collectionProp name="HeaderManager.headers"> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Content-Type</stringProp> - <stringProp name="Header.value">application/json</stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Accept</stringProp> - <stringProp name="Header.value">*/*</stringProp> - </elementProp> - </collectionProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> + <stringProp name="VAR">product_option</stringProp> + <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> <hashTree/> + </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> - <stringProp name="BeanShellSampler.query"> -import java.util.Random; - -Random random = new Random(); -if (${seedForRandom} > 0) { - random.setSeed(${seedForRandom} + ${__threadNum}); -} - -vars.putObject("randomIntGenerator", random); - </stringProp> - <stringProp name="BeanShellSampler.filename"/> - <stringProp name="BeanShellSampler.parameters"/> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - </BeanShellSampler> - <hashTree/> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41461,20 +42064,13 @@ vars.putObject("randomIntGenerator", random); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> - <stringProp name="VAR">quote_id</stringProp> - <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> + <stringProp name="675049292">"sku":"${product_option}"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -41483,33 +42079,13 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> - <stringProp name="BeanShellSampler.query"> -import java.util.Random; - -Random random = vars.getObject("randomIntGenerator"); -number = random.nextInt(props.get("configurable_products_list").size()); -product = props.get("configurable_products_list").get(number); - -vars.put("product_url_key", product.get("url_key")); -vars.put("product_id", product.get("id")); -vars.put("product_name", product.get("title")); -vars.put("product_uenc", product.get("uenc")); -vars.put("product_sku", product.get("sku")); - </stringProp> - <stringProp name="BeanShellSampler.filename"/> - <stringProp name="BeanShellSampler.parameters"/> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> - <hashTree/> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41528,36 +42104,35 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> - <stringProp name="VAR">product_option</stringProp> - <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - </hashTree> + </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41576,28 +42151,27 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_configurable_product_qty_in_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> - <stringProp name="675049292">"sku":"${product_option}"</stringProp> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">8</intProp> </ResponseAssertion> <hashTree/> </hashTree> </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Update Simple Product Qty In Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Simple Product From Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlUpdateSimpleProductQtyInCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveSimpleProductFromCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -41618,7 +42192,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Update Simple Product Qty In Cart"); + vars.put("testLabel", "GraphQL Remove Simple Product From Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -41810,13 +42384,13 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Simple Product From Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41835,12 +42409,12 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_simple_product_qty_in_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_simple_product_from_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -41851,11 +42425,11 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Update Configurable Product Qty In Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Configurable Product From Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlUpdateConfigurableProductQtyInCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveConfigurableProductFromCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -41876,7 +42450,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Update Configurable Product Qty In Cart"); + vars.put("testLabel", "GraphQL Remove Configurable Product From Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -42116,13 +42690,13 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Configurable Product From Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42141,12 +42715,12 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_configurable_product_qty_in_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_configurable_product_from_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -42157,11 +42731,11 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Simple Product From Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Apply Coupon To Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveSimpleProductFromCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlApplyCouponToCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -42182,7 +42756,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Remove Simple Product From Cart"); + vars.put("testLabel", "GraphQL Apply Coupon To Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -42327,60 +42901,29 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> + <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="SetUp - Prepare Coupon Code Data" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">random = vars.getObject("randomIntGenerator"); + +var coupons = props.get("coupon_codes"); +number = random.nextInt(coupons.length); + +vars.put("coupon_code", coupons[number].code); + </stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/extract_coupon_code_setup.jmx</stringProp> + </JSR223Sampler> + <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Simple Product From Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Apply Coupon To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n applyCouponToCart(input: {cart_id: \"${quote_id}\", coupon_code: \"${coupon_code}\"}) {\n cart {\n applied_coupon {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42399,12 +42942,12 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_simple_product_from_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/apply_coupon_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> + <stringProp name="1026466978">{"data":{"applyCouponToCart":{"cart":{"applied_coupon":{"code":"${coupon_code}"}}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -42415,11 +42958,11 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Configurable Product From Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Coupon From Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveConfigurableProductFromCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveCouponFromCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -42440,7 +42983,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Remove Configurable Product From Cart"); + vars.put("testLabel", "GraphQL Remove Coupon From Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -42525,13 +43068,13 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; Random random = vars.getObject("randomIntGenerator"); -number = random.nextInt(props.get("configurable_products_list").size()); -product = props.get("configurable_products_list").get(number); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); vars.put("product_url_key", product.get("url_key")); vars.put("product_id", product.get("id")); @@ -42542,64 +43085,16 @@ vars.put("product_sku", product.get("sku")); <stringProp name="BeanShellSampler.filename"/> <stringProp name="BeanShellSampler.parameters"/> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> - <hashTree/> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> - <stringProp name="VAR">product_option</stringProp> - <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> <hashTree/> - </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42618,13 +43113,13 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> - <stringProp name="675049292">"sku":"${product_option}"</stringProp> + <stringProp name="1421843282">addSimpleProductsToCart</stringProp> + <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -42633,13 +43128,29 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="SetUp - Prepare Coupon Code Data" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">random = vars.getObject("randomIntGenerator"); + +var coupons = props.get("coupon_codes"); +number = random.nextInt(coupons.length); + +vars.put("coupon_code", coupons[number].code); + </stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/extract_coupon_code_setup.jmx</stringProp> + </JSR223Sampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Apply Coupon To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n applyCouponToCart(input: {cart_id: \"${quote_id}\", coupon_code: \"${coupon_code}\"}) {\n cart {\n applied_coupon {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42658,35 +43169,27 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/apply_coupon_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + <stringProp name="1026466978">{"data":{"applyCouponToCart":{"cart":{"applied_coupon":{"code":"${coupon_code}"}}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">8</intProp> </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Configurable Product From Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Coupon From Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeCouponFromCart(input: {cart_id: \"${quote_id}\"}) {\n cart {\n applied_coupon {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42705,12 +43208,12 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_configurable_product_from_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_coupon_from_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> + <stringProp name="-76201335">{"data":{"removeCouponFromCart":{"cart":{"applied_coupon":null}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -43743,6 +44246,100 @@ vars.put("product_sku", product.get("sku")); </ResponseAssertion> <hashTree/> </hashTree> + + <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="SetUp - Prepare Coupon Code Data" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">random = vars.getObject("randomIntGenerator"); + +var coupons = props.get("coupon_codes"); +number = random.nextInt(coupons.length); + +vars.put("coupon_code", coupons[number].code); + </stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/extract_coupon_code_setup.jmx</stringProp> + </JSR223Sampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Apply Coupon To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n applyCouponToCart(input: {cart_id: \"${quote_id}\", coupon_code: \"${coupon_code}\"}) {\n cart {\n applied_coupon {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/apply_coupon_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1026466978">{"data":{"applyCouponToCart":{"cart":{"applied_coupon":{"code":"${coupon_code}"}}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Coupon From Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeCouponFromCart(input: {cart_id: \"${quote_id}\"}) {\n cart {\n applied_coupon {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_coupon_from_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-76201335">{"data":{"removeCouponFromCart":{"cart":{"applied_coupon":null}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> </hashTree> </hashTree> From d8131f6539a50b178783474405eba402d9ef8bdc Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 22 Apr 2019 10:52:32 -0500 Subject: [PATCH 451/585] GraphQL-598: CMS Page Integration Test for Tag Cache Generation - Add api-functional test --- .../GraphQl/PageCache/Cms/PageCacheTest.php | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/PageCacheTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/PageCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/PageCacheTest.php new file mode 100644 index 0000000000000..4939088f99d9a --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/PageCacheTest.php @@ -0,0 +1,155 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\PageCache\Cms; + +use Magento\Cms\Model\GetPageByIdentifier; +use Magento\Cms\Model\PageRepository; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test the caching works properly for CMS Pages + */ +class PageCacheTest extends GraphQlAbstract +{ + /** + * @var GetPageByIdentifier + */ + private $pageByIdentifier; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->markTestSkipped( + 'This test will stay skipped until DEVOPS-4924 is resolved' + ); + $this->pageByIdentifier = Bootstrap::getObjectManager()->get(GetPageByIdentifier::class); + } + + /** + * Test that X-Magento-Tags are correct + * + * @magentoApiDataFixture Magento/Cms/_files/pages.php + */ + public function testCacheTagsHaveExpectedValue() + { + $pageIdentifier = 'page100'; + $page = $this->pageByIdentifier->execute($pageIdentifier, 0); + $pageId = (int) $page->getId(); + + $query = $this->getPageQuery($pageId); + + //cache-debug should be a MISS on first request + $response = $this->graphQlQueryWithResponseHeaders($query); + + $this->assertArrayHasKey('X-Magento-Tags', $response['headers']); + $actualTags = explode(',', $response['headers']['X-Magento-Tags']); + $expectedTags = ["cms_p", "cms_p_{$pageId}", "FPC"]; + foreach ($expectedTags as $expectedTag) { + $this->assertContains($expectedTag, $actualTags); + } + } + + /** + * Test the second request for the same page will return a cached result + * + * @magentoApiDataFixture Magento/Cms/_files/pages.php + */ + public function testCacheIsUsedOnSecondRequest() + { + $pageIdentifier = 'page100'; + $page = $this->pageByIdentifier->execute($pageIdentifier, 0); + $pageId = (int) $page->getId(); + + $query = $this->getPageQuery($pageId); + + //cache-debug should be a MISS on first request + $responseMiss = $this->graphQlQueryWithResponseHeaders($query); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseMiss['headers']); + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); + + //cache-debug should be a HIT on second request + $responseHit = $this->graphQlQueryWithResponseHeaders($query); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseHit['headers']); + $this->assertEquals('HIT', $responseHit['headers']['X-Magento-Cache-Debug']); + //cached data should be correct + $this->assertNotEmpty($responseHit['body']); + $this->assertArrayNotHasKey('errors', $responseHit['body']); + $pageData = $responseHit['body']['cmsPage']; + $this->assertEquals('Cms Page 100', $pageData['title']); + } + + /** + * Test that cache is invalidated when page is updated + * + * @magentoApiDataFixture Magento/Cms/_files/pages.php + */ + public function testCacheIsInvalidatedOnPageUpdate() + { + $page100Identifier = 'page100'; + $page100 = $this->pageByIdentifier->execute($page100Identifier, 0); + $page100Id = (int) $page100->getId(); + $pageBlankIdentifier = 'page_design_blank'; + $pageBlank = $this->pageByIdentifier->execute($pageBlankIdentifier, 0); + $pageBlankId = (int) $pageBlank->getId(); + + $page100Query = $this->getPageQuery($page100Id); + $pageBlankQuery = $this->getPageQuery($pageBlankId); + + //cache-debug should be a MISS on first request + $page100Miss = $this->graphQlQueryWithResponseHeaders($page100Query); + $this->assertEquals('MISS', $page100Miss['headers']['X-Magento-Cache-Debug']); + $pageBlankMiss = $this->graphQlQueryWithResponseHeaders($pageBlankQuery); + $this->assertEquals('MISS', $pageBlankMiss['headers']['X-Magento-Cache-Debug']); + + //cache-debug should be a HIT on second request + $page100Hit = $this->graphQlQueryWithResponseHeaders($page100Query); + $this->assertEquals('HIT', $page100Hit['headers']['X-Magento-Cache-Debug']); + $pageBlankHit = $this->graphQlQueryWithResponseHeaders($pageBlankQuery); + $this->assertEquals('HIT', $pageBlankHit['headers']['X-Magento-Cache-Debug']); + + $pageRepository = Bootstrap::getObjectManager()->get(PageRepository::class); + $newPageContent = 'New page content for blank page.'; + $pageBlank->setContent($newPageContent); + $pageRepository->save($pageBlank); + + //cache-debug should be a MISS after updating the page + $pageBlankMiss = $this->graphQlQueryWithResponseHeaders($pageBlankQuery); + $this->assertEquals('MISS', $pageBlankMiss['headers']['X-Magento-Cache-Debug']); + $page100Hit = $this->graphQlQueryWithResponseHeaders($page100Query); + $this->assertEquals('HIT', $page100Hit['headers']['X-Magento-Cache-Debug']); + //updated page data should be correct + $this->assertNotEmpty($pageBlankMiss['body']); + $pageData = $pageBlankMiss['body']['cmsPage']; + $this->assertArrayNotHasKey('errors', $pageBlankMiss['body']); + $this->assertEquals('Cms Page Design Blank', $pageData['title']); + $this->assertEquals($newPageContent, $pageData['content']); + } + + /** + * Get page query + * + * @param int $pageId + * @return string + */ + private function getPageQuery(int $pageId): string + { + $query = <<<QUERY +{ + cmsPage(id: $pageId) { + title + url_key + content + } +} +QUERY; + return $query; + } +} From 49cca531132d07184ab65cff4ee64284ef703b21 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 22 Apr 2019 11:13:04 -0500 Subject: [PATCH 452/585] GraphQl-595: Category with Product (Integration Test for Tag Cache Generation) --- .../Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index bb358d32278cb..fc797b01658ec 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -10,7 +10,6 @@ use Magento\Cms\Model\GetPageByIdentifier; use Magento\Framework\App\Request\Http; use Magento\GraphQl\Controller\GraphQl; -use Magento\Framework\App\ResponseInterface; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; /** @@ -76,7 +75,6 @@ public function testToCheckCmsPageRequestCacheTags(): void $result = $this->graphqlController->dispatch($this->request); /** @var \Magento\Framework\App\Response\Http $response */ $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ $result->renderResult($response); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); From 59e1ff5eccdca5e0f2c9565231098645edb777fb Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 22 Apr 2019 11:13:04 -0500 Subject: [PATCH 453/585] GraphQl-595: Category with Product (Integration Test for Tag Cache Generation) --- .../Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index bb358d32278cb..fc797b01658ec 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -10,7 +10,6 @@ use Magento\Cms\Model\GetPageByIdentifier; use Magento\Framework\App\Request\Http; use Magento\GraphQl\Controller\GraphQl; -use Magento\Framework\App\ResponseInterface; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; /** @@ -76,7 +75,6 @@ public function testToCheckCmsPageRequestCacheTags(): void $result = $this->graphqlController->dispatch($this->request); /** @var \Magento\Framework\App\Response\Http $response */ $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ $result->renderResult($response); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); From 13606623917f8fa129823b9213472851788cdf49 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 22 Apr 2019 11:27:03 -0500 Subject: [PATCH 454/585] GraphQL-597: Test coverage for cart-not cached test --- .../Magento/GraphQl/PageCache/CacheTagTest.php | 2 +- .../GraphQl/PageCache/Quote/Guest/CartCacheTest.php | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php index e9ff8d93177ce..23bcd342ec994 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/CacheTagTest.php @@ -151,7 +151,7 @@ public function testCacheTagForCategoriesWithProduct() /** * Get Product query * - * @param string $productSku + * @param string $productSku * @return string */ private function getProductQuery(string $productSku): string diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php index 176fa0dff2f07..e09ee8bc969af 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php @@ -10,7 +10,7 @@ use Magento\TestFramework\TestCase\GraphQlAbstract; /** - * Test cart queries are note cached + * Test cart queries are not cached * * @magentoApiDataFixture Magento/Catalog/_files/products.php */ @@ -67,11 +67,11 @@ private function createEmptyCart(): string /** * Add simple product to the cart using the maskedQuoteId * - * @param $maskedCartId - * @param $qty - * @param $sku + * @param string $maskedCartId + * @param int $qty + * @param string $sku */ - private function addSimpleProductToCart($maskedCartId, $qty, $sku) + private function addSimpleProductToCart(string $maskedCartId, int $qty, string $sku): void { $addProductToCartQuery = <<<QUERY From bbf4bbcd9d742d93a38924457d208255629fe8b8 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Mon, 22 Apr 2019 11:27:56 -0500 Subject: [PATCH 455/585] Minor fixes for magento/magento-functional-tests-migration#638: Convert ValidateEmailOnCheckoutTest to MFTF --- ...ClickAddToCartOnProductPageActionGroup.xml | 14 +++++ ...tEmailNoteMessageOnCheckoutActionGroup.xml | 18 ++++++ ...ailTooltipContentOnCheckoutActionGroup.xml | 19 ++++++ ...ValidationMessageOnCheckoutActionGroup.xml | 18 ++++++ .../Mftf/ActionGroup/CheckoutActionGroup.xml | 2 +- ...ontFillEmailFieldOnCheckoutActionGroup.xml | 19 ++++++ .../StorefrontOpenCheckoutPageActionGroup.xml | 14 +++++ ...ntCheckoutCheckoutCustomerLoginSection.xml | 22 +++++++ .../StorefrontValidateEmailOnCheckoutTest.xml | 54 +++++++++++++++++ .../Mftf/Test/ValidateEmailOnCheckoutTest.xml | 59 ------------------- 10 files changed, 179 insertions(+), 60 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontClickAddToCartOnProductPageActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailNoteMessageOnCheckoutActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailTooltipContentOnCheckoutActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailValidationMessageOnCheckoutActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillEmailFieldOnCheckoutActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCheckoutPageActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontValidateEmailOnCheckoutTest.xml delete mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontClickAddToCartOnProductPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontClickAddToCartOnProductPageActionGroup.xml new file mode 100644 index 0000000000000..fb2065d228d5a --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontClickAddToCartOnProductPageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontClickAddToCartOnProductPageActionGroup"> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart" /> + <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccessMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailNoteMessageOnCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailNoteMessageOnCheckoutActionGroup.xml new file mode 100644 index 0000000000000..c4fc753e73713 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailNoteMessageOnCheckoutActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontEmailNoteMessageOnCheckoutActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="You can create an account after checkout." /> + </arguments> + <waitForElementVisible selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailNoteMessage}}" stepKey="waitForFormValidation"/> + <see selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailNoteMessage}}" userInput="{{message}}" stepKey="seeTheNoteMessageIsDisplayed"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailTooltipContentOnCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailTooltipContentOnCheckoutActionGroup.xml new file mode 100644 index 0000000000000..f9c6771262ccc --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailTooltipContentOnCheckoutActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontEmailTooltipContentOnCheckoutActionGroup"> + <arguments> + <argument name="content" type="string" defaultValue="We'll send your order confirmation here." /> + </arguments> + <waitForElementVisible selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailTooltipButton}}" stepKey="waitForTooltipButtonVisible" /> + <click selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailTooltipButton}}" stepKey="clickEmailTooltipButton" /> + <see selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailTooltipContent}}" userInput="{{content}}" stepKey="seeEmailTooltipContent" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailValidationMessageOnCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailValidationMessageOnCheckoutActionGroup.xml new file mode 100644 index 0000000000000..14b96ed46ce6b --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailValidationMessageOnCheckoutActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontEmailValidationMessageOnCheckoutActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="Please enter a valid email address (Ex: johndoe@domain.com)." /> + </arguments> + <waitForElementVisible selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailErrorMessage}}" stepKey="waitForFormValidation"/> + <see selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailErrorMessage}}" userInput="{{message}}" stepKey="seeTheErrorMessageIsDisplayed"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml index b67b7451d5968..94c6e3fd76972 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml @@ -110,7 +110,7 @@ <argument name="paymentMethod" type="string"/> </arguments> <remove keyForRemoval="checkMessage"/> - <dontsee selector="{{CheckoutPaymentSection.paymentMethodByName(paymentMethod)}}" parametrized="true" stepKey="paymentMethodDoesNotAvailable"/> + <dontSee selector="{{CheckoutPaymentSection.paymentMethodByName(paymentMethod)}}" stepKey="paymentMethodDoesNotAvailable"/> </actionGroup> <!-- Logged in user checkout filling shipping section --> <actionGroup name="LoggedInUserCheckoutFillingShippingSectionActionGroup"> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillEmailFieldOnCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillEmailFieldOnCheckoutActionGroup.xml new file mode 100644 index 0000000000000..fcac780a36776 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillEmailFieldOnCheckoutActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontFillEmailFieldOnCheckoutActionGroup"> + <arguments> + <argument name="email" type="string" /> + </arguments> + <fillField selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.email}}" userInput="{{email}}" stepKey="fillCustomerEmailField"/> + <doubleClick selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailTooltipButton}}" stepKey="clickToMoveFocusFromEmailInput" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCheckoutPageActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCheckoutPageActionGroup.xml new file mode 100644 index 0000000000000..b18d476c02c65 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCheckoutPageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontOpenCheckoutPageActionGroup"> + <amOnPage url="{{CheckoutPage.url}}" stepKey="openCheckoutPage" /> + <waitForPageLoad stepKey="waitForCheckoutPageLoaded" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml new file mode 100644 index 0000000000000..5a3c309c6a1d4 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontCheckoutCheckoutCustomerLoginSection"> + <element name="email" type="input" selector="form[data-role='email-with-possible-login'] input[name='username']" /> + <element name="emailNoteMessage" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[contains(@class, 'note')]" /> + <element name="emailErrorMessage" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[@id='customer-email-error']" /> + <element name="emailTooltipButton" type="button" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[contains(@class, 'action-help')]" /> + <element name="emailTooltipContent" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[contains(@class, 'field-tooltip-content')]" /> + <element name="password" type="input" selector="form[data-role='email-with-possible-login'] input[name='password']" /> + <element name="passwordNoteMessage" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='password']]//*[contains(@class, 'note')]" /> + <element name="submit" type="button" selector="form[data-role='email-with-possible-login'] button[type='submit']" /> + <element name="forgotPassword" type="button" selector="form[data-role='email-with-possible-login'] a.remind" /> + </section> +</sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontValidateEmailOnCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontValidateEmailOnCheckoutTest.xml new file mode 100644 index 0000000000000..1b27e1d53adad --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontValidateEmailOnCheckoutTest.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontValidateEmailOnCheckoutTest"> + <annotations> + <features value="Checkout"/> + <title value="Email validation for Guest on checkout flow"/> + <description value="Email validation for Guest on checkout flow"/> + <stories value="Guest Checkout"/> + <testCaseId value="MC-14695" /> + <group value="checkout"/> + <group value="shoppingCart"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <createData entity="SimpleTwo" stepKey="simpleProduct"/> + </before> + + <after> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + </after> + + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductStorefront"> + <argument name="productUrl" value="$$simpleProduct.custom_attributes[url_key]$$" /> + </actionGroup> + <actionGroup ref="StorefrontClickAddToCartOnProductPageActionGroup" stepKey="addToCartFromStorefrontProductPage" /> + + <actionGroup ref="StorefrontOpenCheckoutPageActionGroup" stepKey="openCheckoutPage" /> + <actionGroup ref="AssertStorefrontEmailTooltipContentOnCheckoutActionGroup" stepKey="assertEmailTooltipContent" /> + <actionGroup ref="AssertStorefrontEmailNoteMessageOnCheckoutActionGroup" stepKey="assertEmailNoteMessage" /> + + <actionGroup ref="StorefrontFillEmailFieldOnCheckoutActionGroup" stepKey="fillIncorrectEmailFirstAttempt"> + <argument name="email" value="John" /> + </actionGroup> + <actionGroup ref="AssertStorefrontEmailValidationMessageOnCheckoutActionGroup" stepKey="verifyValidationErrorMessageFirstAttempt" /> + + <actionGroup ref="StorefrontFillEmailFieldOnCheckoutActionGroup" stepKey="fillIncorrectEmailSecondAttempt"> + <argument name="email" value="johndoe#example.com" /> + </actionGroup> + <actionGroup ref="AssertStorefrontEmailValidationMessageOnCheckoutActionGroup" stepKey="verifyValidationErrorMessageSecondAttempt" /> + + <actionGroup ref="StorefrontFillEmailFieldOnCheckoutActionGroup" stepKey="fillIncorrectEmailThirdAttempt"> + <argument name="email" value="johndoe@example.c" /> + </actionGroup> + <actionGroup ref="AssertStorefrontEmailValidationMessageOnCheckoutActionGroup" stepKey="verifyValidationErrorMessageThirdAttempt" /> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml deleted file mode 100644 index e41573ffbfc64..0000000000000 --- a/app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml +++ /dev/null @@ -1,59 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="ValidateEmailOnCheckoutTest"> - <annotations> - <features value="Checkout"/> - <title value="Guest Checkout"/> - <description value="Email validation for Guest on checkout flow"/> - <stories value="Email validation for Guest on checkout flow"/> - <group value="shoppingCart"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <createData entity="SimpleTwo" stepKey="createSimpleProduct"/> - </before> - - <!--Go to product page--> - <amOnPage url="$$createSimpleProduct.custom_attributes[url_key]$$.html" stepKey="navigateToSimpleProductPage"/> - <waitForPageLoad stepKey="waitForCatalogPageLoad"/> - - <!--Add Product to Shopping Cart--> - <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addToCartFromStorefrontProductPage"> - <argument name="productName" value="$$createSimpleProduct.name$$"/> - </actionGroup> - - <!--Go to Checkout--> - <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask1"/> - - <!--Fill in the form fields for 1st variation, and check the validation message--> - <fillField selector="{{CheckoutShippingSection.email}}" userInput="johndoe" stepKey="setCustomerEmailVariation1"/> - <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="John" stepKey="SetCustomerFirstNameVariation1"/> - <waitForPageLoad stepKey="waitforFormValidation1"/> - <see userInput="Please enter a valid email address (Ex: johndoe@domain.com)." stepKey="seeTheErrorMessageIsDisplayed1"/> - - <!--Fill in the form fields for 2nd variation, and check the validation message--> - <fillField selector="{{CheckoutShippingSection.email}}" userInput="johndoe#example.com" stepKey="setCustomerEmailVariation2"/> - <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="John" stepKey="SetCustomerFirstNameVariation2"/> - <waitForPageLoad stepKey="waitForFormValidation2"/> - <see userInput="Please enter a valid email address (Ex: johndoe@domain.com)." stepKey="seeTheErrorMessageIsDisplayed2"/> - - <!--Fill in the form fields for 3rd variation, and check the validation message--> - <fillField selector="{{CheckoutShippingSection.email}}" userInput="johndoe@example.c" stepKey="setCustomerEmailVariation3"/> - <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="John" stepKey="SetCustomerFirstNameVariation3"/> - <waitForPageLoad stepKey="waitForFormValidation3"/> - <see userInput="Please enter a valid email address (Ex: johndoe@domain.com)." stepKey="seeTheErrorMessageIsDisplayed3"/> - - <after> - <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> - </after> - </test> -</tests> From 457fc5abba0fe7c2d9a1638fb6bb5907b5bb1616 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 22 Apr 2019 12:37:40 -0500 Subject: [PATCH 456/585] GraphQl-599: CMS Blocks (Integration Test for Tag Cache Generation) --- .../Magento/GraphQl/PageCache/Cms/BlockCacheTest.php | 6 ++---- .../Magento/GraphQl/PageCache/Cms/PageCacheTest.php | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php index 3e8c3e0c9b47e..5182ff791f576 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/BlockCacheTest.php @@ -45,10 +45,8 @@ public function testCacheTagsHaveExpectedValue() $this->assertArrayHasKey('X-Magento-Tags', $response['headers']); $actualTags = explode(',', $response['headers']['X-Magento-Tags']); - $expectedTags = ["cms_b", "cms_b_{$blockIdentifier}", "cms_b_{$blockId}", "FPC"]; - foreach ($expectedTags as $expectedTag) { - $this->assertContains($expectedTag, $actualTags); - } + $expectedTags = ["cms_b", "cms_b_{$blockId}", "cms_b_{$blockIdentifier}", "FPC"]; + $this->assertEquals($expectedTags, $actualTags); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/PageCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/PageCacheTest.php index 4939088f99d9a..34dc9eef4c339 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/PageCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Cms/PageCacheTest.php @@ -52,9 +52,7 @@ public function testCacheTagsHaveExpectedValue() $this->assertArrayHasKey('X-Magento-Tags', $response['headers']); $actualTags = explode(',', $response['headers']['X-Magento-Tags']); $expectedTags = ["cms_p", "cms_p_{$pageId}", "FPC"]; - foreach ($expectedTags as $expectedTag) { - $this->assertContains($expectedTag, $actualTags); - } + $this->assertEquals($expectedTags, $actualTags); } /** From 83059746ee107e86f8046d78890556311bbd00cf Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Mon, 22 Apr 2019 12:43:45 -0500 Subject: [PATCH 457/585] magento-engcom/magento2ce#2777: Fixed code style issues --- .../Model/Product/Gallery/CreateHandler.php | 2 ++ .../Entity/Collection/AbstractCollection.php | 20 ++++++++++--------- .../Model/Import/ProductTest.php | 1 + .../Magento/Framework/Data/Collection.php | 18 ++++++++--------- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php index d2ad6748a9f83..e06e85e90a2d8 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php @@ -230,6 +230,7 @@ public function getAttribute() * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @since 101.0.0 + * phpcs:disable Magento2.CodeAnalysis.EmptyBlock */ protected function processDeletedImages($product, array &$images) { @@ -400,6 +401,7 @@ protected function getUniqueFileName($file, $forTmp = false) $destinationFile = $forTmp ? $this->mediaDirectory->getAbsolutePath($this->mediaConfig->getTmpMediaPath($file)) : $this->mediaDirectory->getAbsolutePath($this->mediaConfig->getMediaPath($file)); + // phpcs:disable Magento2.Functions.DiscouragedFunction $destFile = dirname($file) . '/' . FileUploader::getNewFileName($destinationFile); } diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 9129015c99c55..52f106a0475f5 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -16,6 +16,7 @@ /** * Entity/Attribute/Model - collection abstract * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.TooManyFields) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) @@ -188,6 +189,7 @@ public function __construct( * Initialize collection * * @return void + * phpcs:disable Magento2.CodeAnalysis.EmptyBlock */ protected function _construct() { @@ -298,7 +300,7 @@ public function getResource() /** * Set template object for the collection * - * @param \Magento\Framework\DataObject $object + * @param \Magento\Framework\DataObject $object * @return $this */ public function setObject($object = null) @@ -1371,8 +1373,8 @@ protected function _getAttributeFieldName($attributeCode) /** * Add attribute value table to the join if it wasn't added previously * - * @param string $attributeCode - * @param string $joinType inner|left + * @param string $attributeCode + * @param string $joinType inner|left * @return $this * @throws LocalizedException * @SuppressWarnings(PHPMD.NPathComplexity) @@ -1466,12 +1468,12 @@ protected function getEntityPkName(\Magento\Eav\Model\Entity\AbstractEntity $ent /** * Adding join statement to collection select instance * - * @param string $method - * @param object $attribute - * @param string $tableAlias - * @param array $condition - * @param string $fieldCode - * @param string $fieldAlias + * @param string $method + * @param object $attribute + * @param string $tableAlias + * @param array $condition + * @param string $fieldCode + * @param string $fieldAlias * @return $this */ protected function _joinAttributeToSelect($method, $attribute, $tableAlias, $condition, $fieldCode, $fieldAlias) diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index ceffbc6d138e5..70c16e05712b9 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -568,6 +568,7 @@ public function testSaveDatetimeAttribute() */ protected function getExpectedOptionsData(string $pathToFile, string $storeCode = ''): array { + // phpcs:disable Magento2.Functions.DiscouragedFunction $productData = $this->csvToArray(file_get_contents($pathToFile)); $expectedOptionId = 0; $expectedOptions = []; diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index e0781a25de146..128d3d8e9fd3d 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -392,7 +392,7 @@ public function getItemByColumnValue($column, $value) /** * Adding item to item array * - * @param \Magento\Framework\DataObject $item + * @param \Magento\Framework\DataObject $item * @return $this * @throws \Exception */ @@ -454,7 +454,7 @@ public function getAllIds() /** * Remove item from collection by item key * - * @param mixed $key + * @param mixed $key * @return $this */ public function removeItemByKey($key) @@ -542,8 +542,8 @@ public function each($objMethod, $args = []) /** * Setting data for all collection items * - * @param mixed $key - * @param mixed $value + * @param mixed $key + * @param mixed $value * @return $this */ public function setDataToAll($key, $value = null) @@ -563,7 +563,7 @@ public function setDataToAll($key, $value = null) /** * Set current page * - * @param int $page + * @param int $page * @return $this */ public function setCurPage($page) @@ -575,7 +575,7 @@ public function setCurPage($page) /** * Set collection page size * - * @param int $size + * @param int $size * @return $this */ public function setPageSize($size) @@ -587,8 +587,8 @@ public function setPageSize($size) /** * Set select order * - * @param string $field - * @param string $direction + * @param string $field + * @param string $direction * @return $this */ public function setOrder($field, $direction = self::SORT_ORDER_DESC) @@ -600,7 +600,7 @@ public function setOrder($field, $direction = self::SORT_ORDER_DESC) /** * Set collection item class name * - * @param string $className + * @param string $className * @return $this * @throws \InvalidArgumentException */ From c018ba3fce2d1d9cc8cfc899f1e0c0eb2bb6291f Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 22 Apr 2019 12:44:08 -0500 Subject: [PATCH 458/585] GraphQl-599: CMS Blocks (Integration Test for Tag Cache Generation) --- .../Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php index 58e665c057f03..6e9d2ca0f491b 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php @@ -77,8 +77,6 @@ public function testCmsBlocksRequestHasCorrectTags(): void $expectedCacheTags = ['cms_b', 'cms_b_' . $block->getId(), 'cms_b_' . $block->getIdentifier(), 'FPC']; $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); $actualCacheTags = explode(',', $rawActualCacheTags); - foreach ($expectedCacheTags as $expectedCacheTag) { - $this->assertContains($expectedCacheTag, $actualCacheTags); - } + $this->assertEquals($expectedCacheTags, $actualCacheTags); } } From 9a82db00ccfb5085478b3195e4c0cff8b64cbc60 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Mon, 22 Apr 2019 13:07:34 -0500 Subject: [PATCH 459/585] GraphQL-600: Integration test for simple Products query - test for cache tag and cache debug headers - Fixed review comments --- .../GraphQlCache/Controller/Catalog/ProductsCacheTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php index d0b95b20656c6..ec55bfcb4928b 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php @@ -115,11 +115,10 @@ public function testToCheckRequestNoTagsForProducts(): void $result = $this->graphqlController->dispatch($this->request); /** @var \Magento\Framework\App\Response\Http $response */ $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ $result->renderResult($response); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); - $expectedCacheTags = [ 'FPC']; + $expectedCacheTags = ['FPC']; $this->assertEquals($expectedCacheTags, $actualCacheTags); } } From c295e5449fc87ca427f610dedce797360cb66778 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 22 Apr 2019 14:58:21 -0500 Subject: [PATCH 460/585] Issue-230: adding varnish - fixing messages --- .../Controller/HttpRequestValidator/CurrencyValidator.php | 4 ++-- .../Controller/HttpRequestValidator/StoreValidator.php | 2 +- .../Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php | 2 +- .../GraphQl/PageCache/ProductInMultipleStoresCacheTest.php | 6 +++--- .../Magento/GraphQl/Quote/Customer/GetCartTest.php | 2 +- .../testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php b/app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php index 6c0d4ec2e7be6..7dab90802c205 100644 --- a/app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php +++ b/app/code/Magento/DirectoryGraphQl/Controller/HttpRequestValidator/CurrencyValidator.php @@ -48,14 +48,14 @@ public function validate(HttpRequestInterface $request): void $currentStore = $this->storeManager->getStore(); if (!in_array($headerCurrency, $currentStore->getAvailableCurrencyCodes(true))) { throw new GraphQlInputException( - __('Currency not allowed for store %1', [$currentStore->getCode()]) + __('Please correct the target currency') ); } } } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { $this->storeManager->setCurrentStore(null); throw new GraphQlInputException( - __("The store that was requested wasn't found. Verify the store and try again.") + __("Requested store is not found") ); } } diff --git a/app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php b/app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php index afc84c061df44..144905d728141 100644 --- a/app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php +++ b/app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php @@ -48,7 +48,7 @@ public function validate(HttpRequestInterface $request): void if (strtolower($storeCode) !== 'default') { $this->storeManager->setCurrentStore(null); throw new GraphQlInputException( - __("The store that was requested wasn't found. Verify the store and try again.") + __("Requested store is not found") ); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php index d49eef8a887e7..d17b434f39d9f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductInMultipleStoresTest.php @@ -97,7 +97,7 @@ public function testProductFromSpecificAndDefaultStore() $nonExistingStoreCode = "non_existent_store"; $headerMapInvalidStoreCode = ['Store' => $nonExistingStoreCode]; $this->expectException(\Exception::class); - $this->expectExceptionMessage('The store that was requested wasn\'t found. Verify the store and try again.'); + $this->expectExceptionMessage('Requested store is not found'); $this->graphQlQuery($query, [], '', $headerMapInvalidStoreCode); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php index 12cd8894659b4..cf4cebdfe8e44 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/ProductInMultipleStoresCacheTest.php @@ -118,7 +118,7 @@ public function testProductFromSpecificAndDefaultStoreWithMultiCurrencyNonExisti //test non existing currency $headerMap = ['Store' => 'default', 'Content-Currency' => 'someNonExistentCurrency']; - $this->expectExceptionMessage('GraphQL response contains errors: Currency not allowed for store default'); + $this->expectExceptionMessage('GraphQL response contains errors: Please correct the target currency'); $this->graphQlQuery($query, [], '', $headerMap); } @@ -166,7 +166,7 @@ public function testProductFromSpecificAndDefaultStoreWithMultiCurrencyNotAllowe //test not allowed existing currency $headerMap = ['Store' => $storeCodeFromFixture, 'Content-Currency' => 'CAD']; $this->expectExceptionMessage( - "GraphQL response contains errors: Currency not allowed for store {$storeCodeFromFixture}" + 'GraphQL response contains errors: Please correct the target currency' ); $this->graphQlQuery($query, [], '', $headerMap); } @@ -315,7 +315,7 @@ public function testProductFromSpecificAndDefaultStoreWithMultiCurrency() // test cached response store + currency header with non existing currency, and no valid response, no cache $headerMap = ['Store' => $storeCodeFromFixture, 'Content-Currency' => 'SOMECURRENCY']; $this->expectExceptionMessage( - "GraphQL response contains errors: Currency not allowed for store {$storeCodeFromFixture}" + 'GraphQL response contains errors: Please correct the target currency' ); $this->graphQlQuery($query, [], '', $headerMap); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php index a19ad16cf60cc..60790aacb37b2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php @@ -163,7 +163,7 @@ public function testGetCartWithWrongStore() * @magentoApiDataFixture Magento/Checkout/_files/active_quote_customer_not_default_store.php * * @expectedException \Exception - * @expectedExceptionMessage The store that was requested wasn't found. Verify the store and try again. + * @expectedExceptionMessage Requested store is not found */ public function testGetCartWithNotExistingStore() { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php index 2678cf1be1540..8e4feb1d48e8c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php @@ -133,7 +133,7 @@ public function testGetCartWithWrongStore() * @magentoApiDataFixture Magento/Checkout/_files/active_quote_guest_not_default_store.php * * @expectedException \Exception - * @expectedExceptionMessage The store that was requested wasn't found. Verify the store and try again. + * @expectedExceptionMessage Requested store is not found */ public function testGetCartWithNotExistingStore() { From d7006f19794e27265e15ef87e022e98b9e01e63e Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 22 Apr 2019 15:03:03 -0500 Subject: [PATCH 461/585] Issue-230: adding varnish - removing new phrase because it's not allowed in a patch release --- app/code/Magento/Directory/i18n/en_US.csv | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Directory/i18n/en_US.csv b/app/code/Magento/Directory/i18n/en_US.csv index 79a99eb97fec3..3dcd2ceebf134 100644 --- a/app/code/Magento/Directory/i18n/en_US.csv +++ b/app/code/Magento/Directory/i18n/en_US.csv @@ -52,4 +52,3 @@ Service,Service "The """%1"" is not allowed as base currency for your subscription plan.","The """%1"" is not allowed as base currency for your subscription plan." "An invalid base currency has been entered.","An invalid base currency has been entered." "Currency rates can't be retrieved.","Currency rates can't be retrieved." -"Currency not allowed for store %1","Currency not allowed for store %1" \ No newline at end of file From 6e809c1f42bb612cb1450f56f62970a2420dd489 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Mon, 22 Apr 2019 15:09:08 -0500 Subject: [PATCH 462/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- dev/tests/integration/framework/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/framework/bootstrap.php b/dev/tests/integration/framework/bootstrap.php index 1cae393dc01c3..56cffaa0c8ea8 100644 --- a/dev/tests/integration/framework/bootstrap.php +++ b/dev/tests/integration/framework/bootstrap.php @@ -132,7 +132,7 @@ function ($errNo, $errStr, $errFile, $errLine) { $errName = isset($errorNames[$errNo]) ? $errorNames[$errNo] : ""; throw new \PHPUnit\Framework\Exception( - sprintf("%s: %s in %s:%s.", $errName, $errStr, $errFile, $errLine), + sprintf("%s: %s in %s:%s.\n\n%s\n\n", $errName, $errStr, $errFile, $errLine, debug_backtrace()), $errNo ); } From 47847759a72f77c7b51ff1df1d9ecd63357dacbd Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Mon, 22 Apr 2019 17:09:29 -0500 Subject: [PATCH 463/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- lib/internal/Magento/Framework/Session/SessionManager.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/internal/Magento/Framework/Session/SessionManager.php b/lib/internal/Magento/Framework/Session/SessionManager.php index c7d201676b228..db2c6ff47f390 100644 --- a/lib/internal/Magento/Framework/Session/SessionManager.php +++ b/lib/internal/Magento/Framework/Session/SessionManager.php @@ -165,6 +165,9 @@ public function __call($method, $args) sprintf('Invalid method %s::%s(%s)', get_class($this), $method, print_r($args, 1)) ); } + if (!($this->storage instanceof StorageInterface)) { + throw new \RuntimeException('Not storage'); + } $return = call_user_func_array([$this->storage, $method], $args); return $return === $this->storage ? $this : $return; } From 332c4b1af0c1d4123fb3a2e7957ec6111434c4ed Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Mon, 22 Apr 2019 20:46:50 -0500 Subject: [PATCH 464/585] Minor fixes for magento/magento-functional-tests-migration#382: Convert LockAdminUserWhenCreatingNewUserTest to MFTF - add test case id and move some files --- .../Mftf/Section/AdminLoginFormSection.xml | 1 - .../Test/Mftf/Section/AdminNewUserSection.xml | 23 ---- ...rInvalidCurrentUserPasswordActionGroup.xml | 35 ------ .../Security/Test/Mftf/Data/AdminUserData.xml | 18 --- .../AdminUserLockWhenCreatingNewUserTest.xml | 79 +++++++++++++ .../LockAdminUserWhenCreatingNewUserTest.xml | 110 ------------------ ...inClickSaveButtonOnUserFormActionGroup.xml | 14 +++ .../AdminCreateUserActionGroup.xml | 2 +- ...llNewUserFormRequiredFieldsActionGroup.xml | 31 +++++ .../AdminOpenNewUserPageActionGroup.xml | 14 +++ .../AssertAdminUserSaveMessageActionGroup.xml | 18 +++ .../Magento/User/Test/Mftf/Data/UserData.xml | 34 ++++++ .../Test/Mftf/Page/AdminNewUserPage.xml} | 5 +- .../Mftf/Section/AdminNewUserFormSection.xml | 30 +++++ .../Section/AdminUserFormMessagesSection.xml | 14 +++ 15 files changed, 238 insertions(+), 190 deletions(-) delete mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml delete mode 100644 app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml delete mode 100644 app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml create mode 100644 app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenCreatingNewUserTest.xml delete mode 100644 app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminClickSaveButtonOnUserFormActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillNewUserFormRequiredFieldsActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenNewUserPageActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminUserSaveMessageActionGroup.xml rename app/code/Magento/{Backend/Test/Mftf/Page/AdminAddNewUserPage.xml => User/Test/Mftf/Page/AdminNewUserPage.xml} (61%) create mode 100644 app/code/Magento/User/Test/Mftf/Section/AdminNewUserFormSection.xml create mode 100644 app/code/Magento/User/Test/Mftf/Section/AdminUserFormMessagesSection.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 9239784393d29..bd65dea89abc2 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -13,6 +13,5 @@ <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> <element name="forgotPasswordLink" type="button" selector=".action-forgotpassword" timeout="10"/> - <element name="error" type="text" selector=".message.message-error.error"/> </section> </sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml deleted file mode 100644 index a85229ad991d6..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="AdminNewUserSection"> - <element name="username" type="input" selector="#user_username"/> - <element name="firstname" type="input" selector="#user_firstname"/> - <element name="lastname" type="input" selector="#user_lastname"/> - <element name="email" type="input" selector="#user_email"/> - <element name="password" type="input" selector="#user_password"/> - <element name="confirmation" type="input" selector="#user_confirmation"/> - <element name="currentPassword" type="input" selector="#user_current_password"/> - <element name="save" type="button" selector="#save"/> - <element name="userRoleTab" type="button" selector="#page_tabs_roles_section"/> - <element name="administratorRole" type="radio" selector="//*[@id='permissionsUserRolesGrid_table']//td[{{role}}]/input" parameterized="true"/> - </section> -</sections> diff --git a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml deleted file mode 100644 index 0992dd23c76f4..0000000000000 --- a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminNewUserInvalidCurrentUserPasswordActionGroup"> - <arguments> - <argument name="adminUser" type="string" /> - <argument name="adminFirstname" type="string" /> - <argument name="adminLastname" type="string" /> - <argument name="adminEmail" type="string" /> - <argument name="adminPassword" type="string" /> - <argument name="adminPasswordConfirmation" type="string" /> - <argument name="currentAdminPassword" type="string" /> - <argument name="adminUserRole" type="string"/> - </arguments> - <!-- Fill in all data according to data set (current password is incorrect). --> - <fillField selector="{{AdminNewUserSection.username}}" userInput="{{adminUser}}" stepKey="fillUser"/> - <fillField selector="{{AdminNewUserSection.firstname}}" userInput="{{adminFirstname}}" stepKey="fillFirstName"/> - <fillField selector="{{AdminNewUserSection.lastname}}" userInput="{{adminLastname}}" stepKey="fillLastName"/> - <fillField selector="{{AdminNewUserSection.email}}" userInput="{{adminEmail}}" stepKey="fillEmail"/> - <fillField selector="{{AdminNewUserSection.password}}" userInput="{{adminPassword}}" stepKey="fillPassword"/> - <fillField selector="{{AdminNewUserSection.confirmation}}" userInput="{{adminPasswordConfirmation}}" stepKey="fillPasswordConfirmation"/> - <fillField selector="{{AdminNewUserSection.currentPassword}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> - <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> - <click selector="{{AdminNewUserSection.userRoleTab}}" stepKey="openUserRoleTab"/> - <click selector="{{adminUserRole}}" stepKey="assignRole"/> - <click selector="{{AdminNewUserSection.save}}" stepKey="saveNewUser"/> - <waitForPageLoad stepKey="waitForSaveResultLoad"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml b/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml deleted file mode 100644 index 1b3ec0ab351b9..0000000000000 --- a/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> - <entity name="AdminUserData" type="admin"> - <data key="email" unique="prefix">John.Doe@example.com</data> - <data key="firstname">John</data> - <data key="username" unique="prefix">lockuser</data> - <data key="lastname">Doe</data> - <data key="password">pwdTest123!</data> - </entity> -</entities> diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenCreatingNewUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenCreatingNewUserTest.xml new file mode 100644 index 0000000000000..4ceffd676313d --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenCreatingNewUserTest.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminUserLockWhenCreatingNewUserTest"> + <annotations> + <features value="Security"/> + <stories value="Runs Lock admin user when creating new user test."/> + <title value="Lock admin user when creating new user"/> + <description value="Runs Lock admin user when creating new user test."/> + <testCaseId value="MC-14383" /> + <severity value="CRITICAL"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Log in to Admin Panel --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!-- Unlock Admin user --> + <magentoCLI command="admin:user:unlock {{DefaultAdminUser.username}}" stepKey="unlockAdminUser"/> + </after> + + <!-- Open Admin New User Page --> + <actionGroup ref="AdminOpenNewUserPageActionGroup" stepKey="openNewUserPage" /> + + <!-- Perform add new admin user 6 specified number of times. + "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserFirstAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveFirstAttempt" /> + <actionGroup ref="AssertAdminUserSaveMessageActionGroup" stepKey="seeInvalidPasswordError"> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="messageType" value="error" /> + </actionGroup> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserSecondAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveSecondAttempt" /> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserThirdAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveThirdAttempt" /> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserFourthAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveFourthAttempt" /> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserFifthAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveFifthAttempt" /> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserSixthAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveSixthAttempt" /> + + <!-- Check Error that account has been locked --> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeLockUserErrorMessage"> + <argument name="message" value="Your account is temporarily disabled. Please try again later." /> + </actionGroup> + + <!-- Try to login as admin and check error --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeLoginUserErrorMessage" /> + </test> +</tests> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml deleted file mode 100644 index ec4dcd8dd0f6d..0000000000000 --- a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml +++ /dev/null @@ -1,110 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="LockAdminUserWhenCreatingNewUserTest"> - <annotations> - <features value="Security"/> - <stories value="Runs Lock admin user when creating new user test."/> - <title value="Lock admin user when creating new user"/> - <description value="Runs Lock admin user when creating new user test."/> - <severity value="MAJOR"/> - <group value="security"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <!-- Log in to Admin Panel --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - </before> - <after> - <!-- Unlock Admin user --> - <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> - </after> - - <!-- Open Admin New User Page --> - <amOnPage url="{{AdminAddNewUserPage.url}}" stepKey="amOnNewAdminUserPage"/> - <waitForPageLoad stepKey="waitForNewAdminUserPageLoad"/> - - <!-- Perform add new admin user 6 specified number of times. - "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFirstAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - <waitForPageLoad stepKey="waitForSaveResultLoad"/> - <see selector="{{AdminMessagesSection.error}}" userInput="The password entered for the current user is invalid. Verify the password and try again." - stepKey="seeInvalidPasswordError"/> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserSecondAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserThirdAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFourthAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFifthAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserSixthAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - - <!-- Check Error that account has been locked --> - <waitForPageLoad stepKey="wailtForSaveResultLoad"/> - <see selector="{{AdminLoginFormSection.error}}" userInput="Your account is temporarily disabled. Please try again later." stepKey="seeLockUserError"/> - - <!-- Try to login as admin and check error --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> - <waitForPageLoad stepKey="waitForError"/> - <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" - stepKey="seeLoginUserError"/> - </test> -</tests> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminClickSaveButtonOnUserFormActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminClickSaveButtonOnUserFormActionGroup.xml new file mode 100644 index 0000000000000..e1edb16aba6ea --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminClickSaveButtonOnUserFormActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminClickSaveButtonOnUserFormActionGroup"> + <click selector="{{AdminNewUserFormSection.save}}" stepKey="saveNewUser"/> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateUserActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateUserActionGroup.xml index 303713132d2b0..5d51dcc610f78 100644 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateUserActionGroup.xml +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateUserActionGroup.xml @@ -39,7 +39,7 @@ <argument name="role"/> <argument name="user" defaultValue="newAdmin"/> </arguments> - <amOnPage url="{{AdminEditUserPage.url}}" stepKey="navigateToNewUser"/> + <amOnPage url="{{AdminNewUserPage.url}}" stepKey="navigateToNewUser"/> <waitForPageLoad stepKey="waitForUsersPage" /> <fillField selector="{{AdminCreateUserSection.usernameTextField}}" userInput="{{user.username}}" stepKey="enterUserName" /> <fillField selector="{{AdminCreateUserSection.firstNameTextField}}" userInput="{{user.firstName}}" stepKey="enterFirstName" /> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillNewUserFormRequiredFieldsActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillNewUserFormRequiredFieldsActionGroup.xml new file mode 100644 index 0000000000000..87bf1e003931a --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillNewUserFormRequiredFieldsActionGroup.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminFillNewUserFormRequiredFieldsActionGroup"> + <arguments> + <argument name="user" type="entity" /> + </arguments> + <fillField selector="{{AdminNewUserFormSection.username}}" userInput="{{user.username}}" stepKey="fillUser"/> + <fillField selector="{{AdminNewUserFormSection.firstname}}" userInput="{{user.firstname}}" stepKey="fillFirstName"/> + <fillField selector="{{AdminNewUserFormSection.lastname}}" userInput="{{user.lastname}}" stepKey="fillLastName"/> + <fillField selector="{{AdminNewUserFormSection.email}}" userInput="{{user.email}}" stepKey="fillEmail"/> + <fillField selector="{{AdminNewUserFormSection.password}}" userInput="{{user.password}}" stepKey="fillPassword"/> + <fillField selector="{{AdminNewUserFormSection.passwordConfirmation}}" userInput="{{user.password_confirmation}}" stepKey="fillPasswordConfirmation"/> + <fillField selector="{{AdminNewUserFormSection.currentPassword}}" userInput="{{user.current_password}}" stepKey="fillCurrentUserPassword"/> + <scrollToTopOfPage stepKey="scrollToTopOfPage"/> + <click selector="{{AdminNewUserFormSection.userRoleTab}}" stepKey="openUserRoleTab"/> + <waitForPageLoad stepKey="waitForUserRoleTabOpened" /> + <click selector="{{AdminNewUserFormSection.resetFilter}}" stepKey="resetGridFilter" /> + <waitForPageLoad stepKey="waitForFiltersReset" /> + <fillField userInput="{{user.role}}" selector="{{AdminNewUserFormSection.roleFilterField}}" stepKey="fillRoleFilterField" /> + <click selector="{{AdminNewUserFormSection.search}}" stepKey="clickSearchButton" /> + <waitForPageLoad stepKey="waitForFiltersApplied" /> + <checkOption selector="{{AdminNewUserFormSection.roleRadiobutton(user.role)}}" stepKey="assignRole"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenNewUserPageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenNewUserPageActionGroup.xml new file mode 100644 index 0000000000000..67aef9379faa8 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenNewUserPageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenNewUserPageActionGroup"> + <amOnPage url="{{AdminNewUserPage.url}}" stepKey="amOnNewAdminUserPage"/> + <waitForPageLoad stepKey="waitForNewAdminUserPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminUserSaveMessageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminUserSaveMessageActionGroup.xml new file mode 100644 index 0000000000000..db4f0a89348a9 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminUserSaveMessageActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertAdminUserSaveMessageActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="You saved the user." /> + <argument name="messageType" type="string" defaultValue="success" /> + </arguments> + <waitForElementVisible selector="{{AdminUserFormMessagesSection.messageByType(messageType)}}" stepKey="waitForMessage" /> + <see userInput="{{message}}" selector="{{AdminUserFormMessagesSection.messageByType(messageType)}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/Data/UserData.xml b/app/code/Magento/User/Test/Mftf/Data/UserData.xml index d602f094ce4e5..e665736ae28f1 100644 --- a/app/code/Magento/User/Test/Mftf/Data/UserData.xml +++ b/app/code/Magento/User/Test/Mftf/Data/UserData.xml @@ -16,6 +16,40 @@ <data key="username" unique="suffix">username_</data> <data key="password" unique="suffix">password_</data> </entity> + <entity name="NewAdminUser" type="user"> + <data key="username" unique="suffix">admin</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="email" unique="prefix">admin@example.com</data> + <data key="password">123123q</data> + <data key="password_confirmation">123123q</data> + <data key="interface_local">en_US</data> + <data key="interface_local_label">English (United States)</data> + <data key="is_active">true</data> + <data key="is_active_label">Active</data> + <data key="current_password">{{_ENV.MAGENTO_ADMIN_PASSWORD}}</data> + <data key="role">Administrators</data> + <array key="roles"> + <item>1</item> + </array> + </entity> + <entity name="NewAdminUserWrongCurrentPassword" type="user"> + <data key="username" unique="suffix">admin</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="email" unique="prefix">admin@example.com</data> + <data key="password">123123q</data> + <data key="password_confirmation">123123q</data> + <data key="interface_local">en_US</data> + <data key="interface_local_label">English (United States)</data> + <data key="is_active">true</data> + <data key="is_active_label">Active</data> + <data key="current_password" unique="suffix">password_</data> + <data key="role">Administrators</data> + <array key="roles"> + <item>1</item> + </array> + </entity> <entity name="admin" type="user"> <data key="email">admin@magento.com</data> <data key="password">admin123</data> diff --git a/app/code/Magento/Backend/Test/Mftf/Page/AdminAddNewUserPage.xml b/app/code/Magento/User/Test/Mftf/Page/AdminNewUserPage.xml similarity index 61% rename from app/code/Magento/Backend/Test/Mftf/Page/AdminAddNewUserPage.xml rename to app/code/Magento/User/Test/Mftf/Page/AdminNewUserPage.xml index 4f7dc5539de6f..6de0945793447 100644 --- a/app/code/Magento/Backend/Test/Mftf/Page/AdminAddNewUserPage.xml +++ b/app/code/Magento/User/Test/Mftf/Page/AdminNewUserPage.xml @@ -8,7 +8,8 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> - <page name="AdminAddNewUserPage" url="admin/user/new" area="admin" module="Backend"> - <section name="AddNewAdminUserSection"/> + <page name="AdminNewUserPage" url="admin/user/new" area="admin" module="Magento_User"> + <section name="AdminNewUserFormSection" /> + <section name="AdminNewUserFormMessagesSection" /> </page> </pages> diff --git a/app/code/Magento/User/Test/Mftf/Section/AdminNewUserFormSection.xml b/app/code/Magento/User/Test/Mftf/Section/AdminNewUserFormSection.xml new file mode 100644 index 0000000000000..9b030b216ce2c --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/Section/AdminNewUserFormSection.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminNewUserFormSection"> + <element name="save" type="button" selector=".page-main-actions #save"/> + + <element name="userInfoTab" type="button" selector="#page_tabs_main_section"/> + <element name="username" type="input" selector="#page_tabs_main_section_content input[name='username']"/> + <element name="firstname" type="input" selector="#page_tabs_main_section_content input[name='firstname']"/> + <element name="lastname" type="input" selector="#page_tabs_main_section_content input[name='lastname']"/> + <element name="email" type="input" selector="#page_tabs_main_section_content input[name='email']"/> + <element name="password" type="input" selector="#page_tabs_main_section_content input[name='password']"/> + <element name="passwordConfirmation" type="input" selector="#page_tabs_main_section_content input[name='password_confirmation']"/> + <element name="interfaceLocale" type="select" selector="#page_tabs_main_section_content select[name='interface_locale']"/> + <element name="currentPassword" type="input" selector="#page_tabs_main_section_content input[name='current_password']"/> + + <element name="userRoleTab" type="button" selector="#page_tabs_roles_section"/> + <element name="search" type="button" selector="#page_tabs_roles_section_content #permissionsUserRolesGrid [data-action='grid-filter-apply']" /> + <element name="resetFilter" type="button" selector="#page_tabs_roles_section_content #permissionsUserRolesGrid [data-action='grid-filter-reset']" /> + <element name="roleFilterField" type="input" selector="#page_tabs_roles_section_content #permissionsUserRolesGrid input[name='role_name']" /> + <element name="roleRadiobutton" type="radio" selector="//table[@id='permissionsUserRolesGrid_table']//tr[./td[contains(@class, 'col-role_name') and contains(., '{{roleName}}')]]//input[@name='roles[]']" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/User/Test/Mftf/Section/AdminUserFormMessagesSection.xml b/app/code/Magento/User/Test/Mftf/Section/AdminUserFormMessagesSection.xml new file mode 100644 index 0000000000000..ec4f4d8bf3ad7 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/Section/AdminUserFormMessagesSection.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminUserFormMessagesSection"> + <element name="messageByType" type="block" selector="#messages .message-{{messageType}}" parameterized="true" /> + </section> +</sections> From 8a9a986f930cb5f8516b3fe5ecb6d1a6d3f9e8af Mon Sep 17 00:00:00 2001 From: Ruslan Kostiv <rkostiv@adobe.com> Date: Tue, 23 Apr 2019 00:26:38 -0500 Subject: [PATCH 465/585] MC-5681: Onepage Checkout improvements. --- .../BraintreeCreditCardOnCheckoutTest.xml | 2 +- .../Controller/Adminhtml/Product/Search.php | 5 +- .../Block/Checkout/LayoutProcessor.php | 6 + .../Checkout/Model/DefaultConfigProvider.php | 112 ++---------- .../Mftf/ActionGroup/CheckoutActionGroup.xml | 31 ++++ ...FillNewShippingAddressModalActionGroup.xml | 18 ++ ...playBillingAddressOnPaymentPageSection.xml | 14 ++ .../frontend/layout/checkout_index_index.xml | 2 +- .../web/js/action/create-billing-address.js | 13 +- .../web/js/model/checkout-data-resolver.js | 4 +- .../frontend/web/js/view/billing-address.js | 36 ++-- .../web/js/view/billing-address/list.js | 77 ++++++++ .../web/template/billing-address.html | 20 +-- .../web/template/billing-address/actions.html | 21 +++ .../web/template/billing-address/form.html | 2 +- .../view/frontend/web/template/shipping.html | 14 +- .../Address/CustomAttributesProcessor.php | 112 ++++++++++++ .../Address/CustomerAddressDataFormatter.php | 165 ++++++++++++++++++ .../Address/CustomerAddressDataProvider.php | 64 +++++++ .../Test/Mftf/Data/ConfigData.xml | 33 ++++ .../base/web/js/form/element/ui-select.js | 80 ++++++--- app/code/Magento/Wishlist/Helper/Data.php | 8 +- .../Rule/Design/CookieAndSessionMisuse.php | 15 ++ 23 files changed, 672 insertions(+), 182 deletions(-) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillNewShippingAddressModalActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.xml create mode 100644 app/code/Magento/Checkout/view/frontend/web/js/view/billing-address/list.js create mode 100644 app/code/Magento/Checkout/view/frontend/web/template/billing-address/actions.html create mode 100644 app/code/Magento/Customer/Model/Address/CustomAttributesProcessor.php create mode 100644 app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php create mode 100644 app/code/Magento/Customer/Model/Address/CustomerAddressDataProvider.php create mode 100644 app/code/Magento/OfflinePayments/Test/Mftf/Data/ConfigData.xml diff --git a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml index f066c88b12fcc..a781841e0a77b 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml @@ -81,7 +81,7 @@ <actionGroup ref="LoggedInCheckoutFillNewBillingAddressActionGroup" stepKey="LoggedInCheckoutFillNewBillingAddressActionGroup1"> <argument name="Address" value="US_Address_NY"/> </actionGroup> - <click selector="{{CheckoutPaymentSection.addressAction('Save Address')}}" stepKey="SaveAddress"/> + <click selector="{{CheckoutPaymentSection.addressAction('Ship here')}}" stepKey="SaveAddress"/> <waitForPageLoad stepKey="waitForPageLoad9"/> <click selector="{{CheckoutShippingSection.next}}" stepKey="clickNext1"/> <waitForPageLoad stepKey="waitForPageLoad10"/> diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Search.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Search.php index c7c71b2f56026..316983298a1b9 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Search.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Search.php @@ -9,11 +9,12 @@ namespace Magento\Catalog\Controller\Adminhtml\Product; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\App\Action\HttpGetActionInterface; /** * Controller to search product for ui-select component */ -class Search extends \Magento\Backend\App\Action +class Search extends \Magento\Backend\App\Action implements HttpGetActionInterface { /** * Authorization level of a basic admin session @@ -48,6 +49,8 @@ public function __construct( } /** + * Execute product search. + * * @return \Magento\Framework\Controller\ResultInterface */ public function execute() : \Magento\Framework\Controller\ResultInterface diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php index 3f6f638db5b82..5d02dd636825b 100644 --- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php @@ -287,8 +287,14 @@ private function getBillingAddressComponent($paymentCode, $elements) 'provider' => 'checkoutProvider', 'deps' => 'checkoutProvider', 'dataScopePrefix' => 'billingAddress' . $paymentCode, + 'billingAddressListProvider' => '${$.name}.billingAddressList', 'sortOrder' => 1, 'children' => [ + 'billingAddressList' => [ + 'component' => 'Magento_Checkout/js/view/billing-address/list', + 'displayArea' => 'billing-address-list', + 'template' => 'Magento_Checkout/billing-address/list' + ], 'form-fields' => [ 'component' => 'uiComponent', 'displayArea' => 'additional-fieldsets', diff --git a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php index f30bd73deeae2..c2c049d2bf99f 100644 --- a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php +++ b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php @@ -10,6 +10,7 @@ use Magento\Checkout\Model\Session as CheckoutSession; use Magento\Customer\Api\AddressMetadataInterface; use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository; +use Magento\Customer\Model\Address\CustomerAddressDataProvider; use Magento\Customer\Model\Context as CustomerContext; use Magento\Customer\Model\Session as CustomerSession; use Magento\Customer\Model\Url as CustomerUrlManager; @@ -177,6 +178,11 @@ class DefaultConfigProvider implements ConfigProviderInterface */ private $addressMetadata; + /** + * @var CustomerAddressDataProvider + */ + private $customerAddressData; + /** * @param CheckoutHelper $checkoutHelper * @param Session $checkoutSession @@ -206,6 +212,7 @@ class DefaultConfigProvider implements ConfigProviderInterface * @param UrlInterface $urlBuilder * @param AddressMetadataInterface $addressMetadata * @param AttributeOptionManagementInterface $attributeOptionManager + * @param CustomerAddressDataProvider|null $customerAddressData * @codeCoverageIgnore * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -237,7 +244,8 @@ public function __construct( \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement, UrlInterface $urlBuilder, AddressMetadataInterface $addressMetadata = null, - AttributeOptionManagementInterface $attributeOptionManager = null + AttributeOptionManagementInterface $attributeOptionManager = null, + CustomerAddressDataProvider $customerAddressData = null ) { $this->checkoutHelper = $checkoutHelper; $this->checkoutSession = $checkoutSession; @@ -268,6 +276,8 @@ public function __construct( $this->addressMetadata = $addressMetadata ?: ObjectManager::getInstance()->get(AddressMetadataInterface::class); $this->attributeOptionManager = $attributeOptionManager ?? ObjectManager::getInstance()->get(AttributeOptionManagementInterface::class); + $this->customerAddressData = $customerAddressData ?: + ObjectManager::getInstance()->get(CustomerAddressDataProvider::class); } /** @@ -359,57 +369,18 @@ private function isAutocompleteEnabled() * * @return array */ - private function getCustomerData() + private function getCustomerData(): array { $customerData = []; if ($this->isCustomerLoggedIn()) { + /** @var \Magento\Customer\Api\Data\CustomerInterface $customer */ $customer = $this->customerRepository->getById($this->customerSession->getCustomerId()); $customerData = $customer->__toArray(); - foreach ($customer->getAddresses() as $key => $address) { - $customerData['addresses'][$key]['inline'] = $this->getCustomerAddressInline($address); - if ($address->getCustomAttributes()) { - $customerData['addresses'][$key]['custom_attributes'] = $this->filterNotVisibleAttributes( - $customerData['addresses'][$key]['custom_attributes'] - ); - } - } + $customerData['addresses'] = $this->customerAddressData->getAddressDataByCustomer($customer); } return $customerData; } - /** - * Filter not visible on storefront custom attributes. - * - * @param array $attributes - * @return array - */ - private function filterNotVisibleAttributes(array $attributes) - { - $attributesMetadata = $this->addressMetadata->getAllAttributesMetadata(); - foreach ($attributesMetadata as $attributeMetadata) { - if (!$attributeMetadata->isVisible()) { - unset($attributes[$attributeMetadata->getAttributeCode()]); - } - } - - return $this->setLabelsToAttributes($attributes); - } - - /** - * Set additional customer address data - * - * @param \Magento\Customer\Api\Data\AddressInterface $address - * @return string - */ - private function getCustomerAddressInline($address) - { - $builtOutputAddressData = $this->addressMapper->toFlatArray($address); - return $this->addressConfig - ->getFormatByCode(\Magento\Customer\Model\Address\Config::DEFAULT_ADDRESS_FORMAT) - ->getRenderer() - ->renderArray($builtOutputAddressData); - } - /** * Retrieve quote data * @@ -726,61 +697,6 @@ private function getPaymentMethods() return $paymentMethods; } - /** - * Set Labels to custom Attributes - * - * @param array $customAttributes - * @return array $customAttributes - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Exception\StateException - */ - private function setLabelsToAttributes(array $customAttributes) : array - { - if (!empty($customAttributes)) { - foreach ($customAttributes as $customAttributeCode => $customAttribute) { - $attributeOptionLabels = $this->getAttributeLabels($customAttribute, $customAttributeCode); - if (!empty($attributeOptionLabels)) { - $customAttributes[$customAttributeCode]['label'] = implode(', ', $attributeOptionLabels); - } - } - } - - return $customAttributes; - } - - /** - * Get Labels by CustomAttribute and CustomAttributeCode - * - * @param array $customAttribute - * @param string|integer $customAttributeCode - * @return array $attributeOptionLabels - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Exception\StateException - */ - private function getAttributeLabels(array $customAttribute, string $customAttributeCode) : array - { - $attributeOptionLabels = []; - - if (!empty($customAttribute['value'])) { - $customAttributeValues = explode(',', $customAttribute['value']); - $attributeOptions = $this->attributeOptionManager->getItems( - \Magento\Customer\Model\Indexer\Address\AttributeProvider::ENTITY, - $customAttributeCode - ); - - if (!empty($attributeOptions)) { - foreach ($attributeOptions as $attributeOption) { - $attributeOptionValue = $attributeOption->getValue(); - if (in_array($attributeOptionValue, $customAttributeValues)) { - $attributeOptionLabels[] = $attributeOption->getLabel() ?? $attributeOptionValue; - } - } - } - } - - return $attributeOptionLabels; - } - /** * Get notification messages for the quote items * diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml index b67b7451d5968..93179a90a7aa1 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml @@ -241,6 +241,21 @@ <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskAfterPaymentMethodSelection"/> </actionGroup> + <!-- Check selected shipping address information on shipping information step --> + <actionGroup name="CheckSelectedShippingAddressInCheckoutActionGroup"> + <arguments> + <argument name="customerVar"/> + <argument name="customerAddressVar"/> + </arguments> + <waitForElement selector="{{CheckoutShippingSection.shippingTab}}" time="30" stepKey="waitForShippingSectionLoaded"/> + <see stepKey="VerifyFirstNameInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerVar.firstname}}" /> + <see stepKey="VerifyLastNameInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerVar.lastname}}" /> + <see stepKey="VerifyStreetInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerAddressVar.street[0]}}" /> + <see stepKey="VerifyCityInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerAddressVar.city}}" /> + <see stepKey="VerifyZipInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerAddressVar.postcode}}" /> + <see stepKey="VerifyPhoneInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerAddressVar.telephone}}" /> + </actionGroup> + <!-- Check billing address in checkout --> <actionGroup name="CheckBillingAddressInCheckoutActionGroup"> <arguments> @@ -257,6 +272,22 @@ <see userInput="{{customerAddressVar.telephone}}" selector="{{CheckoutPaymentSection.billingAddress}}" stepKey="assertBillingAddressTelephone"/> </actionGroup> + <!-- Check billing address in checkout with billing address on payment page --> + <actionGroup name="CheckBillingAddressInCheckoutWithBillingAddressOnPaymentPageActionGroup"> + <arguments> + <argument name="customerVar"/> + <argument name="customerAddressVar"/> + </arguments> + <waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" time="30" stepKey="waitForPaymentSectionLoaded"/> + <see userInput="{{customerVar.firstName}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsFirstName"/> + <see userInput="{{customerVar.lastName}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsLastName"/> + <see userInput="{{customerAddressVar.street[0]}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsStreet"/> + <see userInput="{{customerAddressVar.city}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsCity"/> + <see userInput="{{customerAddressVar.state}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsState"/> + <see userInput="{{customerAddressVar.postcode}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsPostcode"/> + <see userInput="{{customerAddressVar.telephone}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsTelephone"/> + </actionGroup> + <!-- Checkout place order --> <actionGroup name="CheckoutPlaceOrderActionGroup"> <arguments> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillNewShippingAddressModalActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillNewShippingAddressModalActionGroup.xml new file mode 100644 index 0000000000000..7035855cc0ed3 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillNewShippingAddressModalActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="FillNewShippingAddressModalActionGroup" extends="FillShippingAddressOneStreetActionGroup"> + <arguments> + <argument name="address"/> + </arguments> + <selectOption stepKey="selectRegion" selector="{{CheckoutShippingSection.region}}" + userInput="{{address.state}}" after="fillCityName"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.xml new file mode 100644 index 0000000000000..42decd8d43220 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection"> + <element name="billingAddressDetails" type="text" selector="div.billing-address-details"/> + </section> +</sections> diff --git a/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml index 64b70e80bd84f..a305413bcf1f3 100644 --- a/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml @@ -105,7 +105,7 @@ <item name="trigger" xsi:type="string">opc-new-shipping-address</item> <item name="buttons" xsi:type="array"> <item name="save" xsi:type="array"> - <item name="text" xsi:type="string" translate="true">Save Address</item> + <item name="text" xsi:type="string" translate="true">Ship here</item> <item name="class" xsi:type="string">action primary action-save-address</item> </item> <item name="cancel" xsi:type="array"> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js index 7db0dc5ce7473..c601bb8acf125 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js @@ -12,6 +12,17 @@ define([ 'use strict'; return function (addressData) { - return addressConverter.formAddressDataToQuoteAddress(addressData); + var address = addressConverter.formAddressDataToQuoteAddress(addressData); + + /** + * Returns new customer billing address type. + * + * @returns {String} + */ + address.getType = function () { + return 'new-customer-billing-address'; + }; + + return address; }; }); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js b/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js index e54f464f24d02..bc0ab59b622a2 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js @@ -216,11 +216,11 @@ define([ newCustomerBillingAddressData = checkoutData.getNewCustomerBillingAddress(); if (selectedBillingAddress) { - if (selectedBillingAddress == 'new-customer-address' && newCustomerBillingAddressData) { //eslint-disable-line + if (selectedBillingAddress === 'new-customer-billing-address' && newCustomerBillingAddressData) { selectBillingAddress(createBillingAddress(newCustomerBillingAddressData)); } else { addressList.some(function (address) { - if (selectedBillingAddress == address.getKey()) { //eslint-disable-line eqeqeq + if (selectedBillingAddress === address.getKey()) { selectBillingAddress(address); } }); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index d68b0682eb511..a552aa01da061 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -40,30 +40,23 @@ function ( 'use strict'; var lastSelectedBillingAddress = null, - newAddressOption = { - /** - * Get new address label - * @returns {String} - */ - getAddressInline: function () { - return $t('New Address'); - }, - customerAddressId: null - }, countryData = customerData.get('directory-data'), addressOptions = addressList().filter(function (address) { - return address.getType() == 'customer-address'; //eslint-disable-line eqeqeq + return address.getType() === 'customer-address'; }); - addressOptions.push(newAddressOption); - return Component.extend({ defaults: { - template: 'Magento_Checkout/billing-address' + template: 'Magento_Checkout/billing-address', + actionsTemplate: 'Magento_Checkout/billing-address/actions', + formTemplate: 'Magento_Checkout/billing-address/form', + detailsTemplate: 'Magento_Checkout/billing-address/details', + links: { + isAddressFormVisible: '${$.billingAddressListProvider}:isNewAddressSelected' + } }, currentBillingAddress: quote.billingAddress, - addressOptions: addressOptions, - customerHasAddresses: addressOptions.length > 1, + customerHasAddresses: addressOptions.length > 0, /** * Init component @@ -84,7 +77,7 @@ function ( .observe({ selectedAddress: null, isAddressDetailsVisible: quote.billingAddress() != null, - isAddressFormVisible: !customer.isLoggedIn() || addressOptions.length === 1, + isAddressFormVisible: !customer.isLoggedIn() || !addressOptions.length, isAddressSameAsShipping: false, saveInAddressBook: 1 }); @@ -147,7 +140,7 @@ function ( updateAddress: function () { var addressData, newBillingAddress; - if (this.selectedAddress() && this.selectedAddress() != newAddressOption) { //eslint-disable-line eqeqeq + if (this.selectedAddress() && !this.isAddressFormVisible()) { selectBillingAddress(this.selectedAddress()); checkoutData.setSelectedBillingAddress(this.selectedAddress().getKey()); } else { @@ -218,13 +211,6 @@ function ( } }, - /** - * @param {Object} address - */ - onAddressChange: function (address) { - this.isAddressFormVisible(address == newAddressOption); //eslint-disable-line eqeqeq - }, - /** * @param {Number} countryId * @return {*} diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address/list.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address/list.js new file mode 100644 index 0000000000000..ca3a267c01671 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address/list.js @@ -0,0 +1,77 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'uiComponent', + 'Magento_Customer/js/model/address-list', + 'mage/translate', + 'Magento_Customer/js/model/customer' +], function (Component, addressList, $t, customer) { + 'use strict'; + + var newAddressOption = { + /** + * Get new address label + * @returns {String} + */ + getAddressInline: function () { + return $t('New Address'); + }, + customerAddressId: null + }, + addressOptions = addressList().filter(function (address) { + return address.getType() === 'customer-address'; + }); + + return Component.extend({ + defaults: { + template: 'Magento_Checkout/billing-address', + selectedAddress: null, + isNewAddressSelected: false, + addressOptions: addressOptions, + exports: { + selectedAddress: '${ $.parentName }:selectedAddress' + } + }, + + /** + * @returns {Object} Chainable. + */ + initConfig: function () { + this._super(); + this.addressOptions.push(newAddressOption); + + return this; + }, + + /** + * @return {exports.initObservable} + */ + initObservable: function () { + this._super() + .observe('selectedAddress isNewAddressSelected') + .observe({ + isNewAddressSelected: !customer.isLoggedIn() || !addressOptions.length + }); + + return this; + }, + + /** + * @param {Object} address + * @return {*} + */ + addressOptionsText: function (address) { + return address.getAddressInline(); + }, + + /** + * @param {Object} address + */ + onAddressChange: function (address) { + this.isNewAddressSelected(address === newAddressOption); + } + }); +}); diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html index 63edb5057b933..cabfcc9b3db03 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html @@ -5,28 +5,18 @@ */ --> <div class="checkout-billing-address"> - <div class="billing-address-same-as-shipping-block field choice" data-bind="visible: canUseShippingAddress()"> <input type="checkbox" name="billing-address-same-as-shipping" data-bind="checked: isAddressSameAsShipping, click: useShippingAddress, attr: {id: 'billing-address-same-as-shipping-' + getCode($parent)}"/> <label data-bind="attr: {for: 'billing-address-same-as-shipping-' + getCode($parent)}"><span data-bind="i18n: 'My billing and shipping address are the same'"></span></label> </div> - - <!-- ko template: 'Magento_Checkout/billing-address/details' --><!-- /ko --> + <render args="detailsTemplate"/> <fieldset class="fieldset" data-bind="visible: !isAddressDetailsVisible()"> - <!-- ko template: 'Magento_Checkout/billing-address/list' --><!-- /ko --> - <!-- ko template: 'Magento_Checkout/billing-address/form' --><!-- /ko --> - <div class="actions-toolbar"> - <div class="primary"> - <button class="action action-update" type="button" data-bind="click: updateAddress"> - <span data-bind="i18n: 'Update'"></span> - </button> - <button class="action action-cancel" type="button" data-bind="click: cancelAddressEdit, visible: canUseCancelBillingAddress()"> - <span data-bind="i18n: 'Cancel'"></span> - </button> - </div> + <each args="getRegion('billing-address-list')" render="" /> + <div data-bind="fadeVisible: isAddressFormVisible"> + <render args="formTemplate"/> </div> + <render args="actionsTemplate"/> </fieldset> - </div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/actions.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/actions.html new file mode 100644 index 0000000000000..860f340d3f7ca --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/actions.html @@ -0,0 +1,21 @@ +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="actions-toolbar"> + <div class="primary"> + <button class="action action-update" + type="button" + click="updateAddress"> + <span translate="'Update'"/> + </button> + <button class="action action-cancel" + type="button" + click="cancelAddressEdit" + visible="canUseCancelBillingAddress()"> + <span translate="'Cancel'"/> + </button> + </div> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html index 54fe9a1f59394..e29ed99d17be1 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ --> -<div class="billing-address-form" data-bind="fadeVisible: isAddressFormVisible"> +<div class="billing-address-form"> <!-- ko foreach: getRegion('before-fields') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html index a1a5aa67a9688..1fcfa4b3b1343 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html @@ -16,12 +16,14 @@ <!-- Address form pop up --> <if args="!isFormInline"> - <button type="button" - class="action action-show-popup" - click="showFormPopUp" - visible="!isNewAddressAdded()"> - <span translate="'New Address'" /> - </button> + <div class="new-address-popup"> + <button type="button" + class="action action-show-popup" + click="showFormPopUp" + visible="!isNewAddressAdded()"> + <span translate="'New Address'" /> + </button> + </div> <div id="opc-new-shipping-address" visible="isFormPopUpVisible()" render="shippingFormTemplate" /> diff --git a/app/code/Magento/Customer/Model/Address/CustomAttributesProcessor.php b/app/code/Magento/Customer/Model/Address/CustomAttributesProcessor.php new file mode 100644 index 0000000000000..d6e63e11ee453 --- /dev/null +++ b/app/code/Magento/Customer/Model/Address/CustomAttributesProcessor.php @@ -0,0 +1,112 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +use Magento\Customer\Api\AddressMetadataInterface; +use Magento\Eav\Api\AttributeOptionManagementInterface; + +/** + * Provides customer address data. + */ +class CustomAttributesProcessor +{ + /** + * @var AddressMetadataInterface + */ + private $addressMetadata; + + /** + * @var AttributeOptionManagementInterface + */ + private $attributeOptionManager; + + /** + * @param AddressMetadataInterface $addressMetadata + * @param AttributeOptionManagementInterface $attributeOptionManager + */ + public function __construct( + AddressMetadataInterface $addressMetadata, + AttributeOptionManagementInterface $attributeOptionManager + ) { + $this->addressMetadata = $addressMetadata; + $this->attributeOptionManager = $attributeOptionManager; + } + + /** + * Set Labels to custom Attributes + * + * @param \Magento\Framework\Api\AttributeValue[] $customAttributes + * @return array $customAttributes + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\StateException + */ + private function setLabelsForAttributes(array $customAttributes): array + { + if (!empty($customAttributes)) { + foreach ($customAttributes as $customAttributeCode => $customAttribute) { + $attributeOptionLabels = $this->getAttributeLabels($customAttribute, $customAttributeCode); + if (!empty($attributeOptionLabels)) { + $customAttributes[$customAttributeCode]['label'] = implode(', ', $attributeOptionLabels); + } + } + } + + return $customAttributes; + } + /** + * Get Labels by CustomAttribute and CustomAttributeCode + * + * @param array $customAttribute + * @param string $customAttributeCode + * @return array $attributeOptionLabels + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\StateException + */ + private function getAttributeLabels(array $customAttribute, string $customAttributeCode) : array + { + $attributeOptionLabels = []; + + if (!empty($customAttribute['value'])) { + $customAttributeValues = explode(',', $customAttribute['value']); + $attributeOptions = $this->attributeOptionManager->getItems( + \Magento\Customer\Model\Indexer\Address\AttributeProvider::ENTITY, + $customAttributeCode + ); + + if (!empty($attributeOptions)) { + foreach ($attributeOptions as $attributeOption) { + $attributeOptionValue = $attributeOption->getValue(); + if (\in_array($attributeOptionValue, $customAttributeValues, false)) { + $attributeOptionLabels[] = $attributeOption->getLabel() ?? $attributeOptionValue; + } + } + } + } + + return $attributeOptionLabels; + } + + /** + * Filter not visible on storefront custom attributes. + * + * @param array $attributes + * @return array + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function filterNotVisibleAttributes(array $attributes): array + { + $attributesMetadata = $this->addressMetadata->getAllAttributesMetadata(); + foreach ($attributesMetadata as $attributeMetadata) { + if (!$attributeMetadata->isVisible()) { + unset($attributes[$attributeMetadata->getAttributeCode()]); + } + } + + return $this->setLabelsForAttributes($attributes); + } +} diff --git a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php new file mode 100644 index 0000000000000..e80cc0d69e91d --- /dev/null +++ b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php @@ -0,0 +1,165 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Model\Address\Mapper as AddressMapper; +use Magento\Customer\Model\Address\Config as AddressConfig; + +/** + * Provides method to format customer address data. + */ +class CustomerAddressDataFormatter +{ + /** + * @var AddressMapper + */ + private $addressMapper; + + /** + * @var AddressConfig + */ + private $addressConfig; + + /** + * @var CustomAttributesProcessor + */ + private $customAttributesProcessor; + + /** + * @param Mapper $addressMapper + * @param Config $addressConfig + * @param CustomAttributesProcessor $customAttributesProcessor + */ + public function __construct( + AddressMapper $addressMapper, + AddressConfig $addressConfig, + CustomAttributesProcessor $customAttributesProcessor + ) { + $this->addressMapper = $addressMapper; + $this->addressConfig = $addressConfig; + $this->customAttributesProcessor = $customAttributesProcessor; + } + + /** + * Prepare list of addressed that was selected by customer on checkout page. + * + * @param \Magento\Customer\Api\Data\CustomerInterface $customer + * @param \Magento\Quote\Model\Quote $quote + * @param array $prepareAddressList + * @return array + */ + public function prepareSelectedAddresses( + \Magento\Customer\Api\Data\CustomerInterface $customer, + \Magento\Quote\Model\Quote $quote, + array $prepareAddressList + ): array { + /** @var AddressInterface $billingAddress */ + $billingAddress = $quote->getBillingAddress(); + $billingAddressId = $billingAddress->getOrigData('customer_address_id'); + $prepareAddressList = $this->prepareSelectedAddress($customer, $prepareAddressList, $billingAddressId); + + $shippingAddressId = null; + $shippingAssignments = $quote->getExtensionAttributes()->getShippingAssignments(); + if (isset($shippingAssignments[0])) { + $shipping = current($shippingAssignments)->getData('shipping'); + /** @var AddressInterface $shippingAddress */ + $shippingAddress = $shipping->getAddress(); + $shippingAddressId = $shippingAddress->getOrigData('customer_address_id'); + } + + $prepareAddressList = $this->prepareSelectedAddress($customer, $prepareAddressList, $shippingAddressId); + + return $prepareAddressList; + } + + /** + * Prepare customer address data. + * + * @param AddressInterface $customerAddress + * @return array + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function prepareAddress(AddressInterface $customerAddress) + { + $resultAddress = [ + 'id' => $customerAddress->getId(), + 'customer_id' => $customerAddress->getCustomerId(), + 'company' => $customerAddress->getCompany(), + 'prefix' => $customerAddress->getPrefix(), + 'firstname' => $customerAddress->getFirstname(), + 'lastname' => $customerAddress->getLastname(), + 'middlename' => $customerAddress->getMiddlename(), + 'suffix' => $customerAddress->getSuffix(), + 'street' => $customerAddress->getStreet(), + 'city' => $customerAddress->getCity(), + 'region' => [ + 'region' => $customerAddress->getRegion()->getRegion(), + 'region_code' => $customerAddress->getRegion()->getRegionCode(), + 'region_id' => $customerAddress->getRegion()->getRegionId(), + ], + 'region_id' => $customerAddress->getRegionId(), + 'postcode' => $customerAddress->getPostcode(), + 'country_id' => $customerAddress->getCountryId(), + 'telephone' => $customerAddress->getTelephone(), + 'fax' => $customerAddress->getFax(), + 'default_billing' => $customerAddress->isDefaultBilling(), + 'default_shipping' => $customerAddress->isDefaultShipping(), + 'inline' => $this->getCustomerAddressInline($customerAddress), + 'custom_attributes' => [], + 'extension_attributes' => $customerAddress->getExtensionAttributes(), + ]; + + if ($customerAddress->getCustomAttributes()) { + $customerAddress = $customerAddress->__toArray(); + $resultAddress['custom_attributes'] = $this->customAttributesProcessor->filterNotVisibleAttributes( + $customerAddress['custom_attributes'] + ); + } + + return $resultAddress; + } + + /** + * Prepared address by for given customer with given address id. + * + * @param \Magento\Customer\Api\Data\CustomerInterface $customer + * @param array $addressList + * @param int|null $addressId + * @return array + */ + private function prepareSelectedAddress( + \Magento\Customer\Api\Data\CustomerInterface $customer, + array $addressList, + $addressId = null + ): array { + if (null !== $addressId && !isset($addressList[$addressId])) { + $selectedAddress = $this->prepareAddress($customer->getAddresses()[$addressId]); + if (isset($selectedAddress['id'])) { + $addressList[$selectedAddress['id']] = $selectedAddress; + } + } + + return $addressList; + } + + /** + * Set additional customer address data + * + * @param AddressInterface $address + * @return string + */ + private function getCustomerAddressInline(AddressInterface $address): string + { + $builtOutputAddressData = $this->addressMapper->toFlatArray($address); + return $this->addressConfig + ->getFormatByCode(AddressConfig::DEFAULT_ADDRESS_FORMAT) + ->getRenderer() + ->renderArray($builtOutputAddressData); + } +} diff --git a/app/code/Magento/Customer/Model/Address/CustomerAddressDataProvider.php b/app/code/Magento/Customer/Model/Address/CustomerAddressDataProvider.php new file mode 100644 index 0000000000000..04fdd2a7f7266 --- /dev/null +++ b/app/code/Magento/Customer/Model/Address/CustomerAddressDataProvider.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +/** + * Provides customer address data. + */ +class CustomerAddressDataProvider +{ + /** + * Customer addresses. + * + * @var array + */ + private $customerAddresses = []; + + /** + * @var CustomerAddressDataFormatter + */ + private $customerAddressDataFormatter; + + /** + * @param CustomerAddressDataFormatter $customerAddressDataFormatter + */ + public function __construct( + CustomerAddressDataFormatter $customerAddressDataFormatter + ) { + $this->customerAddressDataFormatter = $customerAddressDataFormatter; + } + + /** + * Get addresses for customer. + * + * @param \Magento\Customer\Api\Data\CustomerInterface $customer + * @return array + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function getAddressDataByCustomer( + \Magento\Customer\Api\Data\CustomerInterface $customer + ): array { + if (!empty($this->customerAddresses)) { + return $this->customerAddresses; + } + + $customerOriginAddresses = $customer->getAddresses(); + if (!$customerOriginAddresses) { + return []; + } + + $customerAddresses = []; + foreach ($customerOriginAddresses as $address) { + $customerAddresses[$address->getId()] = $this->customerAddressDataFormatter->prepareAddress($address); + } + + $this->customerAddresses = $customerAddresses; + + return $this->customerAddresses; + } +} diff --git a/app/code/Magento/OfflinePayments/Test/Mftf/Data/ConfigData.xml b/app/code/Magento/OfflinePayments/Test/Mftf/Data/ConfigData.xml new file mode 100644 index 0000000000000..ec8dd46a00d8e --- /dev/null +++ b/app/code/Magento/OfflinePayments/Test/Mftf/Data/ConfigData.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="DisableCheckMoneyOrderPaymentMethod"> + <data key="path">payment/checkmo/active</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="EnableCheckMoneyOrderPaymentMethod"> + <!-- Magento default value --> + <data key="path">payment/checkmo/active</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisableCashOnDeliveryPaymentMethod"> + <!-- Magento default value --> + <data key="path">payment/cashondelivery/active</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="EnableCashOnDeliveryPaymentMethod"> + <data key="path">payment/cashondelivery/active</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> +</entities> diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js index dba0992c5ba52..4479cff5135dc 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js @@ -131,6 +131,7 @@ define([ return Abstract.extend({ defaults: { options: [], + total: 0, listVisible: false, value: [], filterOptions: false, @@ -153,6 +154,7 @@ define([ labelsDecoration: false, disableLabel: false, filterRateLimit: 500, + filterRateLimitMethod: 'notifyAtFixedRate', closeBtnLabel: $t('Done'), optgroupTmpl: 'ui/grid/filters/elements/ui-select-optgroup', quantityPlaceholder: $t('options'), @@ -180,6 +182,7 @@ define([ debounce: 300, missingValuePlaceholder: $t('Entity with ID: %s doesn\'t exist'), isDisplayMissingValuePlaceholder: false, + currentSearchKey: '', listens: { listVisible: 'cleanHoveredElement', filterInputValue: 'filterOptionsList', @@ -330,7 +333,10 @@ define([ ]); this.filterInputValue.extend({ - rateLimit: this.filterRateLimit + rateLimit: { + timeout: this.filterRateLimit, + method: this.filterRateLimitMethod + } }); return this; @@ -460,7 +466,7 @@ define([ } if (this.searchOptions) { - return _.debounce(this.loadOptions.bind(this, value), this.debounce)(); + return this.loadOptions(value); } this.cleanHoveredElement(); @@ -547,11 +553,21 @@ define([ _setItemsQuantity: function (data) { if (this.showFilteredQuantity) { data || parseInt(data, 10) === 0 ? - this.itemsQuantity(data + ' ' + this.quantityPlaceholder) : + this.itemsQuantity(this.getItemsPlaceholder(data)) : this.itemsQuantity(''); } }, + /** + * Return formatted items placeholder. + * + * @param {Object} data - option data + * @returns {String} + */ + getItemsPlaceholder: function (data) { + return data + ' ' + this.quantityPlaceholder; + }, + /** * Remove element from selected array */ @@ -1234,13 +1250,11 @@ define([ * @param {Number} page */ processRequest: function (searchKey, page) { - var total = 0, - existingOptions = this.options(); - this.loading(true); + this.currentSearchKey = searchKey; $.ajax({ url: this.searchUrl, - type: 'post', + type: 'get', dataType: 'json', context: this, data: { @@ -1248,27 +1262,39 @@ define([ page: page, limit: this.pageLimit }, + success: $.proxy(this.success, this), + error: $.proxy(this.error, this), + beforeSend: $.proxy(this.beforeSend, this), + complete: $.proxy(this.complete, this, searchKey, page) + }); + }, - /** @param {Object} response */ - success: function (response) { - _.each(response.options, function (opt) { - existingOptions.push(opt); - }); - total = response.total; - this.options(existingOptions); - }, - - /** set empty array if error occurs */ - error: function () { - this.options([]); - }, + /** @param {Object} response */ + success: function (response) { + var existingOptions = this.options(); - /** cache options and stop loading*/ - complete: function () { - this.setCachedSearchResults(searchKey, this.options(), page, total); - this.afterLoadOptions(searchKey, page, total); - } + _.each(response.options, function (opt) { + existingOptions.push(opt); }); + + this.total = response.total; + this.options(existingOptions); + }, + + /** add actions before ajax request */ + beforeSend: function () { + + }, + + /** set empty array if error occurs */ + error: function () { + this.options([]); + }, + + /** cache options and stop loading*/ + complete: function (searchKey, page) { + this.setCachedSearchResults(searchKey, this.options(), page, this.total); + this.afterLoadOptions(searchKey, page, this.total); }, /** @@ -1279,9 +1305,9 @@ define([ * @param {Number} total */ afterLoadOptions: function (searchKey, page, total) { - this._setItemsQuantity(total); - this.lastSearchPage = page; this.lastSearchKey = searchKey; + this.lastSearchPage = page; + this._setItemsQuantity(total); this.loading(false); } }); diff --git a/app/code/Magento/Wishlist/Helper/Data.php b/app/code/Magento/Wishlist/Helper/Data.php index 3b9f431566da0..0589747a52d33 100644 --- a/app/code/Magento/Wishlist/Helper/Data.php +++ b/app/code/Magento/Wishlist/Helper/Data.php @@ -171,7 +171,7 @@ public function setCustomer(\Magento\Customer\Api\Data\CustomerInterface $custom public function getCustomer() { if (!$this->_currentCustomer && $this->_customerSession->isLoggedIn()) { - $this->_currentCustomer = $this->_customerSession->getCustomerDataObject(); + $this->_currentCustomer = $this->_customerSession->getCustomerData(); } return $this->_currentCustomer; } @@ -355,7 +355,7 @@ public function getMoveFromCartParams($itemId) * * @param \Magento\Catalog\Model\Product|\Magento\Wishlist\Model\Item $item * - * @return string|false + * @return string|false */ public function getUpdateParams($item) { @@ -382,7 +382,7 @@ public function getUpdateParams($item) * Retrieve params for adding item to shopping cart * * @param string|\Magento\Catalog\Model\Product|\Magento\Wishlist\Model\Item $item - * @return string + * @return string */ public function getAddToCartUrl($item) { @@ -428,7 +428,7 @@ public function addRefererToParams(array $params) * Retrieve URL for adding item to shopping cart from shared wishlist * * @param string|\Magento\Catalog\Model\Product|\Magento\Wishlist\Model\Item $item - * @return string + * @return string */ public function getSharedAddToCartUrl($item) { diff --git a/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/CookieAndSessionMisuse.php b/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/CookieAndSessionMisuse.php index ee56158a54509..707c3442d4056 100644 --- a/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/CookieAndSessionMisuse.php +++ b/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/CookieAndSessionMisuse.php @@ -54,6 +54,19 @@ private function isUiDataProvider(\ReflectionClass $class): bool ); } + /** + * Is given class a Layout Processor? + * + * @param \ReflectionClass $class + * @return bool + */ + private function isLayoutProcessor(\ReflectionClass $class): bool + { + return $class->isSubclassOf( + \Magento\Checkout\Block\Checkout\LayoutProcessorInterface::class + ); + } + /** * Is given class an HTML UI Document? * @@ -159,6 +172,7 @@ private function doesUseRestrictedClasses(\ReflectionClass $class): bool * @inheritdoc * * @param ClassNode|ASTClass $node + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function apply(AbstractNode $node) { @@ -176,6 +190,7 @@ public function apply(AbstractNode $node) && !$this->isUiDocument($class) && !$this->isControllerPlugin($class) && !$this->isBlockPlugin($class) + && !$this->isLayoutProcessor($class) ) { $this->addViolation($node, [$node->getFullQualifiedName()]); } From dfbeeabdf8c04e98799edcc4016bf10e999dd8ba Mon Sep 17 00:00:00 2001 From: Andrii-Deineha <andrii.deineha@transoftgroup.com> Date: Tue, 23 Apr 2019 13:54:13 +0300 Subject: [PATCH 466/585] MC-11940: Create Product Attribute --- .../ProductAttribute/CreateProductAttributeEntityTest.xml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml index 2287546aed102..49725d08b63e8 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml @@ -8,7 +8,6 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\CreateProductAttributeEntityTest" summary="Create Product Attribute" ticketId="MAGETWO-24767"> <variation name="CreateProductAttributeEntityTestVariation1"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Text_Field_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Text Field</data> @@ -60,7 +59,6 @@ <data name="productAttribute/data/used_in_product_listing" xsi:type="string">Yes</data> <data name="productAttribute/data/is_used_for_promo_rules" xsi:type="string">Yes</data> <data name="productAttribute/data/used_for_sort_by" xsi:type="string">Yes</data> - <data name="tag" xsi:type="string">to_maintain:yes</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeInGrid" /> <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeForm" /> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAdvancedSearchProductByAttribute" /> @@ -69,7 +67,6 @@ <constraint name="Magento\CatalogRule\Test\Constraint\AssertProductAttributeIsUsedPromoRules" /> </variation> <variation name="CreateProductAttributeEntityTestVariation4"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Yes/No_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Yes/No</data> @@ -86,6 +83,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> </variation> <variation name="CreateProductAttributeEntityTestVariation5" summary="Create custom multiple select attribute product field" ticketId="MAGETWO-14862"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Multiple_Select_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Multiple Select</data> @@ -102,7 +100,6 @@ <data name="productAttribute/data/is_html_allowed_on_front" xsi:type="string">Yes</data> <data name="productAttribute/data/is_visible_on_front" xsi:type="string">Yes</data> <data name="productAttribute/data/used_in_product_listing" xsi:type="string">Yes</data> - <data name="tag" xsi:type="string">to_maintain:yes</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeInGrid" /> <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeForm" /> <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> @@ -178,7 +175,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterableInSearch" /> </variation> <variation name="CreateProductAttributeEntityTestVariation8"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Fixed_Product_Tax_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Fixed Product Tax</data> @@ -195,7 +191,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> </variation> <variation name="CreateProductAttributeEntityTestVariation9"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Text_Field_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Text Field</data> From c433cbd6fa29384bc1e0d2a760baeb83f8f53438 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 23 Apr 2019 14:43:14 +0300 Subject: [PATCH 467/585] MC-11930: Create Grouped Product --- .../Test/TestCase/CreateGroupedProductEntityTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/CreateGroupedProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/CreateGroupedProductEntityTest.xml index 39f4fd08bb922..f397c1b99e3b2 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/CreateGroupedProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/CreateGroupedProductEntityTest.xml @@ -57,7 +57,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductOutOfStock" /> </variation> <variation name="CreateGroupedProductEntityTestVariation5" summary="Create with no required products"> - <data name="tag" xsi:type="string">stable:no</data> <data name="product/data/url_key" xsi:type="string">test-grouped-product-%isolation%</data> <data name="product/data/name" xsi:type="string">GroupedProduct %isolation%</data> <data name="product/data/sku" xsi:type="string">GroupedProduct_sku%isolation%</data> @@ -110,7 +109,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductPage" /> </variation> <variation name="CreateGroupedProductEntityTestVariation10" summary="Create Grouped Product and Assign it on Custom Website"> - <data name="tag" xsi:type="string">stable:no</data> <data name="product/data/url_key" xsi:type="string">test-grouped-product-%isolation%</data> <data name="product/data/name" xsi:type="string">GroupedProduct %isolation%</data> <data name="product/data/sku" xsi:type="string">GroupedProduct_sku%isolation%</data> From d8d8fed62ea570359c6cc60227b338dbb79d00a2 Mon Sep 17 00:00:00 2001 From: Dan Farmer <dan@danielfarmer.co.uk> Date: Tue, 23 Apr 2019 15:52:57 +0100 Subject: [PATCH 468/585] Use final price rather than base price to calculate price increases / decreases on the configurable attribute dropdown. This fixes a bug introduced in PR #17695 as detailed on issue #22270 --- .../ConfigurableProduct/view/frontend/web/js/configurable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js index e732960421541..ef40dcb9a7323 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js @@ -373,7 +373,7 @@ define([ allowedProducts, i, j, - basePrice = parseFloat(this.options.spConfig.prices.basePrice.amount), + finalPrice = parseFloat(this.options.spConfig.prices.finalPrice.amount), optionFinalPrice, optionPriceDiff, optionPrices = this.options.spConfig.optionPrices, @@ -410,7 +410,7 @@ define([ typeof optionPrices[allowedProducts[0]] !== 'undefined') { allowedProductMinPrice = this._getAllowedProductWithMinPrice(allowedProducts); optionFinalPrice = parseFloat(optionPrices[allowedProductMinPrice].finalPrice.amount); - optionPriceDiff = optionFinalPrice - basePrice; + optionPriceDiff = optionFinalPrice - finalPrice; if (optionPriceDiff !== 0) { options[i].label = options[i].label + ' ' + priceUtils.formatPrice( From 8d78cc194382fe04827b26ffe8fb760878e54ee2 Mon Sep 17 00:00:00 2001 From: Ruslan Kostiv <rkostiv@adobe.com> Date: Tue, 23 Apr 2019 11:08:43 -0500 Subject: [PATCH 469/585] MC-5681: Onepage Checkout improvements. --- app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php | 1 + app/code/Magento/Checkout/Model/DefaultConfigProvider.php | 1 + app/code/Magento/Wishlist/Helper/Data.php | 1 + 3 files changed, 3 insertions(+) diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php index 5d02dd636825b..557f143352446 100644 --- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php @@ -122,6 +122,7 @@ private function convertElementsToSelect($elements, $attributesToConvert) if (!in_array($code, $codes)) { continue; } + // phpcs:ignore Magento2.Functions.DiscouragedFunction $options = call_user_func($attributesToConvert[$code]); if (!is_array($options)) { continue; diff --git a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php index c2c049d2bf99f..470d4a3aca561 100644 --- a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php +++ b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php @@ -35,6 +35,7 @@ * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class DefaultConfigProvider implements ConfigProviderInterface { diff --git a/app/code/Magento/Wishlist/Helper/Data.php b/app/code/Magento/Wishlist/Helper/Data.php index 0589747a52d33..3d25e16294fcd 100644 --- a/app/code/Magento/Wishlist/Helper/Data.php +++ b/app/code/Magento/Wishlist/Helper/Data.php @@ -13,6 +13,7 @@ * * @author Magento Core Team <core@magentocommerce.com> * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * * @api * @since 100.0.2 From 9e4ca95accf142534b7ba02ccfe38ff4a1188940 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 23 Apr 2019 11:58:04 -0500 Subject: [PATCH 470/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- lib/internal/Magento/Framework/Session/SessionManager.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Session/SessionManager.php b/lib/internal/Magento/Framework/Session/SessionManager.php index db2c6ff47f390..c7d201676b228 100644 --- a/lib/internal/Magento/Framework/Session/SessionManager.php +++ b/lib/internal/Magento/Framework/Session/SessionManager.php @@ -165,9 +165,6 @@ public function __call($method, $args) sprintf('Invalid method %s::%s(%s)', get_class($this), $method, print_r($args, 1)) ); } - if (!($this->storage instanceof StorageInterface)) { - throw new \RuntimeException('Not storage'); - } $return = call_user_func_array([$this->storage, $method], $args); return $return === $this->storage ? $this : $return; } From 70525414941d8293049cc4c52847ef4e58158768 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 23 Apr 2019 11:58:27 -0500 Subject: [PATCH 471/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- dev/tests/integration/framework/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/framework/bootstrap.php b/dev/tests/integration/framework/bootstrap.php index 56cffaa0c8ea8..1cae393dc01c3 100644 --- a/dev/tests/integration/framework/bootstrap.php +++ b/dev/tests/integration/framework/bootstrap.php @@ -132,7 +132,7 @@ function ($errNo, $errStr, $errFile, $errLine) { $errName = isset($errorNames[$errNo]) ? $errorNames[$errNo] : ""; throw new \PHPUnit\Framework\Exception( - sprintf("%s: %s in %s:%s.\n\n%s\n\n", $errName, $errStr, $errFile, $errLine, debug_backtrace()), + sprintf("%s: %s in %s:%s.", $errName, $errStr, $errFile, $errLine), $errNo ); } From 8b714b0dd22bcde3f33c2f65702596986ba10dcf Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 23 Apr 2019 12:06:03 -0500 Subject: [PATCH 472/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- app/code/Magento/Authorization/Model/Role.php | 4 ++-- .../Magento/Catalog/Model/ResourceModel/Eav/Attribute.php | 4 ++-- app/code/Magento/Config/Model/Config/Backend/Encrypted.php | 4 ++-- .../Model/Product/Type/Configurable/Attribute.php | 4 ++-- .../Product/Type/Configurable/Attribute/Collection.php | 4 ++-- app/code/Magento/Customer/Model/Attribute.php | 4 ++-- app/code/Magento/Eav/Model/Entity/Attribute.php | 4 ++-- .../Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php | 4 ++-- app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php | 4 ++-- app/code/Magento/Store/Model/Store.php | 4 ++-- app/code/Magento/User/Model/User.php | 4 ++-- lib/internal/Magento/Framework/App/AreaList/Proxy.php | 4 ++-- lib/internal/Magento/Framework/App/Response/Http.php | 4 ++-- .../Magento/Framework/App/Route/ConfigInterface/Proxy.php | 4 ++-- lib/internal/Magento/Framework/DB/Select.php | 4 ++-- lib/internal/Magento/Framework/DB/Select/RendererProxy.php | 4 ++-- lib/internal/Magento/Framework/Data/Collection.php | 4 ++-- lib/internal/Magento/Framework/Data/Collection/AbstractDb.php | 4 ++-- .../Magento/Framework/DataObject/Copy/Config/Data/Proxy.php | 4 ++-- lib/internal/Magento/Framework/Interception/Interceptor.php | 4 ++-- .../Magento/Framework/Model/AbstractExtensibleModel.php | 4 ++-- lib/internal/Magento/Framework/Model/AbstractModel.php | 4 ++-- .../Magento/Framework/Model/ResourceModel/Db/AbstractDb.php | 4 ++-- .../Model/ResourceModel/Db/Collection/AbstractCollection.php | 4 ++-- lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php | 4 ++-- lib/internal/Magento/Framework/Translate/Inline/Proxy.php | 4 ++-- lib/internal/Magento/Framework/View/Layout/Proxy.php | 4 ++-- 27 files changed, 54 insertions(+), 54 deletions(-) diff --git a/app/code/Magento/Authorization/Model/Role.php b/app/code/Magento/Authorization/Model/Role.php index dcc46ee77ee12..757c80f9bca39 100644 --- a/app/code/Magento/Authorization/Model/Role.php +++ b/app/code/Magento/Authorization/Model/Role.php @@ -58,7 +58,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff($properties, ['_resource', '_resourceCollection']); @@ -72,7 +72,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index d56cc40ad0fc2..29e4547d7d2b2 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -851,7 +851,7 @@ public function afterDelete() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('entity_type'); return array_diff( @@ -869,7 +869,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php index ea3b1d4c74a5f..44f29078d6075 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php +++ b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php @@ -56,7 +56,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff($properties, ['_encryptor']); @@ -72,7 +72,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_encryptor = \Magento\Framework\App\ObjectManager::getInstance()->get( diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php index 4ead9ffe0fe70..514d76405fc7e 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php @@ -271,7 +271,7 @@ public function setProductId($value) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -287,7 +287,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php index 81cbbd06c523c..b378b309dcefe 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php @@ -364,7 +364,7 @@ protected function getIncludedOptions(array $usedProducts, AbstractAttribute $pr */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -388,7 +388,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = ObjectManager::getInstance(); diff --git a/app/code/Magento/Customer/Model/Attribute.php b/app/code/Magento/Customer/Model/Attribute.php index ae714f993082e..1d9b6b095f91f 100644 --- a/app/code/Magento/Customer/Model/Attribute.php +++ b/app/code/Magento/Customer/Model/Attribute.php @@ -208,7 +208,7 @@ public function canBeFilterableInGrid() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('entity_type'); return array_diff( @@ -225,7 +225,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute.php b/app/code/Magento/Eav/Model/Entity/Attribute.php index e23f81607a0c0..510d6ef5e531f 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute.php @@ -502,7 +502,7 @@ public function getIdentities() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('attribute_set_info'); return array_diff( @@ -520,7 +520,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 9ed4ac5293681..bd36c55bcdee4 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -1410,7 +1410,7 @@ public function setExtensionAttributes(\Magento\Eav\Api\Data\AttributeExtensionI */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -1440,7 +1440,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php index 5e7226e7a36dd..e5b7ef7fd6844 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php @@ -731,7 +731,7 @@ public function getValidAttributeIds($attributeIds) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); $properties = array_diff($properties, ['_storeManager']); @@ -749,7 +749,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_storeManager = \Magento\Framework\App\ObjectManager::getInstance() diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index 4f69579c41bbb..6e16466089330 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -429,7 +429,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); $properties = array_diff($properties, ['_coreFileStorageDatabase', '_config']); @@ -446,7 +446,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_coreFileStorageDatabase = ObjectManager::getInstance() diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index d8040b0bbaaac..e747dd5b09e04 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -218,7 +218,7 @@ protected function _construct() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff( @@ -251,7 +251,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/App/AreaList/Proxy.php b/lib/internal/Magento/Framework/App/AreaList/Proxy.php index 09115add57190..2d7a315032200 100644 --- a/lib/internal/Magento/Framework/App/AreaList/Proxy.php +++ b/lib/internal/Magento/Framework/App/AreaList/Proxy.php @@ -67,7 +67,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -82,7 +82,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/App/Response/Http.php b/lib/internal/Magento/Framework/App/Response/Http.php index a80d9cbdd6689..5716857fb2917 100644 --- a/lib/internal/Magento/Framework/App/Response/Http.php +++ b/lib/internal/Magento/Framework/App/Response/Http.php @@ -189,7 +189,7 @@ public function representJson($content) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['content', 'isRedirect', 'statusCode', 'context', 'headers']; } @@ -205,7 +205,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = ObjectManager::getInstance(); $this->cookieManager = $objectManager->create(\Magento\Framework\Stdlib\CookieManagerInterface::class); diff --git a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php index 5e79315238f7d..6aecfed8b3481 100644 --- a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php +++ b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php @@ -69,7 +69,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -84,7 +84,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/DB/Select.php b/lib/internal/Magento/Framework/DB/Select.php index f33aaea7d0e68..ad570dbc2c8ae 100644 --- a/lib/internal/Magento/Framework/DB/Select.php +++ b/lib/internal/Magento/Framework/DB/Select.php @@ -519,7 +519,7 @@ public function assemble() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -543,7 +543,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_adapter = $objectManager->get(ResourceConnection::class)->getConnection(); diff --git a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php index dc69b96b79050..a4415ce56d3b8 100644 --- a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php +++ b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php @@ -65,7 +65,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -80,7 +80,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index 5477b58d4e862..962ac5038bacf 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -892,7 +892,7 @@ public function hasFlag($flag) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -915,7 +915,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_entityFactory = $objectManager->get(EntityFactoryInterface::class); diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 1b28e367dcc3a..c0d3e73c90158 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -896,7 +896,7 @@ private function getMainTableAlias() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -913,7 +913,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php index b0f5742afef10..95348cc2828ed 100644 --- a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php @@ -66,7 +66,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -81,7 +81,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Interception/Interceptor.php b/lib/internal/Magento/Framework/Interception/Interceptor.php index df1b680234220..4ad47f3bd95fd 100644 --- a/lib/internal/Magento/Framework/Interception/Interceptor.php +++ b/lib/internal/Magento/Framework/Interception/Interceptor.php @@ -68,7 +68,7 @@ public function ___callParent($method, array $arguments) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); if (method_exists(get_parent_class($this), '__sleep')) { $properties = parent::__sleep(); @@ -89,7 +89,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); if (method_exists(get_parent_class($this), '__wakeup')) { parent::__wakeup(); diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index e1f6c792c9c3e..14255a586ec86 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -365,7 +365,7 @@ private function populateExtensionAttributes(array $extensionAttributesData = [] */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff(parent::__sleep(), ['extensionAttributesFactory', 'customAttributeFactory']); } @@ -378,7 +378,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php index f5095dbb6e872..0c9340d283a4e 100644 --- a/lib/internal/Magento/Framework/Model/AbstractModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractModel.php @@ -225,7 +225,7 @@ protected function _init($resourceModel) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -254,7 +254,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_registry = $objectManager->get(\Magento\Framework\Registry::class); diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php index 0cadb10aaafe2..395724d6e480b 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php @@ -162,7 +162,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff($properties, ['_resources', '_connections']); @@ -179,7 +179,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_resources = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\App\ResourceConnection::class); diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php index bc2187f474919..11585a81de083 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php @@ -612,7 +612,7 @@ public function save() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -629,7 +629,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php index d67c380207554..06b6f394a31f6 100644 --- a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php @@ -64,7 +64,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['subject', 'isShared']; } @@ -79,7 +79,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php index e6d6cc57c2b09..cd0053e00ae17 100644 --- a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php +++ b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php @@ -64,7 +64,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['subject', 'isShared']; } @@ -79,7 +79,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/View/Layout/Proxy.php b/lib/internal/Magento/Framework/View/Layout/Proxy.php index a3d89c6ec7a8e..529412faa7a36 100644 --- a/lib/internal/Magento/Framework/View/Layout/Proxy.php +++ b/lib/internal/Magento/Framework/View/Layout/Proxy.php @@ -66,7 +66,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -81,7 +81,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } From 4b3317119cad79711dcf51d872ec01a01fe6a990 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Tue, 23 Apr 2019 20:19:37 +0300 Subject: [PATCH 473/585] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Added strict type declaration in test file; --- .../integration/testsuite/Magento/Ups/Model/CarrierTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php b/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php index b3ced0b84e27b..042bd03b1cd4c 100644 --- a/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php +++ b/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Ups\Model; use Magento\TestFramework\Helper\Bootstrap; From 90eff3a7f4d6189c8f55e2456d0e28d9e2d929fb Mon Sep 17 00:00:00 2001 From: Tiago Sampaio <tiago@tiagosampaio.com> Date: Sat, 13 Apr 2019 12:40:25 -0300 Subject: [PATCH 474/585] Adding a validation before adding or executing layout generator class. --- .../Framework/View/Layout/GeneratorPool.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Layout/GeneratorPool.php b/lib/internal/Magento/Framework/View/Layout/GeneratorPool.php index 266a1f873f4b7..b899e34e6b39d 100644 --- a/lib/internal/Magento/Framework/View/Layout/GeneratorPool.php +++ b/lib/internal/Magento/Framework/View/Layout/GeneratorPool.php @@ -35,9 +35,9 @@ class GeneratorPool /** * @param ScheduledStructure\Helper $helper - * @param ConditionFactory $conditionFactory - * @param \Psr\Log\LoggerInterface $logger - * @param array $generators + * @param ConditionFactory $conditionFactory + * @param \Psr\Log\LoggerInterface $logger + * @param array $generators */ public function __construct( ScheduledStructure\Helper $helper, @@ -69,8 +69,9 @@ public function getGenerator($type) /** * Traverse through all generators and generate all scheduled elements * - * @param Reader\Context $readerContext + * @param Reader\Context $readerContext * @param Generator\Context $generatorContext + * * @return $this */ public function process(Reader\Context $readerContext, Generator\Context $generatorContext) @@ -86,11 +87,17 @@ public function process(Reader\Context $readerContext, Generator\Context $genera * Add generators to pool * * @param GeneratorInterface[] $generators + * * @return void */ protected function addGenerators(array $generators) { foreach ($generators as $generator) { + if (!$generator instanceof GeneratorInterface) { + throw new \InvalidArgumentException( + sprintf('Generator class must be an instance of %s', GeneratorInterface::class) + ); + } $this->generators[$generator->getType()] = $generator; } } From 04274297730c46bdeb8b95fd233d2390299cd69b Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Tue, 23 Apr 2019 12:47:54 -0500 Subject: [PATCH 475/585] MC-15993: Minisearch is broken on mobile screen --- .../view/frontend/templates/form.mini.phtml | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml index a98a70a90cede..44c8db3f1a663 100644 --- a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml +++ b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml @@ -16,31 +16,26 @@ $helper = $this->helper(\Magento\Search\Helper\Data::class); <div class="block block-content"> <form class="form minisearch" id="search_mini_form" action="<?= /* @escapeNotVerified */ $helper->getResultUrl() ?>" method="get"> <div class="field search"> + <label class="label" for="search" data-role="minisearch-label"> + <span><?= /* @escapeNotVerified */ __('Search') ?></span> + </label> <div class="control"> - <label for="search" data-role="minisearch-label"> - <span class="label"> - <?= /* @escapeNotVerified */ __('Search') ?> - </span> - <input - aria-expanded="false" - id="search" - data-mage-init='{"quickSearch":{ + <input id="search" + data-mage-init='{"quickSearch":{ "formSelector":"#search_mini_form", "url":"<?= /* @escapeNotVerified */ $helper->getSuggestUrl()?>", "destinationSelector":"#search_autocomplete"} - }' - type="text" - name="<?= /* @escapeNotVerified */ $helper->getQueryParamName() ?>" - value="<?= /* @escapeNotVerified */ $helper->getEscapedQueryText() ?>" - placeholder="<?= /* @escapeNotVerified */ __('Search entire store here...') ?>" - class="input-text" - maxlength="<?= /* @escapeNotVerified */ $helper->getMaxQueryLength() ?>" - role="combobox" - aria-haspopup="false" - aria-autocomplete="both" - autocomplete="off" - /> - </label> + }' + type="text" + name="<?= /* @escapeNotVerified */ $helper->getQueryParamName() ?>" + value="<?= /* @escapeNotVerified */ $helper->getEscapedQueryText() ?>" + placeholder="<?= /* @escapeNotVerified */ __('Search entire store here...') ?>" + class="input-text" + maxlength="<?= /* @escapeNotVerified */ $helper->getMaxQueryLength() ?>" + role="combobox" + aria-haspopup="false" + aria-autocomplete="both" + autocomplete="off"/> <div id="search_autocomplete" class="search-autocomplete"></div> <?= $block->getChildHtml() ?> </div> From 2bd1c30ca3ea14f2bd419d92fe43cba3b202caae Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 23 Apr 2019 13:12:11 -0500 Subject: [PATCH 476/585] =?UTF-8?q?GraphQL-608:=20Remove=20=E2=80=9Ccart?= =?UTF-8?q?=5Faddress=5Fid=E2=80=9D=20from=20=E2=80=9CShippingMethodInput?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Model/Cart/GetQuoteAddress.php | 83 ----------------- .../Model/Cart/SetShippingMethodsOnCart.php | 13 +-- .../Quote/Customer/CheckoutEndToEndTest.php | 11 +-- .../SetOfflineShippingMethodsOnCartTest.php | 18 +--- .../Customer/SetShippingMethodsOnCartTest.php | 92 ++----------------- .../Quote/Guest/CheckoutEndToEndTest.php | 11 +-- .../SetOfflineShippingMethodsOnCartTest.php | 9 -- .../Guest/SetShippingMethodsOnCartTest.php | 88 ++---------------- .../Ups/SetUpsShippingMethodsOnCartTest.php | 18 +--- 9 files changed, 28 insertions(+), 315 deletions(-) delete mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/GetQuoteAddress.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/GetQuoteAddress.php b/app/code/Magento/QuoteGraphQl/Model/Cart/GetQuoteAddress.php deleted file mode 100644 index 89124c594dd87..0000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/GetQuoteAddress.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\QuoteGraphQl\Model\Cart; - -use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; -use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; -use Magento\Quote\Api\Data\AddressInterface; -use Magento\Quote\Api\Data\AddressInterfaceFactory; -use Magento\Quote\Api\Data\CartInterface; -use Magento\Quote\Model\ResourceModel\Quote\Address as AddressResource; - -/** - * Get quote address - */ -class GetQuoteAddress -{ - /** - * @var AddressInterfaceFactory - */ - private $quoteAddressFactory; - - /** - * @var AddressResource - */ - private $quoteAddressResource; - - /** - * @param AddressInterfaceFactory $quoteAddressFactory - * @param AddressResource $quoteAddressResource - */ - public function __construct( - AddressInterfaceFactory $quoteAddressFactory, - AddressResource $quoteAddressResource - ) { - $this->quoteAddressFactory = $quoteAddressFactory; - $this->quoteAddressResource = $quoteAddressResource; - } - - /** - * Get quote address - * - * @param CartInterface $cart - * @param int $quoteAddressId - * @param int|null $customerId - * @return AddressInterface - * @throws GraphQlAuthorizationException - * @throws GraphQlNoSuchEntityException - */ - public function execute(CartInterface $cart, int $quoteAddressId, ?int $customerId): AddressInterface - { - $quoteAddress = $this->quoteAddressFactory->create(); - - $this->quoteAddressResource->load($quoteAddress, $quoteAddressId); - if (null === $quoteAddress->getId()) { - throw new GraphQlNoSuchEntityException( - __('Could not find a cart address with ID "%cart_address_id"', ['cart_address_id' => $quoteAddressId]) - ); - } - - // TODO: GetQuoteAddress::execute should depend only on AddressInterface contract - // https://github.com/magento/graphql-ce/issues/550 - if ($quoteAddress->getQuoteId() !== $cart->getId()) { - throw new GraphQlNoSuchEntityException( - __('Cart does not contain address with ID "%cart_address_id"', ['cart_address_id' => $quoteAddressId]) - ); - } - - if ((int)$quoteAddress->getCustomerId() !== (int)$customerId) { - throw new GraphQlAuthorizationException( - __( - 'The current user cannot use cart address with ID "%cart_address_id"', - ['cart_address_id' => $quoteAddressId] - ) - ); - } - return $quoteAddress; - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php index d4e3923846b36..b2526bdc04e98 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php @@ -16,25 +16,17 @@ */ class SetShippingMethodsOnCart implements SetShippingMethodsOnCartInterface { - /** - * @var GetQuoteAddress - */ - private $getQuoteAddress; - /** * @var AssignShippingMethodToCart */ private $assignShippingMethodToCart; /** - * @param GetQuoteAddress $getQuoteAddress * @param AssignShippingMethodToCart $assignShippingMethodToCart */ public function __construct( - GetQuoteAddress $getQuoteAddress, AssignShippingMethodToCart $assignShippingMethodToCart ) { - $this->getQuoteAddress = $getQuoteAddress; $this->assignShippingMethodToCart = $assignShippingMethodToCart; } @@ -60,8 +52,7 @@ public function execute(ContextInterface $context, CartInterface $cart, array $s } $methodCode = $shippingMethodInput['method_code']; - $cartAddressId = $cart->getBillingAddress()->getId(); - $quoteAddress = $this->getQuoteAddress->execute($cart, $cartAddressId, $context->getUserId()); - $this->assignShippingMethodToCart->execute($cart, $quoteAddress, $carrierCode, $methodCode); + $shippingAddress = $cart->getShippingAddress(); + $this->assignShippingMethodToCart->execute($cart, $shippingAddress, $carrierCode, $methodCode); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index 8592a986c5dce..81d655128d753 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -92,10 +92,9 @@ public function testCheckoutWorkflow() $this->addProductToCart($cartId, $qty, $sku); $this->setBillingAddress($cartId); - $shippingAddress = $this->setShippingAddress($cartId); + $shippingMethod = $this->setShippingAddress($cartId); - $shippingMethod = current($shippingAddress['available_shipping_methods']); - $paymentMethod = $this->setShippingMethod($cartId, $shippingAddress['address_id'], $shippingMethod); + $paymentMethod = $this->setShippingMethod($cartId, $shippingMethod); $this->setPaymentMethod($cartId, $paymentMethod); $orderId = $this->placeOrder($cartId); @@ -340,16 +339,15 @@ private function setShippingAddress(string $cartId): array self::assertArrayHasKey('amount', $availableShippingMethod); self::assertNotEmpty($availableShippingMethod['amount']); - return $shippingAddress; + return $availableShippingMethod; } /** * @param string $cartId - * @param int $addressId * @param array $method * @return array */ - private function setShippingMethod(string $cartId, int $addressId, array $method): array + private function setShippingMethod(string $cartId, array $method): array { $query = <<<QUERY mutation { @@ -357,7 +355,6 @@ private function setShippingMethod(string $cartId, int $addressId, array $method cart_id: "{$cartId}", shipping_methods: [ { - cart_address_id: {$addressId} carrier_code: "{$method['carrier_code']}" method_code: "{$method['method_code']}" } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php index 20462220ff6f7..4544691584721 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php @@ -8,7 +8,6 @@ namespace Magento\GraphQl\Quote\Customer; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; -use Magento\GraphQl\Quote\GetQuoteShippingAddressIdByReservedQuoteId; use Magento\Integration\Api\CustomerTokenServiceInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -23,11 +22,6 @@ class SetOfflineShippingMethodsOnCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; - /** - * @var GetQuoteShippingAddressIdByReservedQuoteId - */ - private $getQuoteShippingAddressIdByReservedQuoteId; - /** * @var CustomerTokenServiceInterface */ @@ -40,9 +34,6 @@ protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - $this->getQuoteShippingAddressIdByReservedQuoteId = $objectManager->get( - GetQuoteShippingAddressIdByReservedQuoteId::class - ); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); } @@ -64,13 +55,11 @@ protected function setUp() public function testSetOfflineShippingMethod(string $carrierCode, string $methodCode, float $amount, string $label) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); @@ -111,14 +100,12 @@ public function offlineShippingMethodDataProvider(): array * @param string $maskedQuoteId * @param string $shippingMethodCode * @param string $shippingCarrierCode - * @param int $shippingAddressId * @return string */ private function getQuery( string $maskedQuoteId, string $shippingMethodCode, - string $shippingCarrierCode, - int $shippingAddressId + string $shippingCarrierCode ): string { return <<<QUERY mutation { @@ -126,7 +113,6 @@ private function getQuery( { cart_id: "$maskedQuoteId", shipping_methods: [{ - cart_address_id: $shippingAddressId carrier_code: "$shippingCarrierCode" method_code: "$shippingMethodCode" }] diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php index 0fc52443e86b9..a5c91865926a5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php @@ -9,7 +9,6 @@ use Exception; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; -use Magento\GraphQl\Quote\GetQuoteShippingAddressIdByReservedQuoteId; use Magento\Integration\Api\CustomerTokenServiceInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -24,11 +23,6 @@ class SetShippingMethodsOnCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; - /** - * @var GetQuoteShippingAddressIdByReservedQuoteId - */ - private $getQuoteShippingAddressIdByReservedQuoteId; - /** * @var CustomerTokenServiceInterface */ @@ -41,9 +35,6 @@ protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - $this->getQuoteShippingAddressIdByReservedQuoteId = $objectManager->get( - GetQuoteShippingAddressIdByReservedQuoteId::class - ); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); } @@ -59,13 +50,11 @@ public function testSetShippingMethodOnCartWithSimpleProduct() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $carrierCode = 'flatrate'; $methodCode = 'flatrate'; - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); @@ -98,13 +87,11 @@ public function testReSetShippingMethod() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $carrierCode = 'freeshipping'; $methodCode = 'freeshipping'; - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); @@ -138,8 +125,7 @@ public function testReSetShippingMethod() public function testSetShippingMethodWithWrongParameters(string $input, string $message) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); - $input = str_replace(['cart_id_value', 'cart_address_id_value'], [$maskedQuoteId, $quoteAddressId], $input); + $input = str_replace('cart_id_value', $maskedQuoteId, $input); $query = <<<QUERY mutation { @@ -169,7 +155,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array return [ 'missed_cart_id' => [ 'shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "flatrate" method_code: "flatrate" }]', @@ -183,31 +168,14 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array 'cart_id: "cart_id_value" shipping_methods: []', 'Required parameter "shipping_methods" is missing' ], - 'missed_cart_address_id' => [ - 'cart_id: "cart_id_value", shipping_methods: [{ - carrier_code: "flatrate" - method_code: "flatrate" - }]', - 'Required parameter "cart_address_id" is missing.' - ], - 'non_existent_cart_address_id' => [ - 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: -1 - carrier_code: "flatrate" - method_code: "flatrate" - }]', - 'Could not find a cart address with ID "-1"' - ], 'missed_carrier_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value method_code: "flatrate" }]', 'Field ShippingMethodInput.carrier_code of required type String! was not provided.' ], 'empty_carrier_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "" method_code: "flatrate" }]', @@ -215,7 +183,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array ], 'non_existent_carrier_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "wrong-carrier-code" method_code: "flatrate" }]', @@ -223,14 +190,12 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array ], 'missed_method_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "flatrate" }]', 'Required parameter "method_code" is missing.' ], 'empty_method_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "flatrate" method_code: "" }]', @@ -238,7 +203,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array ], 'non_existent_method_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "flatrate" method_code: "wrong-carrier-code" }]', @@ -246,7 +210,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array ], 'non_existent_shopping_cart' => [ 'cart_id: "non_existent_masked_id", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "flatrate" method_code: "flatrate" }]', @@ -254,7 +217,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array ], 'disabled_shipping_method' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "freeshipping" method_code: "freeshipping" }]', @@ -276,7 +238,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array public function testSetMultipleShippingMethods() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = <<<QUERY mutation { @@ -284,12 +245,10 @@ public function testSetMultipleShippingMethods() cart_id: "{$maskedQuoteId}", shipping_methods: [ { - cart_address_id: {$quoteAddressId} carrier_code: "flatrate" method_code: "flatrate" } { - cart_address_id: {$quoteAddressId} carrier_code: "flatrate" method_code: "flatrate" } @@ -323,12 +282,10 @@ public function testSetShippingMethodToGuestCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $carrierCode = 'flatrate'; $methodCode = 'flatrate'; - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $this->expectExceptionMessage( @@ -352,12 +309,10 @@ public function testSetShippingMethodToAnotherCustomerCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $carrierCode = 'flatrate'; $methodCode = 'flatrate'; - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $this->expectExceptionMessage( @@ -366,46 +321,16 @@ public function testSetShippingMethodToAnotherCustomerCart() $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } - /** - * _security - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/quote_with_address.php - */ - public function testSetShippingMethodIfCustomerIsNotOwnerOfAddress() - { - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $carrierCode = 'flatrate'; - $methodCode = 'flatrate'; - $anotherQuoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('guest_quote_with_address'); - $query = $this->getQuery( - $maskedQuoteId, - $methodCode, - $carrierCode, - $anotherQuoteAddressId - ); - - $this->expectExceptionMessage( - "Cart does not contain address with ID \"{$anotherQuoteAddressId}\"" - ); - $this->graphQlMutation($query, [], '', $this->getHeaderMap()); - } - /** * @param string $maskedQuoteId * @param string $shippingMethodCode * @param string $shippingCarrierCode - * @param int $shippingAddressId * @return string */ private function getQuery( string $maskedQuoteId, string $shippingMethodCode, - string $shippingCarrierCode, - int $shippingAddressId + string $shippingCarrierCode ): string { return <<<QUERY mutation { @@ -413,7 +338,6 @@ private function getQuery( { cart_id: "$maskedQuoteId", shipping_methods: [{ - cart_address_id: $shippingAddressId carrier_code: "$shippingCarrierCode" method_code: "$shippingMethodCode" }] @@ -444,13 +368,11 @@ public function testSetShippingMethodOnAnEmptyCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $carrierCode = 'flatrate'; $methodCode = 'flatrate'; - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index f5114b9253a40..8ba32f76fc62d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -77,10 +77,9 @@ public function testCheckoutWorkflow() $this->addProductToCart($cartId, $qty, $sku); $this->setBillingAddress($cartId); - $shippingAddress = $this->setShippingAddress($cartId); + $shippingMethod = $this->setShippingAddress($cartId); - $shippingMethod = current($shippingAddress['available_shipping_methods']); - $paymentMethod = $this->setShippingMethod($cartId, $shippingAddress['address_id'], $shippingMethod); + $paymentMethod = $this->setShippingMethod($cartId, $shippingMethod); $this->setPaymentMethod($cartId, $paymentMethod); $this->placeOrder($cartId); @@ -300,16 +299,15 @@ private function setShippingAddress(string $cartId): array self::assertArrayHasKey('amount', $availableShippingMethod); self::assertNotEmpty($availableShippingMethod['amount']); - return $shippingAddress; + return $availableShippingMethod; } /** * @param string $cartId - * @param int $addressId * @param array $method * @return array */ - private function setShippingMethod(string $cartId, int $addressId, array $method): array + private function setShippingMethod(string $cartId, array $method): array { $query = <<<QUERY mutation { @@ -317,7 +315,6 @@ private function setShippingMethod(string $cartId, int $addressId, array $method cart_id: "{$cartId}", shipping_methods: [ { - cart_address_id: {$addressId} carrier_code: "{$method['carrier_code']}" method_code: "{$method['method_code']}" } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php index a89419b51df44..2dc4ea360acb9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php @@ -8,7 +8,6 @@ namespace Magento\GraphQl\Quote\Guest; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; -use Magento\GraphQl\Quote\GetQuoteShippingAddressIdByReservedQuoteId; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -22,11 +21,6 @@ class SetOfflineShippingMethodsOnCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; - /** - * @var GetQuoteShippingAddressIdByReservedQuoteId - */ - private $getQuoteShippingAddressIdByReservedQuoteId; - /** * @inheritdoc */ @@ -34,9 +28,6 @@ protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - $this->getQuoteShippingAddressIdByReservedQuoteId = $objectManager->get( - GetQuoteShippingAddressIdByReservedQuoteId::class - ); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php index 06cf3d0c9698c..3cac485f9f6f2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php @@ -9,7 +9,6 @@ use Exception; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; -use Magento\GraphQl\Quote\GetQuoteShippingAddressIdByReservedQuoteId; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -23,11 +22,6 @@ class SetShippingMethodsOnCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; - /** - * @var GetQuoteShippingAddressIdByReservedQuoteId - */ - private $getQuoteShippingAddressIdByReservedQuoteId; - /** * @inheritdoc */ @@ -35,9 +29,6 @@ protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - $this->getQuoteShippingAddressIdByReservedQuoteId = $objectManager->get( - GetQuoteShippingAddressIdByReservedQuoteId::class - ); } /** @@ -92,13 +83,11 @@ public function testSetShippingMethodOnCartWithSimpleProductAndWithoutAddress() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $carrierCode = 'flatrate'; $methodCode = 'flatrate'; - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $this->graphQlMutation($query); } @@ -116,13 +105,11 @@ public function testReSetShippingMethod() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $carrierCode = 'freeshipping'; $methodCode = 'freeshipping'; - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $response = $this->graphQlMutation($query); @@ -155,8 +142,7 @@ public function testReSetShippingMethod() public function testSetShippingMethodWithWrongParameters(string $input, string $message) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); - $input = str_replace(['cart_id_value', 'cart_address_id_value'], [$maskedQuoteId, $quoteAddressId], $input); + $input = str_replace('cart_id_value', $maskedQuoteId, $input); $query = <<<QUERY mutation { @@ -186,7 +172,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array return [ 'missed_cart_id' => [ 'shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "flatrate" method_code: "flatrate" }]', @@ -200,31 +185,14 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array 'cart_id: "cart_id_value" shipping_methods: []', 'Required parameter "shipping_methods" is missing' ], - 'missed_cart_address_id' => [ - 'cart_id: "cart_id_value", shipping_methods: [{ - carrier_code: "flatrate" - method_code: "flatrate" - }]', - 'Required parameter "cart_address_id" is missing.' - ], - 'non_existent_cart_address_id' => [ - 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: -1 - carrier_code: "flatrate" - method_code: "flatrate" - }]', - 'Could not find a cart address with ID "-1"' - ], 'missed_carrier_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value method_code: "flatrate" }]', 'Field ShippingMethodInput.carrier_code of required type String! was not provided.' ], 'empty_carrier_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "" method_code: "flatrate" }]', @@ -232,7 +200,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array ], 'non_existent_carrier_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "wrong-carrier-code" method_code: "flatrate" }]', @@ -240,14 +207,12 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array ], 'missed_method_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "flatrate" }]', 'Required parameter "method_code" is missing.' ], 'empty_method_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "flatrate" method_code: "" }]', @@ -255,7 +220,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array ], 'non_existent_method_code' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "flatrate" method_code: "wrong-carrier-code" }]', @@ -263,7 +227,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array ], 'non_existent_shopping_cart' => [ 'cart_id: "non_existent_masked_id", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "flatrate" method_code: "flatrate" }]', @@ -271,7 +234,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array ], 'disabled_shipping_method' => [ 'cart_id: "cart_id_value", shipping_methods: [{ - cart_address_id: cart_address_id_value carrier_code: "freeshipping" method_code: "freeshipping" }]', @@ -292,7 +254,6 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array public function testSetMultipleShippingMethods() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = <<<QUERY mutation { @@ -300,12 +261,10 @@ public function testSetMultipleShippingMethods() cart_id: "{$maskedQuoteId}", shipping_methods: [ { - cart_address_id: {$quoteAddressId} carrier_code: "flatrate" method_code: "flatrate" } { - cart_address_id: {$quoteAddressId} carrier_code: "flatrate" method_code: "flatrate" } @@ -339,12 +298,10 @@ public function testSetShippingMethodToCustomerCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $carrierCode = 'flatrate'; $methodCode = 'flatrate'; - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $this->expectExceptionMessage( @@ -352,34 +309,7 @@ public function testSetShippingMethodToCustomerCart() ); $this->graphQlMutation($query); } - - /** - * _security - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/quote_with_address.php - */ - public function testSetShippingMethodIfGuestIsNotOwnerOfAddress() - { - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $carrierCode = 'flatrate'; - $methodCode = 'flatrate'; - $anotherQuoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('guest_quote_with_address'); - $query = $this->getQuery( - $maskedQuoteId, - $methodCode, - $carrierCode, - $anotherQuoteAddressId - ); - - $this->expectExceptionMessage( - "Cart does not contain address with ID \"{$anotherQuoteAddressId}\"" - ); - $this->graphQlMutation($query); - } - + /** * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -393,13 +323,11 @@ public function testSetShippingMethodOnAnEmptyCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $carrierCode = 'flatrate'; $methodCode = 'flatrate'; - $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); $query = $this->getQuery( $maskedQuoteId, $methodCode, - $carrierCode, - $quoteAddressId + $carrierCode ); $this->graphQlMutation($query); } @@ -408,14 +336,12 @@ public function testSetShippingMethodOnAnEmptyCart() * @param string $maskedQuoteId * @param string $shippingMethodCode * @param string $shippingCarrierCode - * @param int $shippingAddressId * @return string */ private function getQuery( string $maskedQuoteId, string $shippingMethodCode, - string $shippingCarrierCode, - int $shippingAddressId + string $shippingCarrierCode ): string { return <<<QUERY mutation { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index fb0c205c86a2c..ea498ddb31d16 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -8,7 +8,6 @@ namespace Magento\GraphQl\Ups; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; -use Magento\GraphQl\Quote\GetQuoteShippingAddressIdByReservedQuoteId; use Magento\Integration\Api\CustomerTokenServiceInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -68,11 +67,6 @@ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; - /** - * @var GetQuoteShippingAddressIdByReservedQuoteId - */ - private $getQuoteShippingAddressIdByReservedQuoteId; - /** * @inheritdoc */ @@ -81,9 +75,6 @@ protected function setUp() $objectManager = Bootstrap::getObjectManager(); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - $this->getQuoteShippingAddressIdByReservedQuoteId = $objectManager->get( - GetQuoteShippingAddressIdByReservedQuoteId::class - ); } /** @@ -102,9 +93,8 @@ public function testSetUpsShippingMethod(string $methodCode, string $methodLabel { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); + $query = $this->getQuery($maskedQuoteId, self::CARRIER_CODE, $methodCode); $response = $this->sendRequestWithToken($query); self::assertArrayHasKey('setShippingMethodsOnCart', $response); @@ -158,9 +148,8 @@ public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); + $query = $this->getQuery($maskedQuoteId, self::CARRIER_CODE, $methodCode); $response = $this->sendRequestWithToken($query); self::assertArrayHasKey('setShippingMethodsOnCart', $response); @@ -201,7 +190,6 @@ public function dataProviderShippingMethodsBasedOnCanadaAddress(): array /** * Generates query for setting the specified shipping method on cart * - * @param int $shippingAddressId * @param string $maskedQuoteId * @param string $carrierCode * @param string $methodCode @@ -209,7 +197,6 @@ public function dataProviderShippingMethodsBasedOnCanadaAddress(): array */ private function getQuery( string $maskedQuoteId, - int $shippingAddressId, string $carrierCode, string $methodCode ): string { @@ -219,7 +206,6 @@ private function getQuery( cart_id: "$maskedQuoteId" shipping_methods: [ { - cart_address_id: $shippingAddressId carrier_code: "$carrierCode" method_code: "$methodCode" } From c26f2ac57f771f67ed2ff40dbe5e6e52236d0e55 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Tue, 23 Apr 2019 13:18:04 -0500 Subject: [PATCH 477/585] magento-engcom/magento2ce#2781: Fixed code style issues --- .../Model/Entity/Attribute/Source/AbstractSource.php | 2 +- .../Downloadable/Api/ProductRepositoryTest.php | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php index a81d437acea36..dd4cd4217a127 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php @@ -8,7 +8,7 @@ /** * Entity/Attribute/Model - attribute selection source abstract - * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @author Magento Core Team <core@magentocommerce.com> * @SuppressWarnings(PHPMD.NumberOfChildren) diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php index d0cace993a24a..769abadf20585 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php @@ -51,11 +51,13 @@ protected function getLinkData() 'link_type' => 'file', 'link_file_content' => [ 'name' => 'link1_content.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], 'sample_type' => 'file', 'sample_file_content' => [ 'name' => 'link1_sample.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ], @@ -114,6 +116,7 @@ protected function getSampleData() 'sample_type' => 'file', 'sample_file_content' => [ 'name' => 'sample2.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ], @@ -146,7 +149,9 @@ protected function createDownloadableProduct() "price" => 10, 'attribute_set_id' => 4, "extension_attributes" => [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction "downloadable_product_links" => array_values($this->getLinkData()), + // phpcs:ignore Magento2.Functions.DiscouragedFunction "downloadable_product_samples" => array_values($this->getSampleData()), ], ]; @@ -301,11 +306,13 @@ public function testUpdateDownloadableProductLinksWithNewFile() 'link_type' => 'file', 'link_file_content' => [ 'name' => $linkFile . $extension, + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], 'sample_type' => 'file', 'sample_file_content' => [ 'name' => $sampleFile . $extension, + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ]; @@ -319,11 +326,13 @@ public function testUpdateDownloadableProductLinksWithNewFile() 'link_type' => 'file', 'link_file_content' => [ 'name' => 'link2_content.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], 'sample_type' => 'file', 'sample_file_content' => [ 'name' => 'link2_sample.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ]; @@ -463,6 +472,7 @@ public function testUpdateDownloadableProductSamplesWithNewFile() 'sample_type' => 'file', 'sample_file_content' => [ 'name' => 'sample1.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ]; @@ -474,6 +484,7 @@ public function testUpdateDownloadableProductSamplesWithNewFile() 'sample_type' => 'file', 'sample_file_content' => [ 'name' => 'sample2.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ]; From 4ebdced0ff6c355ff0015c58801e0470f76f28d9 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 23 Apr 2019 13:24:52 -0500 Subject: [PATCH 478/585] GraphQL-533: Cannot set payment method Purchase Order on cart --- ...t.php => SetPurchaseOrderPaymentMethodOnCartTest.php} | 9 ++++++--- ...t.php => SetPurchaseOrderPaymentMethodOnCartTest.php} | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) rename dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/{SetOfflinePaymentMethodOnCartTest.php => SetPurchaseOrderPaymentMethodOnCartTest.php} (94%) rename dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/{SetOfflinePaymentMethodOnCartTest.php => SetPurchaseOrderPaymentMethodOnCartTest.php} (93%) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPurchaseOrderPaymentMethodOnCartTest.php similarity index 94% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php rename to dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPurchaseOrderPaymentMethodOnCartTest.php index ed7b6288f0910..bff66ece59b93 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPurchaseOrderPaymentMethodOnCartTest.php @@ -15,9 +15,9 @@ use Magento\TestFramework\TestCase\GraphQlAbstract; /** - * Test for setting offline payment methods on cart by customer + * Test for setting Purchase Order payment method on cart by customer */ -class SetOfflinePaymentMethodOnCartTest extends GraphQlAbstract +class SetPurchaseOrderPaymentMethodOnCartTest extends GraphQlAbstract { /** * @var GetMaskedQuoteIdByReservedOrderId @@ -77,7 +77,10 @@ public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); - self::assertEquals($purchaseOrderNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); + self::assertEquals( + $purchaseOrderNumber, + $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number'] + ); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPurchaseOrderPaymentMethodOnCartTest.php similarity index 93% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php rename to dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPurchaseOrderPaymentMethodOnCartTest.php index 70996f584b9db..9dd0382a5dbed 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPurchaseOrderPaymentMethodOnCartTest.php @@ -14,9 +14,9 @@ use Magento\TestFramework\TestCase\GraphQlAbstract; /** - * Test for setting offline payment methods on cart by guest + * Test for setting Purchase Order payment method on cart by guest */ -class SetOfflinePaymentMethodOnCartTest extends GraphQlAbstract +class SetPurchaseOrderPaymentMethodOnCartTest extends GraphQlAbstract { /** * @var GetMaskedQuoteIdByReservedOrderId @@ -69,7 +69,10 @@ public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); - self::assertEquals($purchaseOrderNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); + self::assertEquals( + $purchaseOrderNumber, + $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number'] + ); } /** From 817e766e594bc218c9051caafa14e1f40d4f8eb7 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 23 Apr 2019 13:35:38 -0500 Subject: [PATCH 479/585] =?UTF-8?q?GraphQL-608:=20Remove=20=E2=80=9Ccart?= =?UTF-8?q?=5Faddress=5Fid=E2=80=9D=20from=20=E2=80=9CShippingMethodInput?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php | 1 - app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 1 - .../Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php | 3 --- .../Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php | 3 --- 4 files changed, 8 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php index 840dedb4f274e..4d832f603cd91 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php @@ -50,7 +50,6 @@ public function execute(QuoteAddress $address): array } $addressData = array_merge($addressData, [ - 'address_id' => $address->getId(), 'address_type' => $addressType, 'country' => [ 'code' => $address->getCountryId(), diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index c8d2af4c09fd0..3b34b994eabe6 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -187,7 +187,6 @@ type Cart { } type CartAddress { - address_id: Int firstname: String lastname: String company: String diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index 81d655128d753..a49b84e20a8a6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -306,7 +306,6 @@ private function setShippingAddress(string $cartId): array ) { cart { shipping_addresses { - address_id available_shipping_methods { carrier_code method_code @@ -324,8 +323,6 @@ private function setShippingAddress(string $cartId): array self::assertCount(1, $response['setShippingAddressesOnCart']['cart']['shipping_addresses']); $shippingAddress = current($response['setShippingAddressesOnCart']['cart']['shipping_addresses']); - self::assertArrayHasKey('address_id', $shippingAddress); - self::assertNotEmpty($shippingAddress['address_id']); self::assertArrayHasKey('available_shipping_methods', $shippingAddress); self::assertCount(1, $shippingAddress['available_shipping_methods']); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index 8ba32f76fc62d..7cd4e06a19e23 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -266,7 +266,6 @@ private function setShippingAddress(string $cartId): array ) { cart { shipping_addresses { - address_id available_shipping_methods { carrier_code method_code @@ -284,8 +283,6 @@ private function setShippingAddress(string $cartId): array self::assertCount(1, $response['setShippingAddressesOnCart']['cart']['shipping_addresses']); $shippingAddress = current($response['setShippingAddressesOnCart']['cart']['shipping_addresses']); - self::assertArrayHasKey('address_id', $shippingAddress); - self::assertNotEmpty($shippingAddress['address_id']); self::assertArrayHasKey('available_shipping_methods', $shippingAddress); self::assertCount(1, $shippingAddress['available_shipping_methods']); From 461b661ee8d491e5f88a5893e664857bec2fb7d4 Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Tue, 23 Apr 2019 14:05:29 -0500 Subject: [PATCH 480/585] MC-5681: Onepage Checkout improvements - Fix fatal with no default billing or shipping address; --- .../Model/Address/CustomerAddressDataFormatter.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php index e80cc0d69e91d..a95fe3e128470 100644 --- a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php +++ b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php @@ -139,9 +139,17 @@ private function prepareSelectedAddress( $addressId = null ): array { if (null !== $addressId && !isset($addressList[$addressId])) { - $selectedAddress = $this->prepareAddress($customer->getAddresses()[$addressId]); - if (isset($selectedAddress['id'])) { - $addressList[$selectedAddress['id']] = $selectedAddress; + $filteredDefaultAddress = array_filter( + $customer->getAddresses(), + function ($address) use ($addressId) { + return $address->getId() === $addressId; + } + ); + if (!empty ($filteredDefaultAddress)) { + $selectedAddress = $this->prepareAddress(current($filteredDefaultAddress)); + if (isset($selectedAddress['id'])) { + $addressList[$selectedAddress['id']] = $selectedAddress; + } } } From 666e8c3e2c14a917415c0e09c4c998dafa383bb9 Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Tue, 23 Apr 2019 14:07:55 -0500 Subject: [PATCH 481/585] MC-5681: Onepage Checkout improvements - Rename variable; --- .../Customer/Model/Address/CustomerAddressDataFormatter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php index a95fe3e128470..85492bbb2de65 100644 --- a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php +++ b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php @@ -139,14 +139,14 @@ private function prepareSelectedAddress( $addressId = null ): array { if (null !== $addressId && !isset($addressList[$addressId])) { - $filteredDefaultAddress = array_filter( + $filteredAddress = array_filter( $customer->getAddresses(), function ($address) use ($addressId) { return $address->getId() === $addressId; } ); - if (!empty ($filteredDefaultAddress)) { - $selectedAddress = $this->prepareAddress(current($filteredDefaultAddress)); + if (!empty ($filteredAddress)) { + $selectedAddress = $this->prepareAddress(current($filteredAddress)); if (isset($selectedAddress['id'])) { $addressList[$selectedAddress['id']] = $selectedAddress; } From a44f50ae67a1c0a26e8bd2bf8b8c881c18566503 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Tue, 23 Apr 2019 14:31:53 -0500 Subject: [PATCH 482/585] magento-engcom/magento2ce#2781: Fixed integration test (Travis failures) --- .../Model/Import/ProductTest.php | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index 70c16e05712b9..67446960e15dc 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -1595,7 +1595,6 @@ public function testAddUpdateProductWithInvalidUrlKeys() : void /** * Make sure the non existing image in the csv file won't erase the qty key of the existing products. * - * @magentoDataFixture Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv * @magentoDbIsolation enabled * @magentoAppIsolation enabled */ @@ -1604,24 +1603,8 @@ public function testImportWithNonExistingImage() $products = [ 'simple_new' => 100, ]; - $filesystem = $this->objectManager->create(\Magento\Framework\Filesystem::class); - $directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); - $source = $this->objectManager->create( - \Magento\ImportExport\Model\Import\Source\Csv::class, - [ - 'file' => __DIR__ . '/_files/products_to_import_with_non_existing_image.csv', - 'directory' => $directory - ] - ); - $errors = $this->_model->setParameters( - ['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product'] - ) - ->setSource($source) - ->validateData(); - - $this->assertTrue($errors->getErrorsCount() == 0); - $this->_model->importData(); + $this->importFile('products_to_import_with_non_existing_image.csv'); $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); foreach ($products as $productSku => $productQty) { From c40251a7588695b7c675f4e05dec8fb72718b773 Mon Sep 17 00:00:00 2001 From: Ruslan Kostiv <rkostiv@adobe.com> Date: Tue, 23 Apr 2019 14:44:05 -0500 Subject: [PATCH 483/585] MC-5681: Onepage Checkout improvements. --- .../Address/CustomerAddressDataFormatter.php | 55 ------------------- 1 file changed, 55 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php index e80cc0d69e91d..9202d7492040c 100644 --- a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php +++ b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php @@ -46,38 +46,6 @@ public function __construct( $this->customAttributesProcessor = $customAttributesProcessor; } - /** - * Prepare list of addressed that was selected by customer on checkout page. - * - * @param \Magento\Customer\Api\Data\CustomerInterface $customer - * @param \Magento\Quote\Model\Quote $quote - * @param array $prepareAddressList - * @return array - */ - public function prepareSelectedAddresses( - \Magento\Customer\Api\Data\CustomerInterface $customer, - \Magento\Quote\Model\Quote $quote, - array $prepareAddressList - ): array { - /** @var AddressInterface $billingAddress */ - $billingAddress = $quote->getBillingAddress(); - $billingAddressId = $billingAddress->getOrigData('customer_address_id'); - $prepareAddressList = $this->prepareSelectedAddress($customer, $prepareAddressList, $billingAddressId); - - $shippingAddressId = null; - $shippingAssignments = $quote->getExtensionAttributes()->getShippingAssignments(); - if (isset($shippingAssignments[0])) { - $shipping = current($shippingAssignments)->getData('shipping'); - /** @var AddressInterface $shippingAddress */ - $shippingAddress = $shipping->getAddress(); - $shippingAddressId = $shippingAddress->getOrigData('customer_address_id'); - } - - $prepareAddressList = $this->prepareSelectedAddress($customer, $prepareAddressList, $shippingAddressId); - - return $prepareAddressList; - } - /** * Prepare customer address data. * @@ -125,29 +93,6 @@ public function prepareAddress(AddressInterface $customerAddress) return $resultAddress; } - /** - * Prepared address by for given customer with given address id. - * - * @param \Magento\Customer\Api\Data\CustomerInterface $customer - * @param array $addressList - * @param int|null $addressId - * @return array - */ - private function prepareSelectedAddress( - \Magento\Customer\Api\Data\CustomerInterface $customer, - array $addressList, - $addressId = null - ): array { - if (null !== $addressId && !isset($addressList[$addressId])) { - $selectedAddress = $this->prepareAddress($customer->getAddresses()[$addressId]); - if (isset($selectedAddress['id'])) { - $addressList[$selectedAddress['id']] = $selectedAddress; - } - } - - return $addressList; - } - /** * Set additional customer address data * From 496d36a96baabdfe9fcc9b97ab5abb0013ca51ca Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 23 Apr 2019 14:56:23 -0500 Subject: [PATCH 484/585] GraphQL-530: [Cart Operations] Update Cart Items validation messages --- .../Model/Resolver/UpdateCartItems.php | 4 +- .../CatalogInventory/AddProductToCartTest.php | 12 +-- .../CatalogInventory/UpdateCartItemsTest.php | 86 +++++++++++++++++++ .../Quote/Customer/UpdateCartItemsTest.php | 21 ----- .../Quote/Guest/UpdateCartItemsTest.php | 21 ----- 5 files changed, 93 insertions(+), 51 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php index 50d16360dd55d..1af836c07e196 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -115,9 +115,7 @@ private function processCartItems(Quote $cart, array $items): void if ($cartItem->getHasError()) { $errors = []; foreach ($cartItem->getMessage(false) as $message) { - if (!in_array($message, $errors)) { - $errors[] = $message; - } + $errors[] = $message; } if (!empty($errors)) { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 770f5adc4ba90..df93fea7d9009 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -82,15 +82,15 @@ public function testAddSimpleProductToCartWithNegativeQty() } /** - * @magentoApiDataFixture Magento/Catalog/_files/products.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php */ public function testAddProductIfQuantityIsDecimal() { - $sku = 'simple'; + $sku = 'simple_product'; $qty = 0.2; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->expectExceptionMessage( @@ -102,10 +102,10 @@ public function testAddProductIfQuantityIsDecimal() /** * @param string $maskedQuoteId * @param string $sku - * @param int $qty + * @param float $qty * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, int $qty) : string + private function getQuery(string $maskedQuoteId, string $sku, float $qty) : string { return <<<QUERY mutation { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php new file mode 100644 index 0000000000000..27ec288204048 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\CatalogInventory; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\GraphQl\Quote\GetQuoteItemIdByReservedQuoteIdAndSku; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for updating/removing shopping cart items + */ +class UpdateCartItemsTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var GetQuoteItemIdByReservedQuoteIdAndSku + */ + private $getQuoteItemIdByReservedQuoteIdAndSku; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->getQuoteItemIdByReservedQuoteIdAndSku = $objectManager->get( + GetQuoteItemIdByReservedQuoteIdAndSku::class + ); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testUpdateCartItemDecimalQty() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $itemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute('test_quote', 'simple_product'); + + $qty = 0.5; + $this->expectExceptionMessage( + "Could not update the product with SKU simple_product: The fewest you may purchase is 1." + ); + $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $this->graphQlMutation($query); + } + + /** + * @param string $maskedQuoteId + * @param int $itemId + * @param float $qty + * @return string + */ + private function getQuery(string $maskedQuoteId, int $itemId, float $qty): string + { + return <<<QUERY +mutation { + updateCartItems(input: { + cart_id: "{$maskedQuoteId}" + cart_items:[ + { + cart_item_id: {$itemId} + quantity: {$qty} + } + ] + }) { + cart { + items { + id + qty + } + } + } +} +QUERY; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php index ed71562a7a8ae..35e2d62214fb2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php @@ -79,27 +79,6 @@ public function testUpdateCartItemQty() $this->assertEquals($qty, $item['qty']); } - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - */ - public function testUpdateCartItemDecimalQty() - { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); - $product = $this->productRepository->get('simple'); - - $itemId = (int)$quote->getItemByProduct($product)->getId(); - $qty = 0.5; - - $this->expectExceptionMessage( - "Could not update the product with SKU " . $product->getSku() . ": The fewest you may purchase is 1." - ); - - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - } - /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php index 8348aec0e6b68..1b8cf2e1c57f7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php @@ -72,27 +72,6 @@ public function testUpdateCartItemQty() $this->assertEquals($qty, $item['qty']); } - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - */ - public function testUpdateCartItemDecimalQty() - { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); - $product = $this->productRepository->get('simple'); - - $itemId = (int)$quote->getItemByProduct($product)->getId(); - $qty = 0.5; - - $this->expectExceptionMessage( - "Could not update the product with SKU " . $product->getSku() . ": The fewest you may purchase is 1." - ); - - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); - $this->graphQlQuery($query); - } - /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php */ From f767b8f2a8594550ad3147dcd7203a1d7c18892f Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 23 Apr 2019 15:33:12 -0500 Subject: [PATCH 485/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- app/code/Magento/Authorization/Model/Role.php | 4 ++-- .../Magento/Catalog/Model/ResourceModel/Eav/Attribute.php | 4 ++-- app/code/Magento/Config/Model/Config/Backend/Encrypted.php | 4 ++-- .../Model/Product/Type/Configurable/Attribute.php | 4 ++-- .../Product/Type/Configurable/Attribute/Collection.php | 4 ++-- app/code/Magento/Customer/Model/Attribute.php | 4 ++-- app/code/Magento/Eav/Model/Entity/Attribute.php | 4 ++-- .../Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php | 4 ++-- app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php | 4 ++-- app/code/Magento/Store/Model/Store.php | 4 ++-- app/code/Magento/User/Model/User.php | 4 ++-- lib/internal/Magento/Framework/App/AreaList/Proxy.php | 4 ++-- lib/internal/Magento/Framework/App/Response/Http.php | 4 ++-- .../Magento/Framework/App/Route/ConfigInterface/Proxy.php | 4 ++-- lib/internal/Magento/Framework/DB/Select.php | 4 ++-- lib/internal/Magento/Framework/DB/Select/RendererProxy.php | 4 ++-- lib/internal/Magento/Framework/Data/Collection.php | 4 ++-- lib/internal/Magento/Framework/Data/Collection/AbstractDb.php | 4 ++-- .../Magento/Framework/DataObject/Copy/Config/Data/Proxy.php | 4 ++-- lib/internal/Magento/Framework/Interception/Interceptor.php | 4 ++-- .../Magento/Framework/Model/AbstractExtensibleModel.php | 4 ++-- lib/internal/Magento/Framework/Model/AbstractModel.php | 4 ++-- .../Magento/Framework/Model/ResourceModel/Db/AbstractDb.php | 4 ++-- .../Model/ResourceModel/Db/Collection/AbstractCollection.php | 4 ++-- lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php | 4 ++-- lib/internal/Magento/Framework/Translate/Inline/Proxy.php | 4 ++-- lib/internal/Magento/Framework/View/Layout/Proxy.php | 4 ++-- 27 files changed, 54 insertions(+), 54 deletions(-) diff --git a/app/code/Magento/Authorization/Model/Role.php b/app/code/Magento/Authorization/Model/Role.php index 757c80f9bca39..dcc46ee77ee12 100644 --- a/app/code/Magento/Authorization/Model/Role.php +++ b/app/code/Magento/Authorization/Model/Role.php @@ -58,7 +58,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff($properties, ['_resource', '_resourceCollection']); @@ -72,7 +72,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index 29e4547d7d2b2..d56cc40ad0fc2 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -851,7 +851,7 @@ public function afterDelete() */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('entity_type'); return array_diff( @@ -869,7 +869,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php index 44f29078d6075..ea3b1d4c74a5f 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php +++ b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php @@ -56,7 +56,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff($properties, ['_encryptor']); @@ -72,7 +72,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_encryptor = \Magento\Framework\App\ObjectManager::getInstance()->get( diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php index 514d76405fc7e..4ead9ffe0fe70 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php @@ -271,7 +271,7 @@ public function setProductId($value) */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -287,7 +287,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php index b378b309dcefe..81cbbd06c523c 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php @@ -364,7 +364,7 @@ protected function getIncludedOptions(array $usedProducts, AbstractAttribute $pr */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -388,7 +388,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = ObjectManager::getInstance(); diff --git a/app/code/Magento/Customer/Model/Attribute.php b/app/code/Magento/Customer/Model/Attribute.php index 1d9b6b095f91f..ae714f993082e 100644 --- a/app/code/Magento/Customer/Model/Attribute.php +++ b/app/code/Magento/Customer/Model/Attribute.php @@ -208,7 +208,7 @@ public function canBeFilterableInGrid() */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('entity_type'); return array_diff( @@ -225,7 +225,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute.php b/app/code/Magento/Eav/Model/Entity/Attribute.php index 510d6ef5e531f..e23f81607a0c0 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute.php @@ -502,7 +502,7 @@ public function getIdentities() */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('attribute_set_info'); return array_diff( @@ -520,7 +520,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index bd36c55bcdee4..9ed4ac5293681 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -1410,7 +1410,7 @@ public function setExtensionAttributes(\Magento\Eav\Api\Data\AttributeExtensionI */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -1440,7 +1440,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php index e5b7ef7fd6844..5e7226e7a36dd 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php @@ -731,7 +731,7 @@ public function getValidAttributeIds($attributeIds) */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); $properties = array_diff($properties, ['_storeManager']); @@ -749,7 +749,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_storeManager = \Magento\Framework\App\ObjectManager::getInstance() diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index 6e16466089330..4f69579c41bbb 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -429,7 +429,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); $properties = array_diff($properties, ['_coreFileStorageDatabase', '_config']); @@ -446,7 +446,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_coreFileStorageDatabase = ObjectManager::getInstance() diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index e747dd5b09e04..d8040b0bbaaac 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -218,7 +218,7 @@ protected function _construct() */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff( @@ -251,7 +251,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/App/AreaList/Proxy.php b/lib/internal/Magento/Framework/App/AreaList/Proxy.php index 2d7a315032200..09115add57190 100644 --- a/lib/internal/Magento/Framework/App/AreaList/Proxy.php +++ b/lib/internal/Magento/Framework/App/AreaList/Proxy.php @@ -67,7 +67,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -82,7 +82,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/App/Response/Http.php b/lib/internal/Magento/Framework/App/Response/Http.php index 5716857fb2917..a80d9cbdd6689 100644 --- a/lib/internal/Magento/Framework/App/Response/Http.php +++ b/lib/internal/Magento/Framework/App/Response/Http.php @@ -189,7 +189,7 @@ public function representJson($content) */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['content', 'isRedirect', 'statusCode', 'context', 'headers']; } @@ -205,7 +205,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = ObjectManager::getInstance(); $this->cookieManager = $objectManager->create(\Magento\Framework\Stdlib\CookieManagerInterface::class); diff --git a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php index 6aecfed8b3481..5e79315238f7d 100644 --- a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php +++ b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php @@ -69,7 +69,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -84,7 +84,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/DB/Select.php b/lib/internal/Magento/Framework/DB/Select.php index ad570dbc2c8ae..f33aaea7d0e68 100644 --- a/lib/internal/Magento/Framework/DB/Select.php +++ b/lib/internal/Magento/Framework/DB/Select.php @@ -519,7 +519,7 @@ public function assemble() */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -543,7 +543,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_adapter = $objectManager->get(ResourceConnection::class)->getConnection(); diff --git a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php index a4415ce56d3b8..dc69b96b79050 100644 --- a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php +++ b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php @@ -65,7 +65,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -80,7 +80,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index 38208263c2089..2f3aaad98dfe5 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -895,7 +895,7 @@ public function hasFlag($flag) */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -918,7 +918,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_entityFactory = $objectManager->get(EntityFactoryInterface::class); diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index c0d3e73c90158..1b28e367dcc3a 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -896,7 +896,7 @@ private function getMainTableAlias() */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -913,7 +913,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php index 95348cc2828ed..b0f5742afef10 100644 --- a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php @@ -66,7 +66,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -81,7 +81,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Interception/Interceptor.php b/lib/internal/Magento/Framework/Interception/Interceptor.php index 4ad47f3bd95fd..df1b680234220 100644 --- a/lib/internal/Magento/Framework/Interception/Interceptor.php +++ b/lib/internal/Magento/Framework/Interception/Interceptor.php @@ -68,7 +68,7 @@ public function ___callParent($method, array $arguments) */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); if (method_exists(get_parent_class($this), '__sleep')) { $properties = parent::__sleep(); @@ -89,7 +89,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); if (method_exists(get_parent_class($this), '__wakeup')) { parent::__wakeup(); diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index 14255a586ec86..e1f6c792c9c3e 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -365,7 +365,7 @@ private function populateExtensionAttributes(array $extensionAttributesData = [] */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff(parent::__sleep(), ['extensionAttributesFactory', 'customAttributeFactory']); } @@ -378,7 +378,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php index 0c9340d283a4e..f5095dbb6e872 100644 --- a/lib/internal/Magento/Framework/Model/AbstractModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractModel.php @@ -225,7 +225,7 @@ protected function _init($resourceModel) */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -254,7 +254,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_registry = $objectManager->get(\Magento\Framework\Registry::class); diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php index 395724d6e480b..0cadb10aaafe2 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php @@ -162,7 +162,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff($properties, ['_resources', '_connections']); @@ -179,7 +179,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_resources = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\App\ResourceConnection::class); diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php index 11585a81de083..bc2187f474919 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php @@ -612,7 +612,7 @@ public function save() */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -629,7 +629,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php index 06b6f394a31f6..d67c380207554 100644 --- a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php @@ -64,7 +64,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['subject', 'isShared']; } @@ -79,7 +79,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php index cd0053e00ae17..e6d6cc57c2b09 100644 --- a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php +++ b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php @@ -64,7 +64,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['subject', 'isShared']; } @@ -79,7 +79,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/View/Layout/Proxy.php b/lib/internal/Magento/Framework/View/Layout/Proxy.php index 529412faa7a36..a3d89c6ec7a8e 100644 --- a/lib/internal/Magento/Framework/View/Layout/Proxy.php +++ b/lib/internal/Magento/Framework/View/Layout/Proxy.php @@ -66,7 +66,7 @@ public function __construct( */ public function __sleep() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -81,7 +81,7 @@ public function __sleep() */ public function __wakeup() { - throw new \RuntimeException('tst');//trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } From 7d584acbd86a034402047431479aee22759def88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= <bartlomiejszubert@gmail.com> Date: Tue, 23 Apr 2019 23:19:19 +0200 Subject: [PATCH 486/585] Fix #20111 - display variables in popup while editing existing email template --- app/code/Magento/Email/Model/Template.php | 2 +- .../Email/Test/Unit/Model/TemplateTest.php | 22 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Email/Model/Template.php b/app/code/Magento/Email/Model/Template.php index 8724b725ae489..3ee87cb81dfc4 100644 --- a/app/code/Magento/Email/Model/Template.php +++ b/app/code/Magento/Email/Model/Template.php @@ -326,7 +326,7 @@ public function getVariablesOptionArray($withGroup = false) $optionArray[] = ['value' => '{{' . $value . '}}', 'label' => __('%1', $label)]; } if ($withGroup) { - $optionArray = ['label' => __('Template Variables'), 'value' => $optionArray]; + $optionArray = [['label' => __('Template Variables'), 'value' => $optionArray]]; } } return $optionArray; diff --git a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php index 5464ca51cbe35..72aa3078d9067 100644 --- a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php @@ -598,16 +598,18 @@ public function getVariablesOptionArrayDataProvider() 'label' => __('Template Variables'), 'value' => [ [ - 'value' => '{{store url=""}}', - 'label' => __('%1', 'Store Url'), - ], - [ - 'value' => '{{var logo_url}}', - 'label' => __('%1', 'Email Logo Image Url'), - ], - [ - 'value' => '{{var customer.name}}', - 'label' => __('%1', 'Customer Name'), + [ + 'value' => '{{store url=""}}', + 'label' => __('%1', 'Store Url'), + ], + [ + 'value' => '{{var logo_url}}', + 'label' => __('%1', 'Email Logo Image Url'), + ], + [ + 'value' => '{{var customer.name}}', + 'label' => __('%1', 'Customer Name'), + ], ], ], ], From cf46fefa490ff578a4fe0498937cf1e3f08e806f Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 23 Apr 2019 17:57:27 -0500 Subject: [PATCH 487/585] GraphQL-526: Cannot return null for non-nullable field AvailableShippingMethod.method_code when no shipping methods are available --- .../ShippingAddress/AvailableShippingMethods.php | 9 +-------- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 7 ++++--- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php index d0bded279bee5..a9e0ba59d15d9 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php @@ -10,7 +10,6 @@ use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Config\Element\Field; -use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\Data\ShippingMethodInterface; @@ -66,19 +65,13 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $shippingRates = $address->getGroupedAllShippingRates(); foreach ($shippingRates as $carrierRates) { foreach ($carrierRates as $rate) { - $method = $this->dataObjectConverter->toFlatArray( + $methods[] = $this->dataObjectConverter->toFlatArray( $this->shippingMethodConverter->modelToDataObject($rate, $cart->getQuoteCurrencyCode()), [], ShippingMethodInterface::class ); - if ($method['available'] && $method['error_message'] === "") { - $methods[] = $method; - } } } - if (count($methods) === 0) { - throw new GraphQlNoSuchEntityException(__(' This shipping method is not available. To use this shipping method, please contact us.')); - } return $methods; } } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index a9784e97c8952..f6d3d0fe46149 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -231,13 +231,14 @@ type SelectedShippingMethod { type AvailableShippingMethod { carrier_code: String! carrier_title: String! - method_code: String! - method_title: String! + method_code: String @doc(description: "Could be null if method is not available") + method_title: String @doc(description: "Could be null if method is not available") error_message: String amount: Float! - base_amount: Float! + base_amount: Float @doc(description: "Could be null if method is not available") price_excl_tax: Float! price_incl_tax: Float! + available: Boolean! } type AvailablePaymentMethod { From 346955921625a290fb49ca3a21aaf5c6ea9c5810 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 23 Apr 2019 18:02:33 -0500 Subject: [PATCH 488/585] GraphQL-530: [Cart Operations] Update Cart Items validation messages --- .../Model/Resolver/UpdateCartItems.php | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php index 1af836c07e196..d5a47a013382b 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -16,6 +16,7 @@ use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\CartItemRepositoryInterface; use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Item; use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; /** @@ -111,24 +112,32 @@ private function processCartItems(Quote $cart, array $items): void $this->cartItemRepository->deleteById((int)$cart->getId(), $itemId); } else { $cartItem->setQty($qty); + $this->validateCartItem($cartItem); + $this->cartItemRepository->save($cartItem); + } + } + } - if ($cartItem->getHasError()) { - $errors = []; - foreach ($cartItem->getMessage(false) as $message) { - $errors[] = $message; - } - - if (!empty($errors)) { - throw new GraphQlInputException( - __( - 'Could not update the product with SKU %sku: %message', - ['sku' => $cartItem->getSku(), 'message' => __(implode("\n", $errors))] - ) - ); - } - } + /** + * @param Item $cartItem + * @return void + * @throws GraphQlInputException + */ + private function validateCartItem(Item $cartItem): void + { + if ($cartItem->getHasError()) { + $errors = []; + foreach ($cartItem->getMessage(false) as $message) { + $errors[] = $message; + } - $this->cartItemRepository->save($cartItem); + if (!empty($errors)) { + throw new GraphQlInputException( + __( + 'Could not update the product with SKU %sku: %message', + ['sku' => $cartItem->getSku(), 'message' => __(implode("\n", $errors))] + ) + ); } } } From 00ea747c8727420a0c107131721aedb013be25c0 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 23 Apr 2019 18:44:47 -0500 Subject: [PATCH 489/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- app/code/Magento/Authorization/Model/Role.php | 4 ++-- .../Magento/Catalog/Model/ResourceModel/Eav/Attribute.php | 4 ++-- app/code/Magento/Config/Model/Config/Backend/Encrypted.php | 4 ++-- .../Model/Product/Type/Configurable/Attribute.php | 4 ++-- .../Product/Type/Configurable/Attribute/Collection.php | 4 ++-- app/code/Magento/Customer/Model/Attribute.php | 4 ++-- app/code/Magento/Eav/Model/Entity/Attribute.php | 4 ++-- .../Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php | 4 ++-- app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php | 4 ++-- app/code/Magento/Store/Model/Store.php | 4 ++-- app/code/Magento/User/Model/User.php | 4 ++-- lib/internal/Magento/Framework/App/AreaList/Proxy.php | 4 ++-- lib/internal/Magento/Framework/App/Response/Http.php | 4 ++-- .../Magento/Framework/App/Route/ConfigInterface/Proxy.php | 4 ++-- lib/internal/Magento/Framework/DB/Select.php | 4 ++-- lib/internal/Magento/Framework/DB/Select/RendererProxy.php | 4 ++-- lib/internal/Magento/Framework/Data/Collection.php | 4 ++-- lib/internal/Magento/Framework/Data/Collection/AbstractDb.php | 4 ++-- .../Magento/Framework/DataObject/Copy/Config/Data/Proxy.php | 4 ++-- lib/internal/Magento/Framework/Interception/Interceptor.php | 4 ++-- .../Magento/Framework/Model/AbstractExtensibleModel.php | 4 ++-- lib/internal/Magento/Framework/Model/AbstractModel.php | 4 ++-- .../Magento/Framework/Model/ResourceModel/Db/AbstractDb.php | 4 ++-- .../Model/ResourceModel/Db/Collection/AbstractCollection.php | 4 ++-- lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php | 4 ++-- lib/internal/Magento/Framework/Translate/Inline/Proxy.php | 4 ++-- lib/internal/Magento/Framework/View/Layout/Proxy.php | 4 ++-- 27 files changed, 54 insertions(+), 54 deletions(-) diff --git a/app/code/Magento/Authorization/Model/Role.php b/app/code/Magento/Authorization/Model/Role.php index dcc46ee77ee12..d37b95cc5c9df 100644 --- a/app/code/Magento/Authorization/Model/Role.php +++ b/app/code/Magento/Authorization/Model/Role.php @@ -58,7 +58,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff($properties, ['_resource', '_resourceCollection']); @@ -72,7 +72,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index d56cc40ad0fc2..a29ca0e0d4b74 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -851,7 +851,7 @@ public function afterDelete() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('entity_type'); return array_diff( @@ -869,7 +869,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php index ea3b1d4c74a5f..d42075f33d94d 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php +++ b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php @@ -56,7 +56,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff($properties, ['_encryptor']); @@ -72,7 +72,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_encryptor = \Magento\Framework\App\ObjectManager::getInstance()->get( diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php index 4ead9ffe0fe70..4cc8305134760 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php @@ -271,7 +271,7 @@ public function setProductId($value) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -287,7 +287,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php index 81cbbd06c523c..46113a29b35c3 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php @@ -364,7 +364,7 @@ protected function getIncludedOptions(array $usedProducts, AbstractAttribute $pr */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -388,7 +388,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = ObjectManager::getInstance(); diff --git a/app/code/Magento/Customer/Model/Attribute.php b/app/code/Magento/Customer/Model/Attribute.php index ae714f993082e..615071846d158 100644 --- a/app/code/Magento/Customer/Model/Attribute.php +++ b/app/code/Magento/Customer/Model/Attribute.php @@ -208,7 +208,7 @@ public function canBeFilterableInGrid() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('entity_type'); return array_diff( @@ -225,7 +225,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute.php b/app/code/Magento/Eav/Model/Entity/Attribute.php index e23f81607a0c0..262fb8a32b393 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute.php @@ -502,7 +502,7 @@ public function getIdentities() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('attribute_set_info'); return array_diff( @@ -520,7 +520,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 9ed4ac5293681..cc7ccbf01b657 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -1410,7 +1410,7 @@ public function setExtensionAttributes(\Magento\Eav\Api\Data\AttributeExtensionI */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -1440,7 +1440,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php index 5e7226e7a36dd..50e3feb474797 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php @@ -731,7 +731,7 @@ public function getValidAttributeIds($attributeIds) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); $properties = array_diff($properties, ['_storeManager']); @@ -749,7 +749,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_storeManager = \Magento\Framework\App\ObjectManager::getInstance() diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index 4f69579c41bbb..ec3c631323b8d 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -429,7 +429,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); $properties = array_diff($properties, ['_coreFileStorageDatabase', '_config']); @@ -446,7 +446,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_coreFileStorageDatabase = ObjectManager::getInstance() diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index d8040b0bbaaac..e7f2fe1e2341b 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -218,7 +218,7 @@ protected function _construct() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff( @@ -251,7 +251,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/App/AreaList/Proxy.php b/lib/internal/Magento/Framework/App/AreaList/Proxy.php index 09115add57190..f430e8cf73bb6 100644 --- a/lib/internal/Magento/Framework/App/AreaList/Proxy.php +++ b/lib/internal/Magento/Framework/App/AreaList/Proxy.php @@ -67,7 +67,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -82,7 +82,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/App/Response/Http.php b/lib/internal/Magento/Framework/App/Response/Http.php index a80d9cbdd6689..d4ef4653261ca 100644 --- a/lib/internal/Magento/Framework/App/Response/Http.php +++ b/lib/internal/Magento/Framework/App/Response/Http.php @@ -189,7 +189,7 @@ public function representJson($content) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['content', 'isRedirect', 'statusCode', 'context', 'headers']; } @@ -205,7 +205,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = ObjectManager::getInstance(); $this->cookieManager = $objectManager->create(\Magento\Framework\Stdlib\CookieManagerInterface::class); diff --git a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php index 5e79315238f7d..44f8c0fae271f 100644 --- a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php +++ b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php @@ -69,7 +69,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -84,7 +84,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/DB/Select.php b/lib/internal/Magento/Framework/DB/Select.php index f33aaea7d0e68..7c5b0f671e233 100644 --- a/lib/internal/Magento/Framework/DB/Select.php +++ b/lib/internal/Magento/Framework/DB/Select.php @@ -519,7 +519,7 @@ public function assemble() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -543,7 +543,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_adapter = $objectManager->get(ResourceConnection::class)->getConnection(); diff --git a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php index dc69b96b79050..1d56a6f4e8af2 100644 --- a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php +++ b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php @@ -65,7 +65,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -80,7 +80,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index 2f3aaad98dfe5..83db7f77e9d11 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -895,7 +895,7 @@ public function hasFlag($flag) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -918,7 +918,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_entityFactory = $objectManager->get(EntityFactoryInterface::class); diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 1b28e367dcc3a..7dc3dfb7a73b9 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -896,7 +896,7 @@ private function getMainTableAlias() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -913,7 +913,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php index b0f5742afef10..8afdd3f3dd87f 100644 --- a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php @@ -66,7 +66,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -81,7 +81,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Interception/Interceptor.php b/lib/internal/Magento/Framework/Interception/Interceptor.php index df1b680234220..a40e7ded8b476 100644 --- a/lib/internal/Magento/Framework/Interception/Interceptor.php +++ b/lib/internal/Magento/Framework/Interception/Interceptor.php @@ -68,7 +68,7 @@ public function ___callParent($method, array $arguments) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); if (method_exists(get_parent_class($this), '__sleep')) { $properties = parent::__sleep(); @@ -89,7 +89,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); if (method_exists(get_parent_class($this), '__wakeup')) { parent::__wakeup(); diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index e1f6c792c9c3e..5cf7de21c9147 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -365,7 +365,7 @@ private function populateExtensionAttributes(array $extensionAttributesData = [] */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff(parent::__sleep(), ['extensionAttributesFactory', 'customAttributeFactory']); } @@ -378,7 +378,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php index f5095dbb6e872..3a526879f9d0a 100644 --- a/lib/internal/Magento/Framework/Model/AbstractModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractModel.php @@ -225,7 +225,7 @@ protected function _init($resourceModel) */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -254,7 +254,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_registry = $objectManager->get(\Magento\Framework\Registry::class); diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php index 0cadb10aaafe2..231c9bb1562ee 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php @@ -162,7 +162,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff($properties, ['_resources', '_connections']); @@ -179,7 +179,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_resources = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\App\ResourceConnection::class); diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php index bc2187f474919..da5e8f2e7506f 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php @@ -612,7 +612,7 @@ public function save() */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -629,7 +629,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php index d67c380207554..73970f6c9ca1f 100644 --- a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php @@ -64,7 +64,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['subject', 'isShared']; } @@ -79,7 +79,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php index e6d6cc57c2b09..5d7ee20fc5e77 100644 --- a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php +++ b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php @@ -64,7 +64,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['subject', 'isShared']; } @@ -79,7 +79,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/View/Layout/Proxy.php b/lib/internal/Magento/Framework/View/Layout/Proxy.php index a3d89c6ec7a8e..ef5f26f3a4bb8 100644 --- a/lib/internal/Magento/Framework/View/Layout/Proxy.php +++ b/lib/internal/Magento/Framework/View/Layout/Proxy.php @@ -66,7 +66,7 @@ public function __construct( */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -81,7 +81,7 @@ public function __sleep() */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } From 9e00ed29c722e0f77ea7e3dc98f7917dc2afdb9d Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Wed, 24 Apr 2019 09:36:30 +0300 Subject: [PATCH 490/585] static test fix --- app/code/Magento/Catalog/Setup/CategorySetup.php | 2 ++ .../Data/MigrateStoresAllowedCountriesToWebsite.php | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Setup/CategorySetup.php b/app/code/Magento/Catalog/Setup/CategorySetup.php index 581a5bf489194..f8542454bef92 100644 --- a/app/code/Magento/Catalog/Setup/CategorySetup.php +++ b/app/code/Magento/Catalog/Setup/CategorySetup.php @@ -53,6 +53,8 @@ use Magento\Theme\Model\Theme\Source\Theme; /** + * Setup category with default entities. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CategorySetup extends EavSetup diff --git a/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php b/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php index 8ed940250e213..e4978070f53ad 100644 --- a/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php +++ b/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php @@ -13,6 +13,9 @@ use Magento\Framework\Setup\Patch\DataPatchInterface; use Magento\Framework\Setup\Patch\PatchVersionInterface; +/** + * Migrate store allowed countries to website. + */ class MigrateStoresAllowedCountriesToWebsite implements DataPatchInterface, PatchVersionInterface { /** @@ -47,10 +50,11 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function apply() { + $this->moduleDataSetup->getConnection()->beginTransaction(); try { @@ -148,7 +152,7 @@ private function mergeAllowedCountries(array $countries, array $newCountries, $i } /** - * {@inheritdoc} + * @inheritdoc */ public static function getDependencies() { @@ -158,7 +162,7 @@ public static function getDependencies() } /** - * {@inheritdoc} + * @inheritdoc */ public static function getVersion() { @@ -166,7 +170,7 @@ public static function getVersion() } /** - * {@inheritdoc} + * @inheritdoc */ public function getAliases() { From 60e862f64975378c8c2d269fdde1d97d6621275c Mon Sep 17 00:00:00 2001 From: Keyur Kanani <keyurk@emiprotechnologies.com> Date: Wed, 24 Apr 2019 12:21:11 +0530 Subject: [PATCH 491/585] Fixed Dependency on Backup Settings Configuration --- app/code/Magento/Backup/etc/adminhtml/system.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Backup/etc/adminhtml/system.xml b/app/code/Magento/Backup/etc/adminhtml/system.xml index 90f6fa861b40f..aa6635b4dde4a 100644 --- a/app/code/Magento/Backup/etc/adminhtml/system.xml +++ b/app/code/Magento/Backup/etc/adminhtml/system.xml @@ -26,6 +26,7 @@ <label>Scheduled Backup Type</label> <depends> <field id="enabled">1</field> + <field id="functionality_enabled">1</field> </depends> <source_model>Magento\Backup\Model\Config\Source\Type</source_model> </field> @@ -33,12 +34,14 @@ <label>Start Time</label> <depends> <field id="enabled">1</field> + <field id="functionality_enabled">1</field> </depends> </field> <field id="frequency" translate="label" type="select" sortOrder="40" showInDefault="1" showInWebsite="0" showInStore="0"> <label>Frequency</label> <depends> <field id="enabled">1</field> + <field id="functionality_enabled">1</field> </depends> <source_model>Magento\Cron\Model\Config\Source\Frequency</source_model> <backend_model>Magento\Backup\Model\Config\Backend\Cron</backend_model> @@ -48,6 +51,7 @@ <comment>Please put your store into maintenance mode during backup.</comment> <depends> <field id="enabled">1</field> + <field id="functionality_enabled">1</field> </depends> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> From a27c3e0fb452d772e5af7e577d1c0b6ad2a231ef Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Wed, 24 Apr 2019 11:24:29 +0300 Subject: [PATCH 492/585] static test fix --- .../Framework/View/Layout/GeneratorPool.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Layout/GeneratorPool.php b/lib/internal/Magento/Framework/View/Layout/GeneratorPool.php index b899e34e6b39d..a585eda37df68 100644 --- a/lib/internal/Magento/Framework/View/Layout/GeneratorPool.php +++ b/lib/internal/Magento/Framework/View/Layout/GeneratorPool.php @@ -35,9 +35,9 @@ class GeneratorPool /** * @param ScheduledStructure\Helper $helper - * @param ConditionFactory $conditionFactory - * @param \Psr\Log\LoggerInterface $logger - * @param array $generators + * @param ConditionFactory $conditionFactory + * @param \Psr\Log\LoggerInterface $logger + * @param array|null $generators */ public function __construct( ScheduledStructure\Helper $helper, @@ -67,11 +67,10 @@ public function getGenerator($type) } /** - * Traverse through all generators and generate all scheduled elements + * Traverse through all generators and generate all scheduled elements. * - * @param Reader\Context $readerContext + * @param Reader\Context $readerContext * @param Generator\Context $generatorContext - * * @return $this */ public function process(Reader\Context $readerContext, Generator\Context $generatorContext) @@ -138,9 +137,9 @@ protected function buildStructure(ScheduledStructure $scheduledStructure, Data\S } /** - * Reorder a child of a specified element + * Reorder a child of a specified element. * - * @param ScheduledStructure $scheduledStructure, + * @param ScheduledStructure $scheduledStructure * @param Data\Structure $structure * @param string $elementName * @return void @@ -234,6 +233,8 @@ protected function moveElementInStructure( } /** + * Check visibility conditions exists in data. + * * @param array $data * * @return bool From 17774d57a7c8588073ab2dceb174abc7d251ce98 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 24 Apr 2019 12:04:34 +0300 Subject: [PATCH 493/585] magento/magento2#22470: Static test fix. --- .../Model/ResourceModel/Product/Collection.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index a50864e908331..cbcc7d513d36b 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -7,6 +7,8 @@ namespace Magento\Catalog\Model\ResourceModel\Product; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; +use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; use Magento\Catalog\Model\Product\Attribute\Source\Status as ProductStatus; use Magento\Catalog\Model\Product\Gallery\ReadHandler as GalleryReadHandler; use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; @@ -16,12 +18,10 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; use Magento\Framework\EntityManager\MetadataPool; -use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; -use Magento\Store\Model\Indexer\WebsiteDimensionProvider; -use Magento\Store\Model\Store; -use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; use Magento\Framework\Indexer\DimensionFactory; use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; +use Magento\Store\Model\Indexer\WebsiteDimensionProvider; +use Magento\Store\Model\Store; /** * Product collection @@ -32,10 +32,12 @@ * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.NumberOfChildren) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @since 100.0.2 */ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection { + /** * Alias for index table */ @@ -2284,6 +2286,7 @@ private function getBackend() public function addPriceDataFieldFilter($comparisonFormat, $fields) { if (!preg_match('/^%s( (<|>|=|<=|>=|<>) %s)*$/', $comparisonFormat)) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Invalid comparison format.'); } From 4f6a15a487656892490e3042ae7ffe395988b14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= <bartlomiejszubert@gmail.com> Date: Wed, 24 Apr 2019 11:23:24 +0200 Subject: [PATCH 494/585] Fix #20111 - fix unit test --- .../Email/Test/Unit/Model/TemplateTest.php | 156 ++++++++++-------- 1 file changed, 87 insertions(+), 69 deletions(-) diff --git a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php index 72aa3078d9067..9599cd1fef448 100644 --- a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php @@ -5,21 +5,37 @@ */ namespace Magento\Email\Test\Unit\Model; +use Magento\Email\Model\Template; +use Magento\Email\Model\Template\Config; +use Magento\Email\Model\Template\FilterFactory; +use Magento\Email\Model\TemplateFactory; use Magento\Framework\App\Area; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\TemplateTypesInterface; +use Magento\Framework\Filesystem; +use Magento\Framework\Filter\FilterManager; +use Magento\Framework\Model\Context; +use Magento\Framework\Registry; +use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\Url; +use Magento\Framework\View\Asset\Repository; use Magento\Setup\Module\I18n\Locale; +use Magento\Store\Model\App\Emulation; use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\StoreManager; +use Magento\Theme\Model\View\Design; +use PHPUnit\Framework\TestCase; /** * Covers \Magento\Email\Model\Template * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class TemplateTest extends \PHPUnit\Framework\TestCase +class TemplateTest extends TestCase { /** - * @var \Magento\Framework\Model\Context|\PHPUnit_Framework_MockObject_MockObject + * @var Context|\PHPUnit_Framework_MockObject_MockObject */ private $context; @@ -29,13 +45,13 @@ class TemplateTest extends \PHPUnit\Framework\TestCase private $design; /** - * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + * @var Registry|\PHPUnit_Framework_MockObject_MockObject * @deprecated since 2.3.0 in favor of stateful global objects elimination. */ private $registry; /** - * @var \Magento\Store\Model\App\Emulation|\PHPUnit_Framework_MockObject_MockObject + * @var Emulation|\PHPUnit_Framework_MockObject_MockObject */ private $appEmulation; @@ -45,53 +61,53 @@ class TemplateTest extends \PHPUnit\Framework\TestCase private $storeManager; /** - * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject + * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject */ private $filesystem; /** - * @var \Magento\Framework\View\Asset\Repository|\PHPUnit_Framework_MockObject_MockObject + * @var Repository|\PHPUnit_Framework_MockObject_MockObject */ private $assetRepo; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject */ private $scopeConfig; /** - * @var \Magento\Email\Model\Template\FilterFactory|\PHPUnit_Framework_MockObject_MockObject + * @var FilterFactory|\PHPUnit_Framework_MockObject_MockObject */ private $filterFactory; /** - * @var \Magento\Framework\Filter\FilterManager|\PHPUnit_Framework_MockObject_MockObject + * @var FilterManager|\PHPUnit_Framework_MockObject_MockObject */ private $filterManager; /** - * @var \Magento\Framework\Url|\PHPUnit_Framework_MockObject_MockObject + * @var Url|\PHPUnit_Framework_MockObject_MockObject */ private $urlModel; /** - * @var \Magento\Email\Model\Template\Config|\PHPUnit_Framework_MockObject_MockObject + * @var Config|\PHPUnit_Framework_MockObject_MockObject */ private $emailConfig; /** - * @var \Magento\Email\Model\TemplateFactory|\PHPUnit_Framework_MockObject_MockObject + * @var TemplateFactory|\PHPUnit_Framework_MockObject_MockObject */ private $templateFactory; /** - * @var \Magento\Framework\Serialize\Serializer\Json|\PHPUnit_Framework_MockObject_MockObject + * @var Json|\PHPUnit_Framework_MockObject_MockObject */ private $serializerMock; protected function setUp() { - $this->context = $this->getMockBuilder(\Magento\Framework\Model\Context::class) + $this->context = $this->getMockBuilder(Context::class) ->disableOriginalConstructor() ->getMock(); @@ -99,11 +115,11 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->registry = $this->getMockBuilder(\Magento\Framework\Registry::class) + $this->registry = $this->getMockBuilder(Registry::class) ->disableOriginalConstructor() ->getMock(); - $this->appEmulation = $this->getMockBuilder(\Magento\Store\Model\App\Emulation::class) + $this->appEmulation = $this->getMockBuilder(Emulation::class) ->disableOriginalConstructor() ->getMock(); @@ -111,51 +127,51 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->assetRepo = $this->getMockBuilder(\Magento\Framework\View\Asset\Repository::class) + $this->assetRepo = $this->getMockBuilder(Repository::class) ->disableOriginalConstructor() ->getMock(); - $this->filesystem = $this->getMockBuilder(\Magento\Framework\Filesystem::class) + $this->filesystem = $this->getMockBuilder(Filesystem::class) ->disableOriginalConstructor() ->getMock(); - $this->scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) + $this->scopeConfig = $this->getMockBuilder(ScopeConfigInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->emailConfig = $this->getMockBuilder(\Magento\Email\Model\Template\Config::class) + $this->emailConfig = $this->getMockBuilder(Config::class) ->disableOriginalConstructor() ->getMock(); - $this->templateFactory = $this->getMockBuilder(\Magento\Email\Model\TemplateFactory::class) + $this->templateFactory = $this->getMockBuilder(TemplateFactory::class) ->disableOriginalConstructor() ->getMock(); - $this->filterManager = $this->getMockBuilder(\Magento\Framework\Filter\FilterManager::class) + $this->filterManager = $this->getMockBuilder(FilterManager::class) ->disableOriginalConstructor() ->getMock(); - $this->urlModel = $this->getMockBuilder(\Magento\Framework\Url::class) + $this->urlModel = $this->getMockBuilder(Url::class) ->disableOriginalConstructor() ->getMock(); - $this->filterFactory = $this->getMockBuilder(\Magento\Email\Model\Template\FilterFactory::class) + $this->filterFactory = $this->getMockBuilder(FilterFactory::class) ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); - $this->serializerMock = $this->getMockBuilder(\Magento\Framework\Serialize\Serializer\Json::class)->getMock(); + $this->serializerMock = $this->getMockBuilder(Json::class)->getMock(); } /** * Return the model under test with additional methods mocked. * * @param array $mockedMethods - * @return \Magento\Email\Model\Template|\PHPUnit_Framework_MockObject_MockObject + * @return Template|\PHPUnit_Framework_MockObject_MockObject */ protected function getModelMock(array $mockedMethods = []) { - return $this->getMockBuilder(\Magento\Email\Model\Template::class) + return $this->getMockBuilder(Template::class) ->setMethods(array_merge($mockedMethods, ['__wakeup', '__sleep', '_init'])) ->setConstructorArgs([ $this->context, @@ -210,7 +226,7 @@ public function testGetTemplateFilterWithEmptyValue() ->method('setStoreId') ->will($this->returnSelf()); $this->filterFactory->method('create') - ->will($this->returnValue($filterTemplate)); + ->willReturn($filterTemplate); $designConfig = $this->getMockBuilder(\Magento\Framework\DataObject::class) ->setMethods(['getStore']) ->disableOriginalConstructor() @@ -219,7 +235,7 @@ public function testGetTemplateFilterWithEmptyValue() $model = $this->getModelMock(['getUseAbsoluteLinks', 'getDesignConfig']); $model->expects($this->once()) ->method('getDesignConfig') - ->will($this->returnValue($designConfig)); + ->willReturn($designConfig); $this->assertSame($filterTemplate, $model->getTemplateFilter()); } @@ -253,7 +269,7 @@ public function testLoadDefault( $model->expects($this->once()) ->method('getDesignParams') - ->will($this->returnValue($designParams)); + ->willReturn($designParams); $templateId = 'templateId'; @@ -261,11 +277,11 @@ public function testLoadDefault( $this->emailConfig->expects($this->once()) ->method('getTemplateFilename') ->with($templateId) - ->will($this->returnValue($templateFile)); + ->willReturn($templateFile); $this->emailConfig->expects($this->once()) ->method('getTemplateType') ->with($templateId) - ->will($this->returnValue($templateType)); + ->willReturn($templateType); $modulesDir = $this->getMockBuilder(\Magento\Framework\Filesystem\Directory\ReadInterface::class) ->setMethods(['readFile', 'getRelativePath']) @@ -275,15 +291,15 @@ public function testLoadDefault( $modulesDir->expects($this->once()) ->method('getRelativePath') ->with($templateFile) - ->will($this->returnValue($relativePath)); + ->willReturn($relativePath); $modulesDir->expects($this->once()) ->method('readFile') - ->will($this->returnValue($templateText)); + ->willReturn($templateText); $this->filesystem->expects($this->once()) ->method('getDirectoryRead') ->with(DirectoryList::ROOT) - ->will($this->returnValue($modulesDir)); + ->willReturn($modulesDir); $model->loadDefault($templateId); @@ -382,10 +398,10 @@ public function testLoadByConfigPath($loadFromDatabase) $storeId = 'storeId'; $designConfig->expects($this->once()) ->method('getStore') - ->will($this->returnValue($storeId)); + ->willReturn($storeId); $model->expects($this->once()) ->method('getDesignConfig') - ->will($this->returnValue($designConfig)); + ->willReturn($designConfig); if ($loadFromDatabase) { $templateId = '1'; @@ -404,7 +420,7 @@ public function testLoadByConfigPath($loadFromDatabase) $this->scopeConfig->expects($this->once()) ->method('getValue') ->with($configPath, ScopeInterface::SCOPE_STORE, $storeId) - ->will($this->returnValue($templateId)); + ->willReturn($templateId); $model->loadByConfigPath($configPath); } @@ -447,13 +463,13 @@ public function testIsValidForSend($senderName, $senderEmail, $templateSubject, $model = $this->getModelMock(['getSenderName', 'getSenderEmail', 'getTemplateSubject']); $model->expects($this->any()) ->method('getSenderName') - ->will($this->returnValue($senderName)); + ->willReturn($senderName); $model->expects($this->any()) ->method('getSenderEmail') - ->will($this->returnValue($senderEmail)); + ->willReturn($senderEmail); $model->expects($this->any()) ->method('getTemplateSubject') - ->will($this->returnValue($templateSubject)); + ->willReturn($templateSubject); $this->assertEquals($expectedValue, $model->isValidForSend()); } @@ -503,7 +519,7 @@ public function testGetProcessedTemplateSubject() ->getMock(); $model->expects($this->once()) ->method('getTemplateFilter') - ->will($this->returnValue($filterTemplate)); + ->willReturn($filterTemplate); $model->expects($this->once()) ->method('applyDesignConfig'); @@ -515,10 +531,10 @@ public function testGetProcessedTemplateSubject() $storeId = 'storeId'; $designConfig->expects($this->once()) ->method('getStore') - ->will($this->returnValue($storeId)); + ->willReturn($storeId); $model->expects($this->once()) ->method('getDesignConfig') - ->will($this->returnValue($designConfig)); + ->willReturn($designConfig); $filterTemplate->expects($this->once()) ->method('setStoreId') @@ -528,7 +544,7 @@ public function testGetProcessedTemplateSubject() $filterTemplate->expects($this->once()) ->method('filter') ->with($templateSubject) - ->will($this->returnValue($expectedResult)); + ->willReturn($expectedResult); $variables = [ 'key' => 'value' ]; $filterTemplate->expects($this->once()) @@ -595,9 +611,9 @@ public function getVariablesOptionArrayDataProvider() 'templateVariables' => '{"store url=\"\"":"Store Url","var logo_url":"Email Logo Image Url",' . '"var customer.name":"Customer Name"}', 'expectedResult' => [ - 'label' => __('Template Variables'), - 'value' => [ - [ + [ + 'label' => __('Template Variables'), + 'value' => [ [ 'value' => '{{store url=""}}', 'label' => __('%1', 'Store Url'), @@ -644,17 +660,17 @@ public function testProcessTemplate($templateId, $expectedResult) $model->expects($this->once()) ->method('applyDesignConfig') - ->will($this->returnValue(true)); + ->willReturn(true); $model->expects($this->once()) ->method('cancelDesignConfig') - ->will($this->returnValue(true)); + ->willReturn(true); $vars = [ 'key' => 'value' ]; $model->setVars($vars); $model->expects($this->once()) ->method('getProcessedTemplate') ->with($vars) - ->will($this->returnValue($expectedResult)); + ->willReturn($expectedResult); $this->assertEquals($expectedResult, $model->processTemplate()); $this->assertTrue($model->getUseAbsoluteLinks()); @@ -688,11 +704,11 @@ public function testProcessTemplateThrowsExceptionNonExistentTemplate() ]); $model->expects($this->once()) ->method('loadDefault') - ->will($this->returnValue(true)); + ->willReturn(true); $model->expects($this->once()) ->method('applyDesignConfig') - ->will($this->returnValue(true)); + ->willReturn(true); $model->processTemplate(); } @@ -706,7 +722,7 @@ public function testGetSubject() $model->expects($this->once()) ->method('getProcessedTemplateSubject') ->with($variables) - ->will($this->returnValue($expectedResult)); + ->willReturn($expectedResult); $this->assertEquals($expectedResult, $model->getSubject()); } @@ -727,30 +743,32 @@ public function testSetOptions() */ public function testGetType($templateType, $expectedResult) { - $emailConfig = $this->getMockBuilder(\Magento\Email\Model\Template\Config::class) + $emailConfig = $this->getMockBuilder(Config::class) ->setMethods(['getTemplateType']) ->disableOriginalConstructor() ->getMock(); $emailConfig->expects($this->once())->method('getTemplateType')->will($this->returnValue($templateType)); - /** @var \Magento\Email\Model\Template $model */ - $model = $this->getMockBuilder(\Magento\Email\Model\Template::class) + /** @var Template $model */ + $model = $this->getMockBuilder(Template::class) ->setMethods(['_init']) ->setConstructorArgs([ - $this->createMock(\Magento\Framework\Model\Context::class), - $this->createMock(\Magento\Theme\Model\View\Design::class), - $this->createMock(\Magento\Framework\Registry::class), - $this->createMock(\Magento\Store\Model\App\Emulation::class), - $this->createMock(\Magento\Store\Model\StoreManager::class), - $this->createMock(\Magento\Framework\View\Asset\Repository::class), - $this->createMock(\Magento\Framework\Filesystem::class), - $this->createMock(\Magento\Framework\App\Config\ScopeConfigInterface::class), + $this->createMock(Context::class), + $this->createMock(Design::class), + $this->createMock(Registry::class), + $this->createMock(Emulation::class), + $this->createMock(StoreManager::class), + $this->createMock(Repository::class), + $this->createMock(Filesystem::class), + $this->createMock(ScopeConfigInterface::class), $emailConfig, - $this->createMock(\Magento\Email\Model\TemplateFactory::class), - $this->createMock(\Magento\Framework\Filter\FilterManager::class), - $this->createMock(\Magento\Framework\Url::class), - $this->createMock(\Magento\Email\Model\Template\FilterFactory::class), + $this->createMock(TemplateFactory::class), + $this->createMock(FilterManager::class), + $this->createMock(Url::class), + $this->createMock(FilterFactory::class), + [], + $this->createMock(Json::class) ]) ->getMock(); From 65a61a5c8560f800824f2c18e0b53dad1dd49675 Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Wed, 24 Apr 2019 14:00:36 +0300 Subject: [PATCH 495/585] static, integration test fix --- app/code/Magento/Email/Model/Template.php | 2 ++ .../testsuite/Magento/Email/Model/TemplateTest.php | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Email/Model/Template.php b/app/code/Magento/Email/Model/Template.php index 3ee87cb81dfc4..ef2c4341dafa4 100644 --- a/app/code/Magento/Email/Model/Template.php +++ b/app/code/Magento/Email/Model/Template.php @@ -418,6 +418,8 @@ public function setOptions(array $options) } /** + * Return filter factory. + * * @return \Magento\Email\Model\Template\FilterFactory */ protected function getFilterFactory() diff --git a/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php b/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php index 7789a79794f39..2d12eefc286c6 100644 --- a/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php +++ b/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php @@ -703,8 +703,8 @@ public function testGetVariablesOptionArrayInGroup() $testTemplateVariables = '{"var data.name":"Sender Name","var data.email":"Sender Email"}'; $this->model->setOrigTemplateVariables($testTemplateVariables); $variablesOptionArray = $this->model->getVariablesOptionArray(true); - $this->assertEquals('Template Variables', $variablesOptionArray['label']->getText()); - $this->assertEquals($this->model->getVariablesOptionArray(), $variablesOptionArray['value']); + $this->assertEquals('Template Variables', $variablesOptionArray[0]['label']->getText()); + $this->assertEquals($this->model->getVariablesOptionArray(), $variablesOptionArray[0]['value']); } /** From 01764ece0bf9a47106d34911505a98d52588907a Mon Sep 17 00:00:00 2001 From: Andrii-Deineha <andrii.deineha@transoftgroup.com> Date: Wed, 24 Apr 2019 16:16:30 +0300 Subject: [PATCH 496/585] MC-11927: Update Attribute Set (Product Template) --- .../Test/TestCase/ProductAttribute/UpdateAttributeSetTest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.xml index 18b9a199cac04..18dc5c983ad79 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.xml @@ -8,7 +8,6 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\UpdateAttributeSetTest" summary="Update Attribute Set" ticketId="MAGETWO-26251"> <variation name="UpdateAttributeSetTestVariation1"> - <data name="tag" xsi:type="string">stable:no</data> <data name="attributeSet/data/attribute_set_name" xsi:type="string">AttributeSetEdit1%isolation%</data> <data name="attributeSet/data/group" xsi:type="string">Custom-group%isolation%</data> <data name="attributeSetOriginal/dataset" xsi:type="string">custom_attribute_set</data> From eb819132802b15a1c58bbc9c5eb3974dcb28be63 Mon Sep 17 00:00:00 2001 From: Yuliya Labudova <Yuliya_Labudova@epam.com> Date: Wed, 24 Apr 2019 16:39:37 +0300 Subject: [PATCH 497/585] MAGETWO-98584: Google chart API used by Magento dashboard scheduled to be turned off - Add functional test. --- .../Mftf/Section/AdminDashboardSection.xml | 19 +++ .../Test/AdminDashboardWithChartsChart.xml | 122 ++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminDashboardSection.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardWithChartsChart.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminDashboardSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminDashboardSection.xml new file mode 100644 index 0000000000000..664c335a4cfc6 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminDashboardSection.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminDashboardSection"> + <element name="dashboardDiagramContent" type="button" selector="#diagram_tab_content"/> + <element name="dashboardDiagramOrderContentTab" type="block" selector="#diagram_tab_orders_content"/> + <element name="dashboardDiagramAmounts" type="button" selector="#diagram_tab_amounts"/> + <element name="dashboardDiagramAmountsContentTab" type="block" selector="#diagram_tab_amounts_content"/> + <element name="dashboardDiagramTotals" type="text" selector="#diagram_tab_amounts_content"/> + <element name="dashboardTotals" type="text" selector="//*[@class='dashboard-totals-label' and contains(text(), '{{columnName}}')]/../*[@class='dashboard-totals-value']" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardWithChartsChart.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardWithChartsChart.xml new file mode 100644 index 0000000000000..55cb5a71505a5 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardWithChartsChart.xml @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminDashboardWithChartsTest"> + <annotations> + <features value="Backend"/> + <title value="Google chart on Magento dashboard"/> + <description value="Google chart on Magento dashboard page is not broken"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-98934"/> + <useCaseId value="MAGETWO-98584"/> + <group value="backend"/> + </annotations> + <before> + <magentoCLI command="config:set admin/dashboard/enable_charts 1" stepKey="setEnableCharts" /> + <createData entity="SimpleProduct2" stepKey="createProduct"> + <field key="price">150</field> + </createData> + <createData entity="Simple_US_Customer" stepKey="createCustomer"> + <field key="firstname">John1</field> + <field key="lastname">Doe1</field> + </createData> + </before> + <after> + <!-- Reset admin order filter --> + <comment userInput="Reset admin order filter" stepKey="resetAdminOrderFilter"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingOrderGrid"/> + <magentoCLI command="config:set admin/dashboard/enable_charts 0" stepKey="setDisableChartsAsDefault" /> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!-- Login as admin --> + <comment userInput="Login as admin" stepKey="adminLogin"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!-- Grab quantity value --> + <comment userInput="Grab quantity value from dashboard" stepKey="grabQuantityFromDashboard"/> + <grabTextFrom selector="{{AdminDashboardSection.dashboardTotals('Quantity')}}" stepKey="grabStartQuantity"/> + <!-- Login as customer --> + <comment userInput="Login as customer" stepKey="loginAsCustomer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> + <argument name="Customer" value="$$createCustomer$$" /> + </actionGroup> + <!-- Add Product to Shopping Cart--> + <comment userInput="Add product to the shopping cart" stepKey="addProductToCart"/> + <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToSimpleProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addToCartFromStorefrontProductPage"> + <argument name="productName" value="$$createProduct.name$$"/> + </actionGroup> + <!--Go to Checkout--> + <comment userInput="Go to checkout" stepKey="goToCheckout"/> + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingCheckoutPageWithShippingMethod"/> + <click selector="{{CheckoutShippingMethodsSection.firstShippingMethod}}" stepKey="selectFirstShippingMethod"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask1"/> + <waitForElement selector="{{CheckoutShippingMethodsSection.next}}" time="30" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickNext"/> + <!-- Checkout select Check/Money Order payment --> + <comment userInput="Select Check/Money payment" stepKey="checkoutSelectCheckMoneyPayment"/> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment"/> + <!-- Place Order --> + <comment userInput="Place order" stepKey="placeOrder"/> + <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder"/> + <see selector="{{CheckoutSuccessMainSection.successTitle}}" userInput="Thank you for your purchase!" stepKey="seeSuccessTitle"/> + <see selector="{{CheckoutSuccessMainSection.orderNumberText}}" userInput="Your order number is: " stepKey="seeOrderNumber"/> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> + <!-- Search for Order in the order grid --> + <comment userInput="Search for Order in the order grid" stepKey="searchOrderInGrid"/> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$grabOrderNumber"/> + </actionGroup> + <waitForLoadingMaskToDisappear stepKey="waitForSearchingOrder"/> + <!-- Create invoice --> + <comment userInput="Create invoice" stepKey="createInvoice"/> + <click selector="{{AdminOrdersGridSection.firstRow}}" stepKey="clickOrderRow"/> + <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceButton"/> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Invoice" stepKey="seeNewInvoiceInPageTitle" after="clickInvoiceButton"/> + <see selector="{{AdminInvoiceTotalSection.total('Subtotal')}}" userInput="$150.00" stepKey="seeCorrectGrandTotal"/> + <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="clickSubmitInvoice"/> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The invoice has been created." stepKey="seeSuccessInvoiceMessage"/> + <!--Create Shipment for the order--> + <comment userInput="Create Shipment for the order" stepKey="createShipmentForOrder"/> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="onOrdersPage2"/> + <waitForPageLoad time="30" stepKey="waitForOrderListPageLoading"/> + <click selector="{{AdminOrdersGridSection.firstRow}}" stepKey="openOrderPageForShip"/> + <waitForPageLoad stepKey="waitForOrderDetailsPage"/> + <click selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="clickShipAction"/> + <waitForPageLoad stepKey="waitForShipmentPagePage"/> + <seeInCurrentUrl url="{{AdminShipmentNewPage.url}}" stepKey="seeOrderShipmentUrl"/> + <!--Submit Shipment--> + <comment userInput="Submit Shipment" stepKey="submitShipment"/> + <click selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="clickSubmitShipment"/> + <waitForPageLoad stepKey="waitForShipmentSubmit"/> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The shipment has been created." stepKey="seeShipmentCreateSuccess"/> + <!-- Go to dashboard page --> + <comment userInput="Go to dashboard page" stepKey="goToDashboardPage"/> + <amOnPage url="{{AdminDashboardPage.url}}" stepKey="amOnDashboardPage"/> + <waitForPageLoad stepKey="waitForDashboardPageLoad4"/> + <!-- Grab quantity value --> + <comment userInput="Grab quantity value from dashboard at the end" stepKey="grabQuantityFromDashboardAtTheEnd"/> + <grabTextFrom selector="{{AdminDashboardSection.dashboardTotals('Quantity')}}" stepKey="grabEndQuantity"/> + <!-- Assert that page is not broken --> + <comment userInput="Assert that dashboard page is not broken" stepKey="assertDashboardPageIsNotBroken"/> + <seeElement selector="{{AdminDashboardSection.dashboardDiagramOrderContentTab}}" stepKey="seeOrderContentTab"/> + <seeElement selector="{{AdminDashboardSection.dashboardDiagramContent}}" stepKey="seeDiagramContent"/> + <click selector="{{AdminDashboardSection.dashboardDiagramAmounts}}" stepKey="clickDashboardAmount"/> + <waitForLoadingMaskToDisappear stepKey="waitForDashboardAmountLoading"/> + <seeElement selector="{{AdminDashboardSection.dashboardDiagramAmountsContentTab}}" stepKey="seeDiagramAmountContent"/> + <seeElement selector="{{AdminDashboardSection.dashboardDiagramTotals}}" stepKey="seeAmountTotals"/> + <dontSeeJsError stepKey="dontSeeJsError"/> + <assertGreaterThan expected="$grabStartQuantity" actual="$grabEndQuantity" stepKey="checkQuantityWasChanged"/> + </test> +</tests> From c147c603c98f8fa6eaff39d11b2c17c6c51b00a3 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 24 Apr 2019 10:40:21 -0500 Subject: [PATCH 498/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- app/code/Magento/Authorization/Model/Role.php | 4 ++-- .../Magento/Catalog/Model/ResourceModel/Eav/Attribute.php | 4 ++-- app/code/Magento/Config/Model/Config/Backend/Encrypted.php | 4 ++-- .../Model/Product/Type/Configurable/Attribute.php | 4 ++-- .../Product/Type/Configurable/Attribute/Collection.php | 4 ++-- app/code/Magento/Customer/Model/Attribute.php | 4 ++-- app/code/Magento/Eav/Model/Entity/Attribute.php | 4 ++-- .../Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php | 4 ++-- app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php | 4 ++-- app/code/Magento/Store/Model/Store.php | 4 ++-- app/code/Magento/User/Model/User.php | 4 ++-- lib/internal/Magento/Framework/App/AreaList/Proxy.php | 4 ++-- lib/internal/Magento/Framework/App/Response/Http.php | 4 ++-- .../Magento/Framework/App/Route/ConfigInterface/Proxy.php | 4 ++-- lib/internal/Magento/Framework/DB/Select.php | 4 ++-- lib/internal/Magento/Framework/DB/Select/RendererProxy.php | 4 ++-- lib/internal/Magento/Framework/Data/Collection.php | 4 ++-- lib/internal/Magento/Framework/Data/Collection/AbstractDb.php | 4 ++-- .../Magento/Framework/DataObject/Copy/Config/Data/Proxy.php | 4 ++-- lib/internal/Magento/Framework/Interception/Interceptor.php | 4 ++-- .../Magento/Framework/Model/AbstractExtensibleModel.php | 4 ++-- lib/internal/Magento/Framework/Model/AbstractModel.php | 4 ++-- .../Magento/Framework/Model/ResourceModel/Db/AbstractDb.php | 4 ++-- .../Model/ResourceModel/Db/Collection/AbstractCollection.php | 4 ++-- lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php | 4 ++-- lib/internal/Magento/Framework/Translate/Inline/Proxy.php | 4 ++-- lib/internal/Magento/Framework/View/Layout/Proxy.php | 4 ++-- 27 files changed, 54 insertions(+), 54 deletions(-) diff --git a/app/code/Magento/Authorization/Model/Role.php b/app/code/Magento/Authorization/Model/Role.php index d37b95cc5c9df..dcc46ee77ee12 100644 --- a/app/code/Magento/Authorization/Model/Role.php +++ b/app/code/Magento/Authorization/Model/Role.php @@ -58,7 +58,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff($properties, ['_resource', '_resourceCollection']); @@ -72,7 +72,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index a29ca0e0d4b74..d56cc40ad0fc2 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -851,7 +851,7 @@ public function afterDelete() */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('entity_type'); return array_diff( @@ -869,7 +869,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php index d42075f33d94d..ea3b1d4c74a5f 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php +++ b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php @@ -56,7 +56,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff($properties, ['_encryptor']); @@ -72,7 +72,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_encryptor = \Magento\Framework\App\ObjectManager::getInstance()->get( diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php index 4cc8305134760..4ead9ffe0fe70 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php @@ -271,7 +271,7 @@ public function setProductId($value) */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -287,7 +287,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php index 46113a29b35c3..81cbbd06c523c 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php @@ -364,7 +364,7 @@ protected function getIncludedOptions(array $usedProducts, AbstractAttribute $pr */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -388,7 +388,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = ObjectManager::getInstance(); diff --git a/app/code/Magento/Customer/Model/Attribute.php b/app/code/Magento/Customer/Model/Attribute.php index 615071846d158..ae714f993082e 100644 --- a/app/code/Magento/Customer/Model/Attribute.php +++ b/app/code/Magento/Customer/Model/Attribute.php @@ -208,7 +208,7 @@ public function canBeFilterableInGrid() */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('entity_type'); return array_diff( @@ -225,7 +225,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute.php b/app/code/Magento/Eav/Model/Entity/Attribute.php index 262fb8a32b393..e23f81607a0c0 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute.php @@ -502,7 +502,7 @@ public function getIdentities() */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->unsetData('attribute_set_info'); return array_diff( @@ -520,7 +520,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index cc7ccbf01b657..9ed4ac5293681 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -1410,7 +1410,7 @@ public function setExtensionAttributes(\Magento\Eav\Api\Data\AttributeExtensionI */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -1440,7 +1440,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php index 50e3feb474797..5e7226e7a36dd 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php @@ -731,7 +731,7 @@ public function getValidAttributeIds($attributeIds) */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); $properties = array_diff($properties, ['_storeManager']); @@ -749,7 +749,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_storeManager = \Magento\Framework\App\ObjectManager::getInstance() diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index ec3c631323b8d..4f69579c41bbb 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -429,7 +429,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); $properties = array_diff($properties, ['_coreFileStorageDatabase', '_config']); @@ -446,7 +446,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $this->_coreFileStorageDatabase = ObjectManager::getInstance() diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index e7f2fe1e2341b..d8040b0bbaaac 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -218,7 +218,7 @@ protected function _construct() */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = parent::__sleep(); return array_diff( @@ -251,7 +251,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/App/AreaList/Proxy.php b/lib/internal/Magento/Framework/App/AreaList/Proxy.php index f430e8cf73bb6..09115add57190 100644 --- a/lib/internal/Magento/Framework/App/AreaList/Proxy.php +++ b/lib/internal/Magento/Framework/App/AreaList/Proxy.php @@ -67,7 +67,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -82,7 +82,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/App/Response/Http.php b/lib/internal/Magento/Framework/App/Response/Http.php index d4ef4653261ca..a80d9cbdd6689 100644 --- a/lib/internal/Magento/Framework/App/Response/Http.php +++ b/lib/internal/Magento/Framework/App/Response/Http.php @@ -189,7 +189,7 @@ public function representJson($content) */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['content', 'isRedirect', 'statusCode', 'context', 'headers']; } @@ -205,7 +205,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = ObjectManager::getInstance(); $this->cookieManager = $objectManager->create(\Magento\Framework\Stdlib\CookieManagerInterface::class); diff --git a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php index 44f8c0fae271f..5e79315238f7d 100644 --- a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php +++ b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php @@ -69,7 +69,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -84,7 +84,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/DB/Select.php b/lib/internal/Magento/Framework/DB/Select.php index 7c5b0f671e233..f33aaea7d0e68 100644 --- a/lib/internal/Magento/Framework/DB/Select.php +++ b/lib/internal/Magento/Framework/DB/Select.php @@ -519,7 +519,7 @@ public function assemble() */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -543,7 +543,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_adapter = $objectManager->get(ResourceConnection::class)->getConnection(); diff --git a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php index 1d56a6f4e8af2..dc69b96b79050 100644 --- a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php +++ b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php @@ -65,7 +65,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -80,7 +80,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index 83db7f77e9d11..2f3aaad98dfe5 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -895,7 +895,7 @@ public function hasFlag($flag) */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -918,7 +918,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_entityFactory = $objectManager->get(EntityFactoryInterface::class); diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 7dc3dfb7a73b9..1b28e367dcc3a 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -896,7 +896,7 @@ private function getMainTableAlias() */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -913,7 +913,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php index 8afdd3f3dd87f..b0f5742afef10 100644 --- a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php @@ -66,7 +66,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -81,7 +81,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Interception/Interceptor.php b/lib/internal/Magento/Framework/Interception/Interceptor.php index a40e7ded8b476..df1b680234220 100644 --- a/lib/internal/Magento/Framework/Interception/Interceptor.php +++ b/lib/internal/Magento/Framework/Interception/Interceptor.php @@ -68,7 +68,7 @@ public function ___callParent($method, array $arguments) */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); if (method_exists(get_parent_class($this), '__sleep')) { $properties = parent::__sleep(); @@ -89,7 +89,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); if (method_exists(get_parent_class($this), '__wakeup')) { parent::__wakeup(); diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index 5cf7de21c9147..e1f6c792c9c3e 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -365,7 +365,7 @@ private function populateExtensionAttributes(array $extensionAttributesData = [] */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff(parent::__sleep(), ['extensionAttributesFactory', 'customAttributeFactory']); } @@ -378,7 +378,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php index 3a526879f9d0a..f5095dbb6e872 100644 --- a/lib/internal/Magento/Framework/Model/AbstractModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractModel.php @@ -225,7 +225,7 @@ protected function _init($resourceModel) */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff( @@ -254,7 +254,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_registry = $objectManager->get(\Magento\Framework\Registry::class); diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php index 231c9bb1562ee..0cadb10aaafe2 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php @@ -162,7 +162,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $properties = array_keys(get_object_vars($this)); $properties = array_diff($properties, ['_resources', '_connections']); @@ -179,7 +179,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_resources = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\App\ResourceConnection::class); diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php index da5e8f2e7506f..bc2187f474919 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php @@ -612,7 +612,7 @@ public function save() */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return array_diff( parent::__sleep(), @@ -629,7 +629,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); diff --git a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php index 73970f6c9ca1f..d67c380207554 100644 --- a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php @@ -64,7 +64,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['subject', 'isShared']; } @@ -79,7 +79,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php index 5d7ee20fc5e77..e6d6cc57c2b09 100644 --- a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php +++ b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php @@ -64,7 +64,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['subject', 'isShared']; } @@ -79,7 +79,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/View/Layout/Proxy.php b/lib/internal/Magento/Framework/View/Layout/Proxy.php index ef5f26f3a4bb8..a3d89c6ec7a8e 100644 --- a/lib/internal/Magento/Framework/View/Layout/Proxy.php +++ b/lib/internal/Magento/Framework/View/Layout/Proxy.php @@ -66,7 +66,7 @@ public function __construct( */ public function __sleep() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); return ['_subject', '_isShared']; } @@ -81,7 +81,7 @@ public function __sleep() */ public function __wakeup() { - //trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); + trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } From afa6c57cc12582f1a97b7b78ecd739e6a649f824 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 24 Apr 2019 11:43:55 -0500 Subject: [PATCH 499/585] GraphQL-530: [Cart Operations] Update Cart Items validation messages --- .../Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php index d5a47a013382b..25a79ae126ef8 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -119,6 +119,8 @@ private function processCartItems(Quote $cart, array $items): void } /** + * Validate cart item + * * @param Item $cartItem * @return void * @throws GraphQlInputException From ff06fcc3f2f3a42dbc921fd046ac95c4f0fe32ed Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Wed, 24 Apr 2019 12:06:07 -0500 Subject: [PATCH 500/585] MAGETWO-99307: Authorize.net Transaction Fails but Order goes through --- .../Gateway/Validator/TransactionResponseValidatorTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/AuthorizenetAcceptjs/Test/Unit/Gateway/Validator/TransactionResponseValidatorTest.php b/app/code/Magento/AuthorizenetAcceptjs/Test/Unit/Gateway/Validator/TransactionResponseValidatorTest.php index 1188c9c4107d2..c59cf00899af2 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/Test/Unit/Gateway/Validator/TransactionResponseValidatorTest.php +++ b/app/code/Magento/AuthorizenetAcceptjs/Test/Unit/Gateway/Validator/TransactionResponseValidatorTest.php @@ -15,6 +15,9 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +/** + * Tests for the transaction response validator + */ class TransactionResponseValidatorTest extends TestCase { private const RESPONSE_CODE_APPROVED = 1; From 72e62271922d49986f8954eaf7b30715564fd42a Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Wed, 24 Apr 2019 12:13:09 -0500 Subject: [PATCH 501/585] MQE-1519: Deliver weekly MTF conversion PR - Fix test failures from build - Selector had changed since it was originally delivered --- .../AssertStorefrontCheckoutCartItemsActionGroup.xml | 3 ++- .../Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml | 2 +- .../StorefrontAddBundleDynamicProductToShoppingCartTest.xml | 1 + ...amicProductToShoppingCartWithDisableMiniCartSidebarTest.xml | 1 + .../StorefrontAddConfigurableProductToShoppingCartTest.xml | 1 + .../StorefrontAddDownloadableProductToShoppingCartTest.xml | 1 + .../Test/StorefrontAddGroupedProductToShoppingCartTest.xml | 3 +++ ...frontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml | 1 + ...rontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml | 1 + 9 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml index df234da2e49cd..77a8bef9baf1c 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml @@ -10,6 +10,7 @@ <actionGroup name="AssertStorefrontCheckoutCartItemsActionGroup"> <arguments> <argument name="productName" type="string"/> + <argument name="productSku" type="string"/> <argument name="productPrice" type="string"/> <argument name="subtotal" type="string"/> <argument name="qty" type="string"/> @@ -17,6 +18,6 @@ <see selector="{{CheckoutCartProductSection.productName}}" userInput="{{productName}}" stepKey="seeProductNameInCheckoutSummary"/> <see selector="{{CheckoutCartProductSection.checkoutCartProductPrice}}" userInput="{{productPrice}}" stepKey="seeProductPriceInCart"/> <see selector="{{CheckoutCartProductSection.checkoutCartSubtotal}}" userInput="{{subtotal}}" stepKey="seeSubtotalPrice"/> - <seeElement selector="{{CheckoutCartProductSection.quantity(qty)}}" stepKey="seeProductQuantity" /> + <seeInField selector="{{CheckoutCartProductSection.qtyByContains(productSku)}}" userInput="{{qty}}" stepKey="seeProductQuantity"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml index 4bbb9a953653e..a5a1ce90e3312 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml @@ -34,10 +34,10 @@ <element name="productSubtotalByName" type="input" selector="//main//table[@id='shopping-cart-table']//tbody//tr[..//strong[contains(@class, 'product-item-name')]//a/text()='{{var1}}'][1]//td[contains(@class, 'subtotal')]//span[@class='price']" parameterized="true"/> <element name="updateShoppingCartButton" type="button" selector="#form-validate button[type='submit'].update" timeout="30"/> <element name="qty" type="input" selector="//input[@data-cart-item-id='{{var}}'][@title='Qty']" parameterized="true"/> + <element name="qtyByContains" type="text" selector="//input[contains(@data-cart-item-id, '{{sku}}')][@title='Qty']" parameterized="true"/> <element name="messageErrorItem" type="text" selector="#sku-stock-failed-"/> <element name="messageErrorNeedChooseOptions" type="text" selector="//*[contains(@class, 'error')]/div"/> <element name="productOptionsLink" type="text" selector="a.action.configure"/> - <element name="quantity" type="text" selector="//div[@class='field qty']//div/input[@value='{{qty}}']" parameterized="true"/> <element name="productOptionLabel" type="text" selector="//dl[@class='item-options']"/> <element name="checkoutCartProductPrice" type="text" selector="//td[@class='col price']//span[@class='price']"/> <element name="checkoutCartSubtotal" type="text" selector="//td[@class='col subtotal']//span[@class='price']"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml index 73f8f03e6d9ce..755c0cb9c93a0 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartTest.xml @@ -93,6 +93,7 @@ <!--Assert Product items in cart --> <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productSku" value="$$createBundleProduct.sku$$"/> <argument name="productPrice" value="$50.00"/> <argument name="subtotal" value="$100.00" /> <argument name="qty" value="2"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml index 938f56e61136b..afbc6216ff9ca 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml @@ -85,6 +85,7 @@ <!--Assert Product items in cart --> <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productSku" value="$$createBundleProduct.sku$$"/> <argument name="productPrice" value="$50.00"/> <argument name="subtotal" value="$100.00" /> <argument name="qty" value="2"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml index a0c9c07f9ff80..452f37e29b850 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml @@ -138,6 +138,7 @@ <!--Assert Product Details In Checkout cart --> <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertProductItemInCheckOutCart"> <argument name="productName" value="$$createConfigProduct.name$$"/> + <argument name="productSku" value="$$createConfigChildProduct2.sku$$"/> <argument name="productPrice" value="$$createConfigChildProduct2.price$$"/> <argument name="subtotal" value="$40.00" /> <argument name="qty" value="2"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml index ef49b6660a983..8a501ca7bc28f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml @@ -55,6 +55,7 @@ <!--Assert Product Details In Checkout cart --> <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertProductItemInCheckOutCart"> <argument name="productName" value="$$createDownloadableProduct.name$$"/> + <argument name="productSku" value="$$createDownloadableProduct.sku$$"/> <argument name="productPrice" value="$123.00"/> <argument name="subtotal" value="$123.00" /> <argument name="qty" value="1"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml index 26a2149081d19..a5fa13e15e64d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddGroupedProductToShoppingCartTest.xml @@ -67,6 +67,7 @@ <!--Assert Product1 items in cart --> <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> <argument name="productName" value="$$simple1.name$$"/> + <argument name="productSku" value="$$simple1.sku$$"/> <argument name="productPrice" value="$100.00"/> <argument name="subtotal" value="$100.00" /> <argument name="qty" value="1"/> @@ -75,6 +76,7 @@ <!--Assert Product2 items in cart --> <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct2ItemsInCheckOutCart"> <argument name="productName" value="$$simple2.name$$"/> + <argument name="productSku" value="$$simple2.sku$$"/> <argument name="productPrice" value="$200.00"/> <argument name="subtotal" value="$400.00" /> <argument name="qty" value="2"/> @@ -83,6 +85,7 @@ <!--Assert Product3 items in cart --> <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct3ItemsInCheckOutCart"> <argument name="productName" value="$$simple3.name$$"/> + <argument name="productSku" value="$$simple3.sku$$"/> <argument name="productPrice" value="$300.00"/> <argument name="subtotal" value="$900.00" /> <argument name="qty" value="3"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml index ee50310cd88b8..84c13eb13d48d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddOneBundleMultiSelectOptionToTheShoppingCartTest.xml @@ -92,6 +92,7 @@ <!--Assert Product items in cart --> <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productSku" value="$$createBundleProduct.sku$$"/> <argument name="productPrice" value="$50.00"/> <argument name="subtotal" value="$50.00" /> <argument name="qty" value="1"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml index 6bada4ce66b4d..83c25fb109d03 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddTwoBundleMultiSelectOptionsToTheShoppingCartTest.xml @@ -90,6 +90,7 @@ <!--Assert Product items in cart --> <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productSku" value="$$createBundleProduct.sku$$"/> <argument name="productPrice" value="$60.00"/> <argument name="subtotal" value="$60.00" /> <argument name="qty" value="1"/> From 4c11e115eedfe19feccb1a3766ab2c4c2172709a Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 24 Apr 2019 13:18:33 -0500 Subject: [PATCH 502/585] MAGETWO-96975: Remove __sleep and __wakeup from code --- .../Spi/SessionAclHydratorInterfaceTest.php | 58 ------------------- .../Spi/SessionUserHydratorInterfaceTest.php | 58 ------------------- 2 files changed, 116 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php delete mode 100644 dev/tests/integration/testsuite/Magento/Backend/Spi/SessionUserHydratorInterfaceTest.php diff --git a/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php b/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php deleted file mode 100644 index f3baaeebc137d..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionAclHydratorInterfaceTest.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -declare(strict_types=1); - -namespace Magento\Backend\Spi; - -use Magento\Framework\AclFactory; -use PHPUnit\Framework\TestCase; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\Framework\Acl\Builder as AclBuilder; - -/** - * Test for session hydrator. - */ -class SessionAclHydratorInterfaceTest extends TestCase -{ - /** - * @var SessionAclHydratorInterface - */ - private $hydrator; - - /** - * @var AclBuilder - */ - private $aclBuilder; - - /** - * @var AclFactory - */ - private $aclFactory; - - /** - * @inheritdoc - */ - protected function setUp() - { - $objectManager = Bootstrap::getObjectManager(); - $this->hydrator = $objectManager->get(SessionAclHydratorInterface::class); - $this->aclBuilder = $objectManager->get(AclBuilder::class); - $this->aclFactory = $objectManager->get(AclFactory::class); - } - - /** - * Test that ACL data is preserved. - */ - public function testHydrate() - { - $acl = $this->aclBuilder->getAcl(); - $data = $this->hydrator->extract($acl); - $this->hydrator->hydrate($built = $this->aclFactory->create(), $data); - $this->assertEquals($acl->getRoles(), $built->getRoles()); - $this->assertEquals($acl->getResources(), $built->getResources()); - } -} diff --git a/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionUserHydratorInterfaceTest.php b/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionUserHydratorInterfaceTest.php deleted file mode 100644 index e076a4fe1c387..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Backend/Spi/SessionUserHydratorInterfaceTest.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -declare(strict_types=1); - -namespace Magento\Backend\Spi; - -use PHPUnit\Framework\TestCase; -use Magento\User\Model\UserFactory; -use Magento\User\Model\User; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\Bootstrap as TestHelper; - -/** - * Test hydrator for user data in session. - */ -class SessionUserHydratorInterfaceTest extends TestCase -{ - /** - * @var SessionUserHydratorInterface - */ - private $hydrator; - - /** - * @var UserFactory - */ - private $userFactory; - - /** - * @inheritdoc - */ - protected function setUp() - { - $objectManager = Bootstrap::getObjectManager(); - $this->hydrator = $objectManager->get(SessionUserHydratorInterface::class); - $this->userFactory = $objectManager->get(UserFactory::class); - } - - /** - * Make sure users' data is preserved during extract/hydrate. - */ - public function testHydrate() - { - /** @var User $user */ - $user = $this->userFactory->create(); - $user->loadByUsername(TestHelper::ADMIN_NAME); - - $userData = $this->hydrator->extract($user); - /** @var User $newUser */ - $newUser = $this->userFactory->create(); - $this->hydrator->hydrate($newUser, $userData); - $this->assertEquals($user->getData(), $newUser->getData()); - $this->assertEquals($user->getRole()->getId(), $newUser->getRole()->getId()); - } -} From 06019a6215ea31982494708d55745ae0b9622696 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Wed, 24 Apr 2019 15:51:54 -0500 Subject: [PATCH 503/585] MC-15995: Revert change of PR 3766 --- .../ResourceModel/Category/Collection.php | 9 +- .../Collection/AbstractCollection.php | 10 +- .../ResourceModel/Product/Collection.php | 11 +- .../Product/Compare/Item/Collection.php | 30 +-- .../ResourceModel/Product/CollectionTest.php | 226 ++++++++++++------ .../Product/Link/Product/CollectionTest.php | 32 ++- .../ResourceModel/Advanced/Collection.php | 18 +- .../ResourceModel/Fulltext/Collection.php | 19 +- .../Model/ResourceModel/Search/Collection.php | 31 +-- .../ResourceModel/Advanced/CollectionTest.php | 4 +- .../Model/ResourceModel/BaseCollection.php | 22 +- .../ResourceModel/Fulltext/CollectionTest.php | 6 +- .../ResourceModel/Customer/Collection.php | 9 +- .../Entity/Collection/AbstractCollection.php | 21 +- .../VersionControl/AbstractCollection.php | 17 +- app/code/Magento/Eav/Model/Entity/Type.php | 22 +- .../Collection/AbstractCollectionTest.php | 23 +- .../VersionControl/AbstractCollectionTest.php | 2 +- .../Grouped/AssociatedProductsCollection.php | 30 +-- .../ResourceModel/Customer/Collection.php | 12 +- .../ResourceModel/Product/Collection.php | 34 +-- .../Index/Collection/AbstractCollection.php | 34 +-- .../Product/Lowstock/Collection.php | 34 +-- .../ResourceModel/Product/CollectionTest.php | 141 ++++++----- .../Review/Product/Collection.php | 22 +- app/etc/di.xml | 1 - .../Model/ResourceModel/ResourceModelPool.php | 36 --- .../ResourceModelPoolInterface.php | 23 -- 28 files changed, 345 insertions(+), 534 deletions(-) delete mode 100644 lib/internal/Magento/Framework/Model/ResourceModel/ResourceModelPool.php delete mode 100644 lib/internal/Magento/Framework/Model/ResourceModel/ResourceModelPoolInterface.php diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php index b5668a12f94a5..657daca13055e 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php @@ -7,7 +7,6 @@ use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator; use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; use Magento\Store\Model\ScopeInterface; /** @@ -83,8 +82,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * - * @param ResourceModelPoolInterface|null $resourceModelPool * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -99,8 +96,7 @@ public function __construct( \Magento\Framework\Validator\UniversalFactory $universalFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig = null, - ResourceModelPoolInterface $resourceModelPool = null + \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig = null ) { parent::__construct( $entityFactory, @@ -113,8 +109,7 @@ public function __construct( $resourceHelper, $universalFactory, $storeManager, - $connection, - $resourceModelPool + $connection ); $this->scopeConfig = $scopeConfig ?: \Magento\Framework\App\ObjectManager::getInstance()->get(ScopeConfigInterface::class); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Collection/AbstractCollection.php b/app/code/Magento/Catalog/Model/ResourceModel/Collection/AbstractCollection.php index 2e40d13f1ccac..3a0d47fe573fb 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Collection/AbstractCollection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Collection/AbstractCollection.php @@ -5,8 +5,6 @@ */ namespace Magento\Catalog\Model\ResourceModel\Collection; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Catalog EAV collection resource abstract model * @@ -45,8 +43,6 @@ class AbstractCollection extends \Magento\Eav\Model\Entity\Collection\AbstractCo * @param \Magento\Framework\Validator\UniversalFactory $universalFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection - * - * @param ResourceModelPoolInterface|null $resourceModelPool * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -60,8 +56,7 @@ public function __construct( \Magento\Eav\Model\ResourceModel\Helper $resourceHelper, \Magento\Framework\Validator\UniversalFactory $universalFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - ResourceModelPoolInterface $resourceModelPool = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null ) { $this->_storeManager = $storeManager; parent::__construct( @@ -74,8 +69,7 @@ public function __construct( $eavEntityFactory, $resourceHelper, $universalFactory, - $connection, - $resourceModelPool + $connection ); } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index 136c7e800bf08..9a030e0c37355 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -21,7 +21,6 @@ use Magento\Store\Model\Store; use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; /** * Product collection @@ -32,6 +31,7 @@ * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.NumberOfChildren) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @since 100.0.2 */ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection @@ -324,7 +324,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac * @param TableMaintainer|null $tableMaintainer * @param PriceTableResolver|null $priceTableResolver * @param DimensionFactory|null $dimensionFactory - * @param ResourceModelPoolInterface|null $resourceModelPool * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -353,8 +352,7 @@ public function __construct( MetadataPool $metadataPool = null, TableMaintainer $tableMaintainer = null, PriceTableResolver $priceTableResolver = null, - DimensionFactory $dimensionFactory = null, - ResourceModelPoolInterface $resourceModelPool = null + DimensionFactory $dimensionFactory = null ) { $this->moduleManager = $moduleManager; $this->_catalogProductFlatState = $catalogProductFlatState; @@ -382,8 +380,7 @@ public function __construct( $resourceHelper, $universalFactory, $storeManager, - $connection, - $resourceModelPool + $connection ); $this->tableMaintainer = $tableMaintainer ?: ObjectManager::getInstance()->get(TableMaintainer::class); $this->priceTableResolver = $priceTableResolver ?: ObjectManager::getInstance()->get(PriceTableResolver::class); @@ -1979,6 +1976,7 @@ protected function _productLimitationPrice($joinLeft = false) } // Set additional field filters foreach ($this->_priceDataFieldFilters as $filterData) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction $select->where(call_user_func_array('sprintf', $filterData)); } } else { @@ -2284,6 +2282,7 @@ private function getBackend() public function addPriceDataFieldFilter($comparisonFormat, $fields) { if (!preg_match('/^%s( (<|>|=|<=|>=|<>) %s)*$/', $comparisonFormat)) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Invalid comparison format.'); } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Compare/Item/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Compare/Item/Collection.php index a45e2060d7c20..aa6fb8c1f8827 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Compare/Item/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Compare/Item/Collection.php @@ -5,13 +5,6 @@ */ namespace Magento\Catalog\Model\ResourceModel\Product\Compare\Item; -use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; -use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; -use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Catalog Product Compare Items Resource Collection * @@ -19,6 +12,7 @@ * @author Magento Core Team <core@magentocommerce.com> * @SuppressWarnings(PHPMD.LongVariable) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @since 100.0.2 */ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection @@ -82,12 +76,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param \Magento\Catalog\Model\ResourceModel\Product\Compare\Item $catalogProductCompareItem * @param \Magento\Catalog\Helper\Product\Compare $catalogProductCompare * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection - * @param ProductLimitationFactory|null $productLimitationFactory - * @param MetadataPool|null $metadataPool - * @param TableMaintainer|null $tableMaintainer - * @param PriceTableResolver|null $priceTableResolver - * @param DimensionFactory|null $dimensionFactory - * @param ResourceModelPoolInterface|null $resourceModelPool * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -112,13 +100,7 @@ public function __construct( \Magento\Customer\Api\GroupManagementInterface $groupManagement, \Magento\Catalog\Model\ResourceModel\Product\Compare\Item $catalogProductCompareItem, \Magento\Catalog\Helper\Product\Compare $catalogProductCompare, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - ProductLimitationFactory $productLimitationFactory = null, - MetadataPool $metadataPool = null, - TableMaintainer $tableMaintainer = null, - PriceTableResolver $priceTableResolver = null, - DimensionFactory $dimensionFactory = null, - ResourceModelPoolInterface $resourceModelPool = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null ) { $this->_catalogProductCompareItem = $catalogProductCompareItem; $this->_catalogProductCompare = $catalogProductCompare; @@ -142,13 +124,7 @@ public function __construct( $customerSession, $dateTime, $groupManagement, - $connection, - $productLimitationFactory, - $metadataPool, - $tableMaintainer, - $priceTableResolver, - $dimensionFactory, - $resourceModelPool + $connection ); } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php index 5da5625189ee3..0316b2e374d2f 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php @@ -5,33 +5,13 @@ */ namespace Magento\Catalog\Test\Unit\Model\ResourceModel\Product; -use Magento\Catalog\Model\Indexer; -use Magento\Catalog\Model\Product as ProductModel; -use Magento\Catalog\Model\ResourceModel\Product as ProductResource; use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; use Magento\Framework\DB\Select; -use Magento\Eav\Model\Entity\AbstractEntity; -use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; -use Magento\Eav\Model\EntityFactory; -use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\App\ResourceConnection; -use Magento\Framework\Data\Collection; -use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; -use Magento\Framework\DB; -use Magento\Framework\EntityManager\EntityMetadataInterface; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Event; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; -use Magento\Framework\Stdlib\DateTime\TimezoneInterface; -use Magento\Store\Api\Data\StoreInterface; -use Magento\Store\Model\StoreManagerInterface; -use PHPUnit\Framework\TestCase; -use Psr\Log\LoggerInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class CollectionTest extends TestCase +class CollectionTest extends \PHPUnit\Framework\TestCase { /** * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager @@ -44,12 +24,12 @@ class CollectionTest extends TestCase protected $selectMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject|DB\Adapter\AdapterInterface + * @var \PHPUnit_Framework_MockObject_MockObject */ protected $connectionMock; /** - * @var ProductResource\Collection + * @var \Magento\Catalog\Model\ResourceModel\Product\Collection */ protected $collection; @@ -90,50 +70,121 @@ protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->entityFactory = $this->createMock(\Magento\Framework\Data\Collection\EntityFactory::class); - $this->selectMock = $this->createMock(DB\Select::class); - $this->connectionMock = $this->createMock(DB\Adapter\AdapterInterface::class); - $this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock); - $this->entityMock = $this->createMock(AbstractEntity::class); + $logger = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $fetchStrategy = $this->getMockBuilder(\Magento\Framework\Data\Collection\Db\FetchStrategyInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $eventManager = $this->getMockBuilder(\Magento\Framework\Event\ManagerInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $eavConfig = $this->getMockBuilder(\Magento\Eav\Model\Config::class) + ->disableOriginalConstructor() + ->getMock(); + $resource = $this->getMockBuilder(\Magento\Framework\App\ResourceConnection::class) + ->disableOriginalConstructor() + ->getMock(); + $eavEntityFactory = $this->getMockBuilder(\Magento\Eav\Model\EntityFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $resourceHelper = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Helper::class) + ->disableOriginalConstructor() + ->getMock(); + $universalFactory = $this->getMockBuilder(\Magento\Framework\Validator\UniversalFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getStore', 'getId', 'getWebsiteId']) + ->getMockForAbstractClass(); + $moduleManager = $this->getMockBuilder(\Magento\Framework\Module\Manager::class) + ->disableOriginalConstructor() + ->getMock(); + $catalogProductFlatState = $this->getMockBuilder(\Magento\Catalog\Model\Indexer\Product\Flat\State::class) + ->disableOriginalConstructor() + ->getMock(); + $scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $productOptionFactory = $this->getMockBuilder(\Magento\Catalog\Model\Product\OptionFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $catalogUrl = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Url::class) + ->disableOriginalConstructor() + ->getMock(); + $localeDate = $this->getMockBuilder(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $customerSession = $this->getMockBuilder(\Magento\Customer\Model\Session::class) + ->disableOriginalConstructor() + ->getMock(); + $dateTime = $this->getMockBuilder(\Magento\Framework\Stdlib\DateTime::class) + ->disableOriginalConstructor() + ->getMock(); + $groupManagement = $this->getMockBuilder(\Magento\Customer\Api\GroupManagementInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->connectionMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class) + ->setMethods(['getId']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class) + ->disableOriginalConstructor() + ->getMock(); + $this->entityMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\AbstractEntity::class) + ->disableOriginalConstructor() + ->getMock(); + $this->galleryResourceMock = $this->getMockBuilder( + \Magento\Catalog\Model\ResourceModel\Product\Gallery::class + )->disableOriginalConstructor()->getMock(); + $this->metadataPoolMock = $this->getMockBuilder( + \Magento\Framework\EntityManager\MetadataPool::class + )->disableOriginalConstructor()->getMock(); + $this->galleryReadHandlerMock = $this->getMockBuilder( + \Magento\Catalog\Model\Product\Gallery\ReadHandler::class + )->disableOriginalConstructor()->getMock(); + $this->storeManager->expects($this->any())->method('getId')->willReturn(1); + $this->storeManager->expects($this->any())->method('getStore')->willReturnSelf(); + $universalFactory->expects($this->exactly(1))->method('create')->willReturnOnConsecutiveCalls( + $this->entityMock + ); $this->entityMock->expects($this->once())->method('getConnection')->willReturn($this->connectionMock); $this->entityMock->expects($this->once())->method('getDefaultAttributes')->willReturn([]); - $this->entityMock->method('getTable')->willReturnArgument(0); - $this->galleryResourceMock = $this->createMock(ProductResource\Gallery::class); - $this->metadataPoolMock = $this->createMock(MetadataPool::class); - $this->galleryReadHandlerMock = $this->createMock(ProductModel\Gallery\ReadHandler::class); + $this->entityMock->expects($this->any())->method('getTable')->willReturnArgument(0); + $this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock); - $storeStub = $this->createMock(StoreInterface::class); - $storeStub->method('getId')->willReturn(1); - $storeStub->method('getWebsiteId')->willReturn(1); - $this->storeManager = $this->createMock(StoreManagerInterface::class); - $this->storeManager->method('getStore')->willReturn($storeStub); - $resourceModelPool = $this->createMock(ResourceModelPoolInterface::class); - $resourceModelPool->expects($this->exactly(1))->method('get')->willReturn($this->entityMock); + $productLimitationMock = $this->createMock( + \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class + ); + $productLimitationFactoryMock = $this->getMockBuilder( + ProductLimitationFactory::class + )->disableOriginalConstructor()->setMethods(['create'])->getMock(); - $productLimitationFactoryMock = $this->createPartialMock(ProductLimitationFactory::class, ['create']); $productLimitationFactoryMock->method('create') - ->willReturn($this->createMock(ProductResource\Collection\ProductLimitation::class)); + ->willReturn($productLimitationMock); $this->collection = $this->objectManager->getObject( - ProductResource\Collection::class, + \Magento\Catalog\Model\ResourceModel\Product\Collection::class, [ 'entityFactory' => $this->entityFactory, - 'logger' => $this->createMock(LoggerInterface::class), - 'fetchStrategy' => $this->createMock(FetchStrategyInterface::class), - 'eventManager' => $this->createMock(Event\ManagerInterface::class), - 'eavConfig' => $this->createMock(\Magento\Eav\Model\Config::class), - 'resource' => $this->createMock(ResourceConnection::class), - 'eavEntityFactory' => $this->createMock(EntityFactory::class), - 'resourceHelper' => $this->createMock(\Magento\Catalog\Model\ResourceModel\Helper::class), - 'resourceModelPool' => $resourceModelPool, + 'logger' => $logger, + 'fetchStrategy' => $fetchStrategy, + 'eventManager' => $eventManager, + 'eavConfig' => $eavConfig, + 'resource' => $resource, + 'eavEntityFactory' => $eavEntityFactory, + 'resourceHelper' => $resourceHelper, + 'universalFactory' => $universalFactory, 'storeManager' => $this->storeManager, - 'moduleManager' => $this->createMock(\Magento\Framework\Module\Manager::class), - 'catalogProductFlatState' => $this->createMock(Indexer\Product\Flat\State::class), - 'scopeConfig' => $this->createMock(ScopeConfigInterface::class), - 'productOptionFactory' => $this->createMock(ProductModel\OptionFactory::class), - 'catalogUrl' => $this->createMock(\Magento\Catalog\Model\ResourceModel\Url::class), - 'localeDate' => $this->createMock(TimezoneInterface::class), - 'customerSession' => $this->createMock(\Magento\Customer\Model\Session::class), - 'dateTime' => $this->createMock(\Magento\Framework\Stdlib\DateTime::class), - 'groupManagement' => $this->createMock(\Magento\Customer\Api\GroupManagementInterface::class), + 'moduleManager' => $moduleManager, + 'catalogProductFlatState' => $catalogProductFlatState, + 'scopeConfig' => $scopeConfig, + 'productOptionFactory' => $productOptionFactory, + 'catalogUrl' => $catalogUrl, + 'localeDate' => $localeDate, + 'customerSession' => $customerSession, + 'dateTime' => $dateTime, + 'groupManagement' => $groupManagement, 'connection' => $this->connectionMock, 'productLimitationFactory' => $productLimitationFactoryMock, 'metadataPool' => $this->metadataPoolMock, @@ -158,8 +209,9 @@ public function testAddProductCategoriesFilter() $condition = ['in' => [1, 2]]; $values = [1, 2]; $conditionType = 'nin'; - $preparedSql = 'category_id IN(1,2)'; - $tableName = 'catalog_category_product'; + $preparedSql = "category_id IN(1,2)"; + $tableName = "catalog_category_product"; + $this->connectionMock->expects($this->any())->method('getId')->willReturn(1); $this->connectionMock->expects($this->exactly(2))->method('prepareSqlCondition')->withConsecutive( ['cat.category_id', $condition], ['e.entity_id', [$conditionType => $this->selectMock]] @@ -184,14 +236,19 @@ public function testAddMediaGalleryData() $rowId = 4; $linkField = 'row_id'; $mediaGalleriesMock = [[$linkField => $rowId]]; - /** @var ProductModel|\PHPUnit_Framework_MockObject_MockObject $itemMock */ - $itemMock = $this->getMockBuilder(ProductModel::class) + $itemMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->disableOriginalConstructor() ->setMethods(['getOrigData']) ->getMock(); - $attributeMock = $this->createMock(AbstractAttribute::class); - $selectMock = $this->createMock(DB\Select::class); - $metadataMock = $this->createMock(EntityMetadataInterface::class); + $attributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class) + ->disableOriginalConstructor() + ->getMock(); + $selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class) + ->disableOriginalConstructor() + ->getMock(); + $metadataMock = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadataInterface::class) + ->disableOriginalConstructor() + ->getMock(); $this->collection->addItem($itemMock); $this->galleryResourceMock->expects($this->once())->method('createBatchBaseSelect')->willReturn($selectMock); $attributeMock->expects($this->once())->method('getAttributeId')->willReturn($attributeId); @@ -221,15 +278,25 @@ public function testAddMediaGalleryData() public function testAddTierPriceDataByGroupId() { $customerGroupId = 2; - /** @var ProductModel|\PHPUnit_Framework_MockObject_MockObject $itemMock */ - $itemMock = $this->createMock(ProductModel::class); - $attributeMock = $this->getMockBuilder(AbstractAttribute::class) + $itemMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + ->disableOriginalConstructor() + ->setMethods(['getData']) + ->getMock(); + $attributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class) ->disableOriginalConstructor() ->setMethods(['isScopeGlobal', 'getBackend']) ->getMock(); - $backend = $this->createMock(ProductModel\Attribute\Backend\Tierprice::class); - $resource = $this->createMock(ProductResource\Attribute\Backend\GroupPrice\AbstractGroupPrice::class); - $select = $this->createMock(DB\Select::class); + $backend = $this->getMockBuilder(\Magento\Catalog\Model\Product\Attribute\Backend\Tierprice::class) + ->disableOriginalConstructor() + ->getMock(); + $resource = $this->getMockBuilder( + \Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\GroupPrice\AbstractGroupPrice::class + ) + ->disableOriginalConstructor() + ->getMock(); + $select = $this->getMockBuilder(\Magento\Framework\DB\Select::class) + ->disableOriginalConstructor() + ->getMock(); $this->connectionMock->expects($this->once())->method('getAutoIncrementField')->willReturn('entity_id'); $this->collection->addItem($itemMock); $itemMock->expects($this->atLeastOnce())->method('getData')->with('entity_id')->willReturn(1); @@ -239,6 +306,7 @@ public function testAddTierPriceDataByGroupId() ->willReturn($attributeMock); $attributeMock->expects($this->atLeastOnce())->method('getBackend')->willReturn($backend); $attributeMock->expects($this->once())->method('isScopeGlobal')->willReturn(false); + $this->storeManager->expects($this->once())->method('getWebsiteId')->willReturn(1); $backend->expects($this->once())->method('getResource')->willReturn($resource); $resource->expects($this->once())->method('getSelect')->willReturn($select); $select->expects($this->once())->method('columns')->with(['product_id' => 'entity_id'])->willReturnSelf(); @@ -265,22 +333,25 @@ public function testAddTierPriceDataByGroupId() */ public function testAddTierPriceData() { - /** @var ProductModel|\PHPUnit_Framework_MockObject_MockObject $itemMock */ - $itemMock = $this->getMockBuilder(ProductModel::class) + $itemMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->disableOriginalConstructor() ->setMethods(['getData']) ->getMock(); - $attributeMock = $this->getMockBuilder(AbstractAttribute::class) + $attributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class) ->disableOriginalConstructor() ->setMethods(['isScopeGlobal', 'getBackend']) ->getMock(); - $backend = $this->createMock(ProductModel\Attribute\Backend\Tierprice::class); + $backend = $this->getMockBuilder(\Magento\Catalog\Model\Product\Attribute\Backend\Tierprice::class) + ->disableOriginalConstructor() + ->getMock(); $resource = $this->getMockBuilder( - ProductResource\Attribute\Backend\GroupPrice\AbstractGroupPrice::class + \Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\GroupPrice\AbstractGroupPrice::class ) ->disableOriginalConstructor() ->getMock(); - $select = $this->createMock(DB\Select::class); + $select = $this->getMockBuilder(\Magento\Framework\DB\Select::class) + ->disableOriginalConstructor() + ->getMock(); $this->connectionMock->expects($this->once())->method('getAutoIncrementField')->willReturn('entity_id'); $this->collection->addItem($itemMock); $itemMock->expects($this->atLeastOnce())->method('getData')->with('entity_id')->willReturn(1); @@ -290,6 +361,7 @@ public function testAddTierPriceData() ->willReturn($attributeMock); $attributeMock->expects($this->atLeastOnce())->method('getBackend')->willReturn($backend); $attributeMock->expects($this->once())->method('isScopeGlobal')->willReturn(false); + $this->storeManager->expects($this->once())->method('getWebsiteId')->willReturn(1); $backend->expects($this->once())->method('getResource')->willReturn($resource); $resource->expects($this->once())->method('getSelect')->willReturn($select); $select->expects($this->once())->method('columns')->with(['product_id' => 'entity_id'])->willReturnSelf(); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php index 80180d2033ce5..596148b627506 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php @@ -7,8 +7,6 @@ use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation; use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; -use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -28,7 +26,7 @@ class CollectionTest extends \PHPUnit\Framework\TestCase /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $loggerMock; - /** @var FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Framework\Data\Collection\Db\FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $fetchStrategyMock; /** @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ @@ -46,8 +44,8 @@ class CollectionTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Catalog\Model\ResourceModel\Helper|\PHPUnit_Framework_MockObject_MockObject */ protected $helperMock; - /** @var ResourceModelPoolInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $resourceModelPoolMock; + /** @var \Magento\Framework\Validator\UniversalFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $universalFactoryMock; /** @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $storeManagerMock; @@ -81,23 +79,29 @@ protected function setUp() $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->entityFactoryMock = $this->createMock(\Magento\Framework\Data\Collection\EntityFactory::class); $this->loggerMock = $this->createMock(\Psr\Log\LoggerInterface::class); - $this->fetchStrategyMock = $this->createMock(FetchStrategyInterface::class); + $this->fetchStrategyMock = $this->createMock( + \Magento\Framework\Data\Collection\Db\FetchStrategyInterface::class + ); $this->managerInterfaceMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); $this->configMock = $this->createMock(\Magento\Eav\Model\Config::class); $this->resourceMock = $this->createMock(\Magento\Framework\App\ResourceConnection::class); $this->entityFactoryMock2 = $this->createMock(\Magento\Eav\Model\EntityFactory::class); $this->helperMock = $this->createMock(\Magento\Catalog\Model\ResourceModel\Helper::class); $entity = $this->createMock(\Magento\Eav\Model\Entity\AbstractEntity::class); - $select = $this->createMock(\Magento\Framework\DB\Select::class); - $connection = $this->createMock(\Magento\Framework\DB\Adapter\Pdo\Mysql::class); + $select = $this->getMockBuilder(\Magento\Framework\DB\Select::class) + ->disableOriginalConstructor() + ->getMock(); + $connection = $this->getMockBuilder(\Magento\Framework\DB\Adapter\Pdo\Mysql::class) + ->disableOriginalConstructor() + ->getMock(); $connection->expects($this->any()) ->method('select') ->willReturn($select); $entity->expects($this->any())->method('getConnection')->will($this->returnValue($connection)); $entity->expects($this->any())->method('getDefaultAttributes')->will($this->returnValue([])); - $this->resourceModelPoolMock = $this->createMock(ResourceModelPoolInterface::class); - $this->resourceModelPoolMock->expects($this->any())->method('get')->will($this->returnValue($entity)); - $this->storeManagerMock = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class); + $this->universalFactoryMock = $this->createMock(\Magento\Framework\Validator\UniversalFactory::class); + $this->universalFactoryMock->expects($this->any())->method('create')->will($this->returnValue($entity)); + $this->storeManagerMock = $this->getMockForAbstractClass(\Magento\Store\Model\StoreManagerInterface::class); $this->storeManagerMock ->expects($this->any()) ->method('getStore') @@ -114,7 +118,9 @@ function ($store) { $this->timezoneInterfaceMock = $this->createMock(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class); $this->sessionMock = $this->createMock(\Magento\Customer\Model\Session::class); $this->dateTimeMock = $this->createMock(\Magento\Framework\Stdlib\DateTime::class); - $productLimitationFactoryMock = $this->createPartialMock(ProductLimitationFactory::class, ['create']); + $productLimitationFactoryMock = $this->getMockBuilder( + ProductLimitationFactory::class + )->disableOriginalConstructor()->setMethods(['create'])->getMock(); $productLimitationFactoryMock->method('create') ->willReturn($this->createMock(ProductLimitation::class)); @@ -130,7 +136,7 @@ function ($store) { 'resource' => $this->resourceMock, 'eavEntityFactory' => $this->entityFactoryMock2, 'resourceHelper' => $this->helperMock, - 'resourceModelPool' => $this->resourceModelPoolMock, + 'universalFactory' => $this->universalFactoryMock, 'storeManager' => $this->storeManagerMock, 'catalogData' => $this->catalogHelperMock, 'catalogProductFlatState' => $this->stateMock, diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php index e3f61af771f8c..7791dc761ae39 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php @@ -6,8 +6,6 @@ namespace Magento\CatalogSearch\Model\ResourceModel\Advanced; -use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; -use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; use Magento\Catalog\Model\Product; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchCriteriaResolverInterface; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierInterface; @@ -21,8 +19,6 @@ use Magento\Framework\Api\Search\SearchResultFactory; use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; use Magento\Framework\Search\Request\EmptyRequestDataException; use Magento\Framework\Search\Request\NonExistingRequestNameException; use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; @@ -139,10 +135,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param SearchResultFactory|null $searchResultFactory * @param ProductLimitationFactory|null $productLimitationFactory * @param MetadataPool|null $metadataPool - * @param TableMaintainer|null $tableMaintainer - * @param PriceTableResolver|null $priceTableResolver - * @param DimensionFactory|null $dimensionFactory - * @param ResourceModelPoolInterface|null $resourceModelPool * @param string $searchRequestName * @param SearchCriteriaResolverFactory|null $searchCriteriaResolverFactory * @param SearchResultApplierFactory|null $searchResultApplierFactory @@ -177,10 +169,6 @@ public function __construct( SearchResultFactory $searchResultFactory = null, ProductLimitationFactory $productLimitationFactory = null, MetadataPool $metadataPool = null, - TableMaintainer $tableMaintainer = null, - PriceTableResolver $priceTableResolver = null, - DimensionFactory $dimensionFactory = null, - ResourceModelPoolInterface $resourceModelPool = null, $searchRequestName = 'advanced_search_container', SearchCriteriaResolverFactory $searchCriteriaResolverFactory = null, SearchResultApplierFactory $searchResultApplierFactory = null, @@ -225,11 +213,7 @@ public function __construct( $groupManagement, $connection, $productLimitationFactory, - $metadataPool, - $tableMaintainer, - $priceTableResolver, - $dimensionFactory, - $resourceModelPool + $metadataPool ); } diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php index 2c36b150fed07..59f6cd1c6e7eb 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php @@ -6,8 +6,6 @@ namespace Magento\CatalogSearch\Model\ResourceModel\Fulltext; -use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; -use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\TotalRecordsResolverInterface; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\TotalRecordsResolverFactory; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchCriteriaResolverInterface; @@ -21,8 +19,6 @@ use Magento\CatalogSearch\Model\Search\RequestGenerator; use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Exception\StateException; -use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; use Magento\Framework\Search\Response\QueryResponse; use Magento\Framework\Search\Request\EmptyRequestDataException; use Magento\Framework\Search\Request\NonExistingRequestNameException; @@ -41,6 +37,7 @@ * @since 100.0.2 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection { @@ -167,10 +164,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param SearchResultFactory|null $searchResultFactory * @param ProductLimitationFactory|null $productLimitationFactory * @param MetadataPool|null $metadataPool - * @param TableMaintainer|null $tableMaintainer - * @param PriceTableResolver|null $priceTableResolver - * @param DimensionFactory|null $dimensionFactory - * @param ResourceModelPoolInterface|null $resourceModelPool * @param \Magento\Search\Api\SearchInterface|null $search * @param \Magento\Framework\Api\Search\SearchCriteriaBuilder|null $searchCriteriaBuilder * @param \Magento\Framework\Api\FilterBuilder|null $filterBuilder @@ -210,10 +203,6 @@ public function __construct( SearchResultFactory $searchResultFactory = null, ProductLimitationFactory $productLimitationFactory = null, MetadataPool $metadataPool = null, - TableMaintainer $tableMaintainer = null, - PriceTableResolver $priceTableResolver = null, - DimensionFactory $dimensionFactory = null, - ResourceModelPoolInterface $resourceModelPool = null, \Magento\Search\Api\SearchInterface $search = null, \Magento\Framework\Api\Search\SearchCriteriaBuilder $searchCriteriaBuilder = null, \Magento\Framework\Api\FilterBuilder $filterBuilder = null, @@ -249,11 +238,7 @@ public function __construct( $groupManagement, $connection, $productLimitationFactory, - $metadataPool, - $tableMaintainer, - $priceTableResolver, - $dimensionFactory, - $resourceModelPool + $metadataPool ); $this->requestBuilder = $requestBuilder; $this->searchEngine = $searchEngine; diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Search/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Search/Collection.php index fd948616c005b..e625ccbe51fe3 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Search/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Search/Collection.php @@ -6,17 +6,11 @@ namespace Magento\CatalogSearch\Model\ResourceModel\Search; -use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; -use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; -use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Search collection * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @api * @since 100.0.2 */ @@ -67,12 +61,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param \Magento\Customer\Api\GroupManagementInterface $groupManagement * @param \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $attributeCollectionFactory * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection - * @param ProductLimitationFactory|null $productLimitationFactory - * @param MetadataPool|null $metadataPool - * @param TableMaintainer|null $tableMaintainer - * @param PriceTableResolver|null $priceTableResolver - * @param DimensionFactory|null $dimensionFactory - * @param ResourceModelPoolInterface|null $resourceModelPool * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -96,13 +84,7 @@ public function __construct( \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Customer\Api\GroupManagementInterface $groupManagement, \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $attributeCollectionFactory, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - ProductLimitationFactory $productLimitationFactory = null, - MetadataPool $metadataPool = null, - TableMaintainer $tableMaintainer = null, - PriceTableResolver $priceTableResolver = null, - DimensionFactory $dimensionFactory = null, - ResourceModelPoolInterface $resourceModelPool = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null ) { $this->_attributeCollectionFactory = $attributeCollectionFactory; parent::__construct( @@ -125,13 +107,7 @@ public function __construct( $customerSession, $dateTime, $groupManagement, - $connection, - $productLimitationFactory, - $metadataPool, - $tableMaintainer, - $priceTableResolver, - $dimensionFactory, - $resourceModelPool + $connection ); } @@ -293,6 +269,7 @@ protected function _getSearchEntityIdsSql($query, $searchOnlyInCurrentStore = tr $sql = $this->_getSearchInOptionSql($query); if ($sql) { + // phpcs:ignore Magento2.SQL.RawQuery $selects[] = "SELECT * FROM ({$sql}) AS inoptionsql"; // inherent unions may be inside } diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php index fe29fa1ece011..683070c286239 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php @@ -67,7 +67,7 @@ protected function setUp() $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->eavConfig = $this->createMock(\Magento\Eav\Model\Config::class); $storeManager = $this->getStoreManager(); - $resourceModelPool = $this->getResourceModelPool(); + $universalFactory = $this->getUniversalFactory(); $this->criteriaBuilder = $this->getCriteriaBuilder(); $this->filterBuilder = $this->createMock(\Magento\Framework\Api\FilterBuilder::class); $this->temporaryStorageFactory = $this->createMock( @@ -126,7 +126,7 @@ protected function setUp() [ 'eavConfig' => $this->eavConfig, 'storeManager' => $storeManager, - 'resourceModelPool' => $resourceModelPool, + 'universalFactory' => $universalFactory, 'searchCriteriaBuilder' => $this->criteriaBuilder, 'filterBuilder' => $this->filterBuilder, 'temporaryStorageFactory' => $this->temporaryStorageFactory, diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/BaseCollection.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/BaseCollection.php index 5a5106593af8b..9ea103e23d2a7 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/BaseCollection.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/BaseCollection.php @@ -5,8 +5,6 @@ */ namespace Magento\CatalogSearch\Test\Unit\Model\ResourceModel; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Base class for Collection tests. * @@ -44,17 +42,19 @@ protected function getStoreManager() } /** - * Get mock for ResourceModelPool so Collection can be used. + * Get mock for UniversalFactory so Collection can be used. * - * @return \PHPUnit_Framework_MockObject_MockObject|ResourceModelPoolInterface + * @return \PHPUnit_Framework_MockObject_MockObject */ - protected function getResourceModelPool() + protected function getUniversalFactory() { $connection = $this->getMockBuilder(\Magento\Framework\DB\Adapter\Pdo\Mysql::class) ->disableOriginalConstructor() ->setMethods(['select']) ->getMockForAbstractClass(); - $select = $this->createMock(\Magento\Framework\DB\Select::class); + $select = $this->getMockBuilder(\Magento\Framework\DB\Select::class) + ->disableOriginalConstructor() + ->getMock(); $connection->expects($this->any())->method('select')->willReturn($select); $entity = $this->getMockBuilder(\Magento\Eav\Model\Entity\AbstractEntity::class) @@ -74,14 +74,14 @@ protected function getResourceModelPool() ->method('getEntityTable') ->willReturn('table'); - $resourceModelPool = $this->getMockBuilder(ResourceModelPoolInterface::class) - ->setMethods(['get']) + $universalFactory = $this->getMockBuilder(\Magento\Framework\Validator\UniversalFactory::class) + ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); - $resourceModelPool->expects($this->once()) - ->method('get') + $universalFactory->expects($this->once()) + ->method('create') ->willReturn($entity); - return $resourceModelPool; + return $universalFactory; } } diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php index f1c2161a052e0..9170b81dc3182 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php @@ -49,7 +49,7 @@ class CollectionTest extends BaseCollection /** * @var MockObject */ - private $resourceModelPool; + private $universalFactory; /** * @var MockObject @@ -78,7 +78,7 @@ protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->storeManager = $this->getStoreManager(); - $this->resourceModelPool = $this->getResourceModelPool(); + $this->universalFactory = $this->getUniversalFactory(); $this->scopeConfig = $this->getScopeConfig(); $this->criteriaBuilder = $this->getCriteriaBuilder(); $this->filterBuilder = $this->getFilterBuilder(); @@ -143,7 +143,7 @@ protected function setUp() \Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection::class, [ 'storeManager' => $this->storeManager, - 'resourceModelPool' => $this->resourceModelPool, + 'universalFactory' => $this->universalFactory, 'scopeConfig' => $this->scopeConfig, 'temporaryStorageFactory' => $temporaryStorageFactory, 'productLimitationFactory' => $productLimitationFactoryMock, diff --git a/app/code/Magento/Customer/Model/ResourceModel/Customer/Collection.php b/app/code/Magento/Customer/Model/ResourceModel/Customer/Collection.php index 394a0d3ed556d..af8980a129d3e 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/Customer/Collection.php +++ b/app/code/Magento/Customer/Model/ResourceModel/Customer/Collection.php @@ -5,8 +5,6 @@ */ namespace Magento\Customer\Model\ResourceModel\Customer; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Customers collection * @@ -45,7 +43,6 @@ class Collection extends \Magento\Eav\Model\Entity\Collection\VersionControl\Abs * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection * @param string $modelName * - * @param ResourceModelPoolInterface|null $resourceModelPool * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -61,8 +58,7 @@ public function __construct( \Magento\Framework\Model\ResourceModel\Db\VersionControl\Snapshot $entitySnapshot, \Magento\Framework\DataObject\Copy\Config $fieldsetConfig, \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - $modelName = self::CUSTOMER_MODEL_NAME, - ResourceModelPoolInterface $resourceModelPool = null + $modelName = self::CUSTOMER_MODEL_NAME ) { $this->_fieldsetConfig = $fieldsetConfig; $this->_modelName = $modelName; @@ -77,8 +73,7 @@ public function __construct( $resourceHelper, $universalFactory, $entitySnapshot, - $connection, - $resourceModelPool + $connection ); } diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 52f106a0475f5..e50abbc11e54a 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -6,12 +6,10 @@ namespace Magento\Eav\Model\Entity\Collection; -use Magento\Framework\App\ObjectManager; use Magento\Framework\App\ResourceConnection\SourceProviderInterface; use Magento\Framework\Data\Collection\AbstractDb; use Magento\Framework\DB\Select; use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; /** * Entity/Attribute/Model - collection abstract @@ -128,15 +126,10 @@ abstract class AbstractCollection extends AbstractDb implements SourceProviderIn protected $_resourceHelper; /** - * @deprecated To instantiate resource models, use $resourceModelPool instead * * @var \Magento\Framework\Validator\UniversalFactory */ protected $_universalFactory; - /** - * @var ResourceModelPoolInterface - */ - private $resourceModelPool; /** * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory @@ -149,7 +142,6 @@ abstract class AbstractCollection extends AbstractDb implements SourceProviderIn * @param \Magento\Eav\Model\ResourceModel\Helper $resourceHelper * @param \Magento\Framework\Validator\UniversalFactory $universalFactory * @param mixed $connection - * @param ResourceModelPoolInterface|null $resourceModelPool * @codeCoverageIgnore * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -162,9 +154,8 @@ public function __construct( \Magento\Framework\App\ResourceConnection $resource, \Magento\Eav\Model\EntityFactory $eavEntityFactory, \Magento\Eav\Model\ResourceModel\Helper $resourceHelper, - \Magento\Framework\Validator\UniversalFactory $universalFactory = null, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - ResourceModelPoolInterface $resourceModelPool = null + \Magento\Framework\Validator\UniversalFactory $universalFactory, + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null ) { $this->_eventManager = $eventManager; $this->_eavConfig = $eavConfig; @@ -172,12 +163,6 @@ public function __construct( $this->_eavEntityFactory = $eavEntityFactory; $this->_resourceHelper = $resourceHelper; $this->_universalFactory = $universalFactory; - if ($resourceModelPool === null) { - $resourceModelPool = ObjectManager::getInstance()->get( - ResourceModelPoolInterface::class - ); - } - $this->resourceModelPool = $resourceModelPool; parent::__construct($entityFactory, $logger, $fetchStrategy, $connection); $this->_construct(); $this->setConnection($this->getEntity()->getConnection()); @@ -245,7 +230,7 @@ protected function _initSelect() protected function _init($model, $entityModel) { $this->setItemObjectClass($model); - $entity = $this->resourceModelPool->get($entityModel); + $entity = $this->_universalFactory->create($entityModel); $this->setEntity($entity); return $this; diff --git a/app/code/Magento/Eav/Model/Entity/Collection/VersionControl/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/VersionControl/AbstractCollection.php index 2181c6bc1be05..631bfa3c2d2b5 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/VersionControl/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/VersionControl/AbstractCollection.php @@ -5,10 +5,10 @@ */ namespace Magento\Eav\Model\Entity\Collection\VersionControl; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Class Abstract Collection + * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @since 100.0.2 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -21,6 +21,7 @@ abstract class AbstractCollection extends \Magento\Eav\Model\Entity\Collection\A protected $entitySnapshot; /** + * AbstractCollection constructor. * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy @@ -30,9 +31,9 @@ abstract class AbstractCollection extends \Magento\Eav\Model\Entity\Collection\A * @param \Magento\Eav\Model\EntityFactory $eavEntityFactory * @param \Magento\Eav\Model\ResourceModel\Helper $resourceHelper * @param \Magento\Framework\Validator\UniversalFactory $universalFactory - * @param \Magento\Framework\Model\ResourceModel\Db\VersionControl\Snapshot $entitySnapshot , - * @param mixed $connection - * @param ResourceModelPoolInterface|null $resourceModelPool + * @param \Magento\Framework\Model\ResourceModel\Db\VersionControl\Snapshot $entitySnapshot + * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @codeCoverageIgnore */ @@ -47,8 +48,7 @@ public function __construct( \Magento\Eav\Model\ResourceModel\Helper $resourceHelper, \Magento\Framework\Validator\UniversalFactory $universalFactory, \Magento\Framework\Model\ResourceModel\Db\VersionControl\Snapshot $entitySnapshot, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - ResourceModelPoolInterface $resourceModelPool = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null ) { $this->entitySnapshot = $entitySnapshot; @@ -62,8 +62,7 @@ public function __construct( $eavEntityFactory, $resourceHelper, $universalFactory, - $connection, - $resourceModelPool + $connection ); } diff --git a/app/code/Magento/Eav/Model/Entity/Type.php b/app/code/Magento/Eav/Model/Entity/Type.php index b24f86c73e8df..444d58bf546d4 100644 --- a/app/code/Magento/Eav/Model/Entity/Type.php +++ b/app/code/Magento/Eav/Model/Entity/Type.php @@ -5,9 +5,6 @@ */ namespace Magento\Eav\Model\Entity; -use Magento\Framework\App\ObjectManager; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Entity type model * @@ -78,16 +75,10 @@ class Type extends \Magento\Framework\Model\AbstractModel protected $_storeFactory; /** - * @deprecated To instantiate resource models, use $resourceModelPool instead * @var \Magento\Framework\Validator\UniversalFactory */ protected $_universalFactory; - /** - * @var ResourceModelPoolInterface - */ - private $resourceModelPool; - /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -98,9 +89,7 @@ class Type extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data - * @param ResourceModelPoolInterface|null $resourceModelPool * @codeCoverageIgnore - * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Framework\Model\Context $context, @@ -111,20 +100,13 @@ public function __construct( \Magento\Framework\Validator\UniversalFactory $universalFactory, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [], - ResourceModelPoolInterface $resourceModelPool = null + array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); $this->_attributeFactory = $attributeFactory; $this->_attSetFactory = $attSetFactory; $this->_storeFactory = $storeFactory; $this->_universalFactory = $universalFactory; - if ($resourceModelPool === null) { - $resourceModelPool = ObjectManager::getInstance()->get( - ResourceModelPoolInterface::class - ); - } - $this->resourceModelPool = $resourceModelPool; } /** @@ -381,7 +363,7 @@ public function getAttributeModel() */ public function getEntity() { - return $this->resourceModelPool->get($this->_data['entity_model']); + return $this->_universalFactory->create($this->_data['entity_model']); } /** diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php index c7af666604b39..ab5b40c56685c 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php @@ -63,7 +63,7 @@ class AbstractCollectionTest extends \PHPUnit\Framework\TestCase /** * @var ResourceModelPoolInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $resourceModelPoolMock; + protected $validatorFactoryMock; /** * @var \Magento\Framework\DB\Statement\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject @@ -74,11 +74,17 @@ protected function setUp() { $this->coreEntityFactoryMock = $this->createMock(\Magento\Framework\Data\Collection\EntityFactory::class); $this->loggerMock = $this->createMock(\Psr\Log\LoggerInterface::class); - $this->fetchStrategyMock = $this->createMock(FetchStrategyInterface::class); + $this->fetchStrategyMock = $this->createMock( + \Magento\Framework\Data\Collection\Db\FetchStrategyInterface::class + ); $this->eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); $this->configMock = $this->createMock(\Magento\Eav\Model\Config::class); + $this->coreResourceMock = $this->createMock(\Magento\Framework\App\ResourceConnection::class); $this->resourceHelperMock = $this->createMock(\Magento\Eav\Model\ResourceModel\Helper::class); + $this->validatorFactoryMock = $this->createMock(\Magento\Framework\Validator\UniversalFactory::class); $this->entityFactoryMock = $this->createMock(\Magento\Eav\Model\EntityFactory::class); + /** @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject */ + $connectionMock = $this->createMock(\Magento\Framework\DB\Adapter\Pdo\Mysql::class); $this->statementMock = $this->createPartialMock(\Magento\Framework\DB\Statement\Pdo\Mysql::class, ['fetch']); /** @var $selectMock \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject */ $selectMock = $this->createMock(\Magento\Framework\DB\Select::class); @@ -89,12 +95,9 @@ protected function setUp() )->will( $this->returnCallback([$this, 'getMagentoObject']) ); - /** @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject */ - $connectionMock = $this->createMock(\Magento\Framework\DB\Adapter\Pdo\Mysql::class); $connectionMock->expects($this->any())->method('select')->will($this->returnValue($selectMock)); $connectionMock->expects($this->any())->method('query')->willReturn($this->statementMock); - $this->coreResourceMock = $this->createMock(\Magento\Framework\App\ResourceConnection::class); $this->coreResourceMock->expects( $this->any() )->method( @@ -106,11 +109,10 @@ protected function setUp() $entityMock->expects($this->any())->method('getConnection')->will($this->returnValue($connectionMock)); $entityMock->expects($this->any())->method('getDefaultAttributes')->will($this->returnValue([])); - $this->resourceModelPoolMock = $this->createMock(ResourceModelPoolInterface::class); - $this->resourceModelPoolMock->expects( + $this->validatorFactoryMock->expects( $this->any() )->method( - 'get' + 'create' )->with( 'test_entity_model' // see \Magento\Eav\Test\Unit\Model\Entity\Collection\AbstractCollectionStub )->will( @@ -126,9 +128,8 @@ protected function setUp() $this->coreResourceMock, $this->entityFactoryMock, $this->resourceHelperMock, - null, - null, - $this->resourceModelPoolMock + $this->validatorFactoryMock, + null ); } diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/VersionControl/AbstractCollectionTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/VersionControl/AbstractCollectionTest.php index 5b41b9b71f4b5..cce7b43786a76 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/VersionControl/AbstractCollectionTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/VersionControl/AbstractCollectionTest.php @@ -39,7 +39,7 @@ protected function setUp() \Magento\Eav\Test\Unit\Model\Entity\Collection\VersionControl\AbstractCollectionStub::class, [ 'entityFactory' => $this->coreEntityFactoryMock, - 'resourceModelPool' => $this->resourceModelPoolMock, + 'universalFactory' => $this->validatorFactoryMock, 'entitySnapshot' => $this->entitySnapshot ] ); diff --git a/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Type/Grouped/AssociatedProductsCollection.php b/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Type/Grouped/AssociatedProductsCollection.php index 251dca8ef1615..cbe1ef26c54b0 100644 --- a/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Type/Grouped/AssociatedProductsCollection.php +++ b/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Type/Grouped/AssociatedProductsCollection.php @@ -7,17 +7,11 @@ */ namespace Magento\GroupedProduct\Model\ResourceModel\Product\Type\Grouped; -use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; -use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; -use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Associated products collection. * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class AssociatedProductsCollection extends \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection { @@ -61,12 +55,6 @@ class AssociatedProductsCollection extends \Magento\Catalog\Model\ResourceModel\ * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $config * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection * - * @param ProductLimitationFactory|null $productLimitationFactory - * @param MetadataPool|null $metadataPool - * @param TableMaintainer|null $tableMaintainer - * @param PriceTableResolver|null $priceTableResolver - * @param DimensionFactory|null $dimensionFactory - * @param ResourceModelPoolInterface|null $resourceModelPool * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -91,13 +79,7 @@ public function __construct( \Magento\Customer\Api\GroupManagementInterface $groupManagement, \Magento\Framework\Registry $coreRegistry, \Magento\Catalog\Model\ProductTypes\ConfigInterface $config, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - ProductLimitationFactory $productLimitationFactory = null, - MetadataPool $metadataPool = null, - TableMaintainer $tableMaintainer = null, - PriceTableResolver $priceTableResolver = null, - DimensionFactory $dimensionFactory = null, - ResourceModelPoolInterface $resourceModelPool = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null ) { $this->_coreRegistry = $coreRegistry; $this->_config = $config; @@ -121,13 +103,7 @@ public function __construct( $customerSession, $dateTime, $groupManagement, - $connection, - $productLimitationFactory, - $metadataPool, - $tableMaintainer, - $priceTableResolver, - $dimensionFactory, - $resourceModelPool + $connection ); } diff --git a/app/code/Magento/Reports/Model/ResourceModel/Customer/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Customer/Collection.php index aa01e33caf3d2..b6e55af96f4c1 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Customer/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Customer/Collection.php @@ -6,8 +6,6 @@ namespace Magento\Reports\Model\ResourceModel\Customer; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Customers Report collection. * @@ -75,6 +73,7 @@ class Collection extends \Magento\Customer\Model\ResourceModel\Customer\Collecti protected $orderResource; /** + * Collection constructor. * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy @@ -89,10 +88,9 @@ class Collection extends \Magento\Customer\Model\ResourceModel\Customer\Collecti * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository * @param \Magento\Quote\Model\ResourceModel\Quote\Item\CollectionFactory $quoteItemFactory * @param \Magento\Sales\Model\ResourceModel\Order\Collection $orderResource - * @param mixed $connection + * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection * @param string $modelName * - * @param ResourceModelPoolInterface|null $resourceModelPool * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -111,8 +109,7 @@ public function __construct( \Magento\Quote\Model\ResourceModel\Quote\Item\CollectionFactory $quoteItemFactory, \Magento\Sales\Model\ResourceModel\Order\Collection $orderResource, \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - $modelName = self::CUSTOMER_MODEL_NAME, - ResourceModelPoolInterface $resourceModelPool = null + $modelName = self::CUSTOMER_MODEL_NAME ) { parent::__construct( $entityFactory, @@ -127,8 +124,7 @@ public function __construct( $entitySnapshot, $fieldsetConfig, $connection, - $modelName, - $resourceModelPool + $modelName ); $this->orderResource = $orderResource; $this->quoteRepository = $quoteRepository; diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Collection.php index 451007960a1ce..966ee14c2cb64 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Collection.php @@ -9,17 +9,11 @@ */ namespace Magento\Reports\Model\ResourceModel\Product; -use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; -use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; -use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Products Report collection. * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @api * @since 100.0.2 */ @@ -95,14 +89,8 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param \Magento\Reports\Model\Event\TypeFactory $eventTypeFactory * @param \Magento\Catalog\Model\Product\Type $productType * @param \Magento\Quote\Model\ResourceModel\Quote\Collection $quoteResource - * @param mixed $connection - * @param ProductLimitationFactory|null $productLimitationFactory - * @param MetadataPool|null $metadataPool - * @param TableMaintainer|null $tableMaintainer - * @param PriceTableResolver|null $priceTableResolver - * @param DimensionFactory|null $dimensionFactory - * @param ResourceModelPoolInterface $resourceModelPool - * @throws \Magento\Framework\Exception\LocalizedException + * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -129,13 +117,7 @@ public function __construct( \Magento\Reports\Model\Event\TypeFactory $eventTypeFactory, \Magento\Catalog\Model\Product\Type $productType, \Magento\Quote\Model\ResourceModel\Quote\Collection $quoteResource, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - ProductLimitationFactory $productLimitationFactory = null, - MetadataPool $metadataPool = null, - TableMaintainer $tableMaintainer = null, - PriceTableResolver $priceTableResolver = null, - DimensionFactory $dimensionFactory = null, - ResourceModelPoolInterface $resourceModelPool = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null ) { $this->setProductEntityId($product->getEntityIdField()); $this->setProductEntityTableName($product->getEntityTable()); @@ -160,13 +142,7 @@ public function __construct( $customerSession, $dateTime, $groupManagement, - $connection, - $productLimitationFactory, - $metadataPool, - $tableMaintainer, - $priceTableResolver, - $dimensionFactory, - $resourceModelPool + $connection ); $this->_eventTypeFactory = $eventTypeFactory; $this->_productType = $productType; diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Index/Collection/AbstractCollection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Index/Collection/AbstractCollection.php index bec8faaee0ca7..5b4cf39d65def 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Index/Collection/AbstractCollection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Index/Collection/AbstractCollection.php @@ -9,17 +9,12 @@ */ namespace Magento\Reports\Model\ResourceModel\Product\Index\Collection; -use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; -use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; -use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * Reports Product Index Abstract Product Resource Collection. * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) + * phpcs:disable Magento2.Classes.AbstractApi * @api * @since 100.0.2 */ @@ -59,13 +54,8 @@ abstract class AbstractCollection extends \Magento\Catalog\Model\ResourceModel\P * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Customer\Api\GroupManagementInterface $groupManagement * @param \Magento\Customer\Model\Visitor $customerVisitor - * @param mixed $connection - * @param ProductLimitationFactory|null $productLimitationFactory - * @param MetadataPool|null $metadataPool - * @param TableMaintainer|null $tableMaintainer - * @param PriceTableResolver|null $priceTableResolver - * @param DimensionFactory|null $dimensionFactory - * @param ResourceModelPoolInterface|null $resourceModelPool + * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -89,13 +79,7 @@ public function __construct( \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Customer\Api\GroupManagementInterface $groupManagement, \Magento\Customer\Model\Visitor $customerVisitor, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - ProductLimitationFactory $productLimitationFactory = null, - MetadataPool $metadataPool = null, - TableMaintainer $tableMaintainer = null, - PriceTableResolver $priceTableResolver = null, - DimensionFactory $dimensionFactory = null, - ResourceModelPoolInterface $resourceModelPool = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null ) { parent::__construct( $entityFactory, @@ -117,13 +101,7 @@ public function __construct( $customerSession, $dateTime, $groupManagement, - $connection, - $productLimitationFactory, - $metadataPool, - $tableMaintainer, - $priceTableResolver, - $dimensionFactory, - $resourceModelPool + $connection ); $this->_customerVisitor = $customerVisitor; } diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Lowstock/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Lowstock/Collection.php index 8bf50f4c1b8e7..39d673911111f 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Lowstock/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Lowstock/Collection.php @@ -5,22 +5,19 @@ */ /** + * Product Low Stock Report Collection + * * @author Magento Core Team <core@magentocommerce.com> */ namespace Magento\Reports\Model\ResourceModel\Product\Lowstock; -use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; -use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; -use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; -use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; /** * Product Low Stock Report Collection. * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @api * @since 100.0.2 */ @@ -56,7 +53,6 @@ class Collection extends \Magento\Reports\Model\ResourceModel\Product\Collection protected $_itemResource; /** - * Collection constructor. * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy @@ -84,13 +80,7 @@ class Collection extends \Magento\Reports\Model\ResourceModel\Product\Collection * @param \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration * @param \Magento\CatalogInventory\Model\ResourceModel\Stock\Item $itemResource * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection - * @param ProductLimitationFactory|null $productLimitationFactory - * @param MetadataPool|null $metadataPool - * @param TableMaintainer|null $tableMaintainer - * @param PriceTableResolver|null $priceTableResolver - * @param DimensionFactory|null $dimensionFactory - * @param ResourceModelPoolInterface|null $resourceModelPool - * @throws LocalizedException + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -120,13 +110,7 @@ public function __construct( \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry, \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration, \Magento\CatalogInventory\Model\ResourceModel\Stock\Item $itemResource, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - ProductLimitationFactory $productLimitationFactory = null, - MetadataPool $metadataPool = null, - TableMaintainer $tableMaintainer = null, - PriceTableResolver $priceTableResolver = null, - DimensionFactory $dimensionFactory = null, - ResourceModelPoolInterface $resourceModelPool = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null ) { parent::__construct( $entityFactory, @@ -152,13 +136,7 @@ public function __construct( $eventTypeFactory, $productType, $quoteResource, - $connection, - $productLimitationFactory, - $metadataPool, - $tableMaintainer, - $priceTableResolver, - $dimensionFactory, - $resourceModelPool + $connection ); $this->stockRegistry = $stockRegistry; $this->stockConfiguration = $stockConfiguration; diff --git a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/CollectionTest.php b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/CollectionTest.php index cb4d51e0c540d..038d37a990442 100644 --- a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/CollectionTest.php +++ b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/CollectionTest.php @@ -12,7 +12,6 @@ use Magento\Catalog\Model\Product\Type as ProductType; use Magento\Catalog\Model\ResourceModel\Helper; use Magento\Catalog\Model\ResourceModel\Product as ResourceProduct; -use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; use Magento\Catalog\Model\ResourceModel\Url; use Magento\Customer\Api\GroupManagementInterface; use Magento\Customer\Model\Session; @@ -26,9 +25,7 @@ use Magento\Framework\Data\Collection\EntityFactory; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Select; -use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Event\ManagerInterface; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; use Magento\Framework\Module\Manager; use Magento\Framework\Stdlib\DateTime; use Magento\Framework\Stdlib\DateTime\TimezoneInterface; @@ -37,7 +34,6 @@ use Magento\Quote\Model\ResourceModel\Quote\Collection; use Magento\Reports\Model\Event\TypeFactory; use Magento\Reports\Model\ResourceModel\Product\Collection as ProductCollection; -use Magento\Store\Api\Data\StoreInterface; use Magento\Store\Model\StoreManagerInterface; use Psr\Log\LoggerInterface; @@ -82,6 +78,46 @@ class CollectionTest extends \PHPUnit\Framework\TestCase protected function setUp() { $this->objectManager = new ObjectManager($this); + $context = $this->createPartialMock(Context::class, ['getResource', 'getEavConfig']); + $entityFactoryMock = $this->createMock(EntityFactory::class); + $loggerMock = $this->createMock(LoggerInterface::class); + $fetchStrategyMock = $this->createMock(FetchStrategyInterface::class); + $eventManagerMock = $this->createMock(ManagerInterface::class); + $eavConfigMock = $this->createMock(Config::class); + $this->resourceMock = $this->createPartialMock(ResourceConnection::class, ['getTableName', 'getConnection']); + $eavEntityFactoryMock = $this->createMock(EavEntityFactory::class); + $resourceHelperMock = $this->createMock(Helper::class); + $universalFactoryMock = $this->createMock(UniversalFactory::class); + $storeManagerMock = $this->createPartialMockForAbstractClass( + StoreManagerInterface::class, + ['getStore', 'getId'] + ); + $moduleManagerMock = $this->createMock(Manager::class); + $productFlatStateMock = $this->createMock(State::class); + $scopeConfigMock = $this->createMock(ScopeConfigInterface::class); + $optionFactoryMock = $this->createMock(OptionFactory::class); + $catalogUrlMock = $this->createMock(Url::class); + $localeDateMock = $this->createMock(TimezoneInterface::class); + $customerSessionMock = $this->createMock(Session::class); + $dateTimeMock = $this->createMock(DateTime::class); + $groupManagementMock = $this->createMock(GroupManagementInterface::class); + $eavConfig = $this->createPartialMock(Config::class, ['getEntityType']); + $entityType = $this->createMock(Type::class); + + $eavConfig->expects($this->atLeastOnce())->method('getEntityType')->willReturn($entityType); + $context->expects($this->atLeastOnce())->method('getResource')->willReturn($this->resourceMock); + $context->expects($this->atLeastOnce())->method('getEavConfig')->willReturn($eavConfig); + + $defaultAttributes = $this->createPartialMock(DefaultAttributes::class, ['_getDefaultAttributes']); + $productMock = $this->objectManager->getObject( + ResourceProduct::class, + ['context' => $context, 'defaultAttributes' => $defaultAttributes] + ); + + $this->eventTypeFactoryMock = $this->createMock(TypeFactory::class); + $productTypeMock = $this->createMock(ProductType::class); + $quoteResourceMock = $this->createMock(Collection::class); + $this->connectionMock = $this->createPartialMockForAbstractClass(AdapterInterface::class, ['select']); $this->selectMock = $this->createPartialMock( Select::class, [ @@ -94,65 +130,39 @@ protected function setUp() 'having', ] ); - $this->connectionMock = $this->createMock(AdapterInterface::class); - $this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock); - $this->resourceMock = $this->createPartialMock(ResourceConnection::class, ['getTableName', 'getConnection']); + + $storeManagerMock->expects($this->atLeastOnce())->method('getStore')->willReturn($storeManagerMock); + $storeManagerMock->expects($this->atLeastOnce())->method('getId')->willReturn(1); + $universalFactoryMock->expects($this->atLeastOnce())->method('create')->willReturn($productMock); $this->resourceMock->expects($this->atLeastOnce())->method('getTableName')->willReturn('test_table'); $this->resourceMock->expects($this->atLeastOnce())->method('getConnection')->willReturn($this->connectionMock); - $eavConfig = $this->createPartialMock(Config::class, ['getEntityType']); - $eavConfig->expects($this->atLeastOnce())->method('getEntityType')->willReturn($this->createMock(Type::class)); - $context = $this->createPartialMock(Context::class, ['getResource', 'getEavConfig']); - $context->expects($this->atLeastOnce())->method('getResource')->willReturn($this->resourceMock); - $context->expects($this->atLeastOnce())->method('getEavConfig')->willReturn($eavConfig); - $storeMock = $this->createMock(StoreInterface::class); - $storeMock->expects($this->atLeastOnce())->method('getId')->willReturn(1); - $storeManagerMock = $this->createMock(StoreManagerInterface::class); - $storeManagerMock->expects($this->atLeastOnce())->method('getStore')->willReturn($storeMock); - $productMock = $this->objectManager->getObject( - ResourceProduct::class, - [ - 'context' => $context, - 'defaultAttributes' => $this->createPartialMock( - DefaultAttributes::class, - ['_getDefaultAttributes'] - ) - ] - ); - $resourceModelPoolMock = $this->createMock(ResourceModelPoolInterface::class); - $resourceModelPoolMock->expects($this->atLeastOnce())->method('get')->willReturn($productMock); - $this->eventTypeFactoryMock = $this->createMock(TypeFactory::class); + $this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock); $this->collection = new ProductCollection( - $this->createMock(EntityFactory::class), - $this->createMock(LoggerInterface::class), - $this->createMock(FetchStrategyInterface::class), - $this->createMock(ManagerInterface::class), - $this->createMock(Config::class), + $entityFactoryMock, + $loggerMock, + $fetchStrategyMock, + $eventManagerMock, + $eavConfigMock, $this->resourceMock, - $this->createMock(EavEntityFactory::class), - $this->createMock(Helper::class), - $this->createMock(UniversalFactory::class), + $eavEntityFactoryMock, + $resourceHelperMock, + $universalFactoryMock, $storeManagerMock, - $this->createMock(Manager::class), - $this->createMock(State::class), - $this->createMock(ScopeConfigInterface::class), - $this->createMock(OptionFactory::class), - $this->createMock(Url::class), - $this->createMock(TimezoneInterface::class), - $this->createMock(Session::class), - $this->createMock(DateTime::class), - $this->createMock(GroupManagementInterface::class), + $moduleManagerMock, + $productFlatStateMock, + $scopeConfigMock, + $optionFactoryMock, + $catalogUrlMock, + $localeDateMock, + $customerSessionMock, + $dateTimeMock, + $groupManagementMock, $productMock, $this->eventTypeFactoryMock, - $this->createMock(ProductType::class), - $this->createMock(Collection::class), - $this->connectionMock, - $this->createMock(ProductLimitationFactory::class), - $this->createMock(MetadataPool::class), - $this->createMock(\Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer::class), - $this->createMock(\Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver::class), - $this->createMock(\Magento\Framework\Indexer\DimensionFactory::class), - $resourceModelPoolMock + $productTypeMock, + $quoteResourceMock, + $this->connectionMock ); } @@ -252,4 +262,25 @@ public function testAddViewsCount() $this->collection->addViewsCount(); } + + /** + * Get mock for abstract class with methods. + * + * @param string $className + * @param array $methods + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createPartialMockForAbstractClass($className, $methods) + { + return $this->getMockForAbstractClass( + $className, + [], + '', + true, + true, + true, + $methods + ); + } } diff --git a/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php b/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php index d4e50a9e43d68..ab264ef1b6179 100644 --- a/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php +++ b/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php @@ -5,20 +5,17 @@ */ namespace Magento\Review\Model\ResourceModel\Review\Product; -use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; -use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; use Magento\Framework\DB\Select; use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; /** * Review Product Collection * * @api * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @since 100.0.2 */ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection @@ -92,10 +89,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection * @param ProductLimitationFactory|null $productLimitationFactory * @param MetadataPool|null $metadataPool - * @param TableMaintainer|null $tableMaintainer - * @param PriceTableResolver|null $priceTableResolver - * @param DimensionFactory|null $dimensionFactory - * @param ResourceModelPoolInterface|null $resourceModelPool + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -122,11 +116,7 @@ public function __construct( \Magento\Review\Model\Rating\Option\VoteFactory $voteFactory, \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, ProductLimitationFactory $productLimitationFactory = null, - MetadataPool $metadataPool = null, - TableMaintainer $tableMaintainer = null, - PriceTableResolver $priceTableResolver = null, - DimensionFactory $dimensionFactory = null, - ResourceModelPoolInterface $resourceModelPool = null + MetadataPool $metadataPool = null ) { $this->_ratingFactory = $ratingFactory; $this->_voteFactory = $voteFactory; @@ -152,11 +142,7 @@ public function __construct( $groupManagement, $connection, $productLimitationFactory, - $metadataPool, - $tableMaintainer, - $priceTableResolver, - $dimensionFactory, - $resourceModelPool + $metadataPool ); } diff --git a/app/etc/di.xml b/app/etc/di.xml index 476285878650b..46903c99e422c 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -153,7 +153,6 @@ <preference for="Magento\Framework\Pricing\Amount\AmountInterface" type="Magento\Framework\Pricing\Amount\Base" /> <preference for="Magento\Framework\Api\SearchResultsInterface" type="Magento\Framework\Api\SearchResults" /> <preference for="Magento\Framework\Api\AttributeInterface" type="Magento\Framework\Api\AttributeValue" /> - <preference for="Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface" type="Magento\Framework\Model\ResourceModel\ResourceModelPool" /> <preference for="Magento\Framework\Model\ResourceModel\Db\TransactionManagerInterface" type="Magento\Framework\Model\ResourceModel\Db\TransactionManager" /> <preference for="Magento\Framework\Api\Data\ImageContentInterface" type="Magento\Framework\Api\ImageContent" /> <preference for="Magento\Framework\Api\ImageContentValidatorInterface" type="Magento\Framework\Api\ImageContentValidator" /> diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/ResourceModelPool.php b/lib/internal/Magento/Framework/Model/ResourceModel/ResourceModelPool.php deleted file mode 100644 index f62619f16e1d1..0000000000000 --- a/lib/internal/Magento/Framework/Model/ResourceModel/ResourceModelPool.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Framework\Model\ResourceModel; - -use Magento\Framework\ObjectManagerInterface; - -/** - * Pool of resource model instances per entity - */ -class ResourceModelPool implements ResourceModelPoolInterface -{ - /** - * @var ObjectManagerInterface - */ - private $objectManager; - - /** - * @param ObjectManagerInterface $objectManager - */ - public function __construct(ObjectManagerInterface $objectManager) - { - $this->objectManager = $objectManager; - } - - /** - * @inheritdoc - */ - public function get(string $resourceClassName): AbstractResource - { - return $this->objectManager->get($resourceClassName); - } -} diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/ResourceModelPoolInterface.php b/lib/internal/Magento/Framework/Model/ResourceModel/ResourceModelPoolInterface.php deleted file mode 100644 index 0274bb6504a0c..0000000000000 --- a/lib/internal/Magento/Framework/Model/ResourceModel/ResourceModelPoolInterface.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Framework\Model\ResourceModel; - -/** - * Pool of resource model instances per entity - * - * @api - */ -interface ResourceModelPoolInterface -{ - /** - * Return instance for given class name from pool. - * - * @param string $resourceClassName - * @return AbstractResource - */ - public function get(string $resourceClassName): AbstractResource; -} From 172d6138618a1df3d3b4d8e06dd0a618828f6644 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Wed, 24 Apr 2019 16:01:40 -0500 Subject: [PATCH 504/585] MC-13613: Product mass update --- app/code/Magento/Config/Model/Config.php | 8 +-- .../MessageQueue/Model/CallbackInvoker.php | 66 ------------------- .../MessageQueue/Model/PoisonPillCompare.php | 8 +-- .../Model/ResourceModel/PoisonPill.php | 39 +++++++---- .../Magento/MessageQueue/etc/db_schema.xml | 9 +-- .../MessageQueue/etc/db_schema_whitelist.json | 3 - app/code/Magento/MessageQueue/etc/di.xml | 7 +- app/code/Magento/Store/Model/Group.php | 8 +-- app/code/Magento/Store/Model/Store.php | 8 +-- app/code/Magento/Store/Model/Website.php | 8 +-- app/etc/di.xml | 4 ++ .../MessageQueue/CallbackInvoker.php | 37 +++++++++++ .../PoisonPill/PoisonPillCompare.php | 28 ++++++++ .../PoisonPillCompareInterface.php | 7 +- .../MessageQueue/PoisonPill/PoisonPillPut.php | 35 ++++++++++ .../PoisonPill}/PoisonPillPutInterface.php | 8 +-- .../PoisonPill/PoisonPillRead.php | 26 ++++++++ .../PoisonPill}/PoisonPillReadInterface.php | 8 +-- 18 files changed, 190 insertions(+), 127 deletions(-) delete mode 100644 app/code/Magento/MessageQueue/Model/CallbackInvoker.php create mode 100644 lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompare.php rename {app/code/Magento/MessageQueue/Api => lib/internal/Magento/Framework/MessageQueue/PoisonPill}/PoisonPillCompareInterface.php (69%) create mode 100644 lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPut.php rename {app/code/Magento/MessageQueue/Api => lib/internal/Magento/Framework/MessageQueue/PoisonPill}/PoisonPillPutInterface.php (75%) create mode 100644 lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php rename {app/code/Magento/MessageQueue/Api => lib/internal/Magento/Framework/MessageQueue/PoisonPill}/PoisonPillReadInterface.php (71%) diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index bd38d1451e1b6..b5dbf97f7953d 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -115,7 +115,7 @@ class Config extends \Magento\Framework\DataObject private $scopeTypeNormalizer; /** - * @var \Magento\MessageQueue\Api\PoisonPillPutInterface + * @var \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface */ private $pillPut; @@ -131,7 +131,7 @@ class Config extends \Magento\Framework\DataObject * @param array $data * @param ScopeResolverPool|null $scopeResolverPool * @param ScopeTypeNormalizer|null $scopeTypeNormalizer - * @param \Magento\MessageQueue\Api\PoisonPillPutInterface|null $pillPut + * @param \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface|null $pillPut * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -146,7 +146,7 @@ public function __construct( array $data = [], ScopeResolverPool $scopeResolverPool = null, ScopeTypeNormalizer $scopeTypeNormalizer = null, - \Magento\MessageQueue\Api\PoisonPillPutInterface $pillPut = null + \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface $pillPut = null ) { parent::__construct($data); $this->_eventManager = $eventManager; @@ -163,7 +163,7 @@ public function __construct( $this->scopeTypeNormalizer = $scopeTypeNormalizer ?? ObjectManager::getInstance()->get(ScopeTypeNormalizer::class); $this->pillPut = $pillPut ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\MessageQueue\Api\PoisonPillPutInterface::class); + ->get(\Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface::class); } /** diff --git a/app/code/Magento/MessageQueue/Model/CallbackInvoker.php b/app/code/Magento/MessageQueue/Model/CallbackInvoker.php deleted file mode 100644 index f6305363fc1a6..0000000000000 --- a/app/code/Magento/MessageQueue/Model/CallbackInvoker.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\MessageQueue\Model; - -use Magento\Framework\MessageQueue\CallbackInvokerInterface; -use Magento\Framework\MessageQueue\QueueInterface; -use Magento\MessageQueue\Api\PoisonPillCompareInterface; -use Magento\MessageQueue\Api\PoisonPillReadInterface; - -/** - * Callback invoker - */ -class CallbackInvoker implements CallbackInvokerInterface -{ - /** - * @var PoisonPillReadInterface $poisonPillRead - */ - private $poisonPillRead; - - /** - * @var int $poisonPillVersion - */ - private $poisonPillVersion; - - /** - * @var PoisonPillCompareInterface - */ - private $poisonPillCompare; - - /** - * @param PoisonPillReadInterface $poisonPillRead - * @param PoisonPillCompareInterface $poisonPillCompare - */ - public function __construct( - PoisonPillReadInterface $poisonPillRead, - PoisonPillCompareInterface $poisonPillCompare - ) { - $this->poisonPillRead = $poisonPillRead; - $this->poisonPillCompare = $poisonPillCompare; - } - - /** - * @inheritdoc - */ - public function invoke(QueueInterface $queue, $maxNumberOfMessages, $callback) - { - $this->poisonPillVersion = $this->poisonPillRead->getLatestVersion(); - for ($i = $maxNumberOfMessages; $i > 0; $i--) { - do { - $message = $queue->dequeue(); - // phpcs:ignore Magento2.Functions.DiscouragedFunction - } while ($message === null && (sleep(1) === 0)); - if (false === $this->poisonPillCompare->isLatestVersion($this->poisonPillVersion)) { - $queue->reject($message); - // phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage - exit(0); - } - $callback($message); - } - } -} diff --git a/app/code/Magento/MessageQueue/Model/PoisonPillCompare.php b/app/code/Magento/MessageQueue/Model/PoisonPillCompare.php index a8e40ea495002..a4c89fd26506b 100644 --- a/app/code/Magento/MessageQueue/Model/PoisonPillCompare.php +++ b/app/code/Magento/MessageQueue/Model/PoisonPillCompare.php @@ -7,8 +7,8 @@ namespace Magento\MessageQueue\Model; -use Magento\MessageQueue\Api\PoisonPillCompareInterface; -use Magento\MessageQueue\Api\PoisonPillReadInterface; +use Magento\Framework\MessageQueue\PoisonPill\PoisonPillCompareInterface; +use Magento\Framework\MessageQueue\PoisonPill\PoisonPillReadInterface; /** * Poison pill compare @@ -33,8 +33,8 @@ public function __construct( /** * @inheritdoc */ - public function isLatestVersion(int $poisonPillVersion): bool + public function isLatestVersion(string $poisonPillVersion): bool { - return $poisonPillVersion === $this->poisonPillRead->getLatestVersion(); + return (string) $poisonPillVersion === (string) $this->poisonPillRead->getLatestVersion(); } } diff --git a/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php b/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php index 283fff8ace7c7..e7dbc1af3f2b8 100644 --- a/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php +++ b/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php @@ -7,13 +7,13 @@ namespace Magento\MessageQueue\Model\ResourceModel; -use Magento\MessageQueue\Api\PoisonPillReadInterface; -use Magento\MessageQueue\Api\PoisonPillPutInterface; +use Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface; +use Magento\Framework\MessageQueue\PoisonPill\PoisonPillReadInterface; use Magento\Framework\Model\ResourceModel\Db\Context; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; /** - * PoisonPill. + * PoisonPill class that enclose read and put interface. */ class PoisonPill extends AbstractDb implements PoisonPillPutInterface, PoisonPillReadInterface { @@ -46,30 +46,43 @@ protected function _construct() /** * @inheritdoc */ - public function put(): int + public function put(): string { $connection = $this->getConnection(); $table = $this->getMainTable(); - $connection->insert($table, []); - return (int)$connection->lastInsertId($table); + $uuid = uniqid('version-'); + $version = $this->getVersionFromDb(); + if ($version !== null) { + $connection->update($table, ['version' => $uuid]); + } else { + $connection->insert($table, ['version' => $uuid]); + } + + return $uuid; } /** * @inheritdoc */ - public function getLatestVersion() : int + public function getLatestVersion(): ?string + { + return $this->getVersionFromDb(); + } + + /** + * Returns version form DB or null. + * + * @return string|null + */ + private function getVersionFromDb(): ?string { $select = $this->getConnection()->select()->from( $this->getTable(self::QUEUE_POISON_PILL_TABLE), 'version' - )->order( - 'version ' . \Magento\Framework\DB\Select::SQL_DESC - )->limit( - 1 ); - $version = (int)$this->getConnection()->fetchOne($select); + $result = $this->getConnection()->fetchOne($select); - return $version; + return $result === false ? null : $result; } } diff --git a/app/code/Magento/MessageQueue/etc/db_schema.xml b/app/code/Magento/MessageQueue/etc/db_schema.xml index 9cdf414dd06e1..4403384e9311a 100644 --- a/app/code/Magento/MessageQueue/etc/db_schema.xml +++ b/app/code/Magento/MessageQueue/etc/db_schema.xml @@ -21,12 +21,7 @@ <column name="message_code"/> </constraint> </table> - <table name="queue_poison_pill" resource="default" engine="innodb" - comment="Sequence table for poison pill versions"> - <column xsi:type="int" name="version" padding="10" unsigned="true" nullable="false" identity="true" - comment="Poison Pill version."/> - <constraint xsi:type="primary" referenceId="PRIMARY"> - <column name="version"/> - </constraint> + <table name="queue_poison_pill" resource="default" engine="innodb" comment="Sequence table for poison pill versions"> + <column xsi:type="varchar" name="version" length="255" nullable="false" comment="Poison Pill version."/> </table> </schema> diff --git a/app/code/Magento/MessageQueue/etc/db_schema_whitelist.json b/app/code/Magento/MessageQueue/etc/db_schema_whitelist.json index d9d623a994b37..37a342b21e64c 100644 --- a/app/code/Magento/MessageQueue/etc/db_schema_whitelist.json +++ b/app/code/Magento/MessageQueue/etc/db_schema_whitelist.json @@ -13,9 +13,6 @@ "queue_poison_pill": { "column": { "version": true - }, - "constraint": { - "PRIMARY": true } } } diff --git a/app/code/Magento/MessageQueue/etc/di.xml b/app/code/Magento/MessageQueue/etc/di.xml index 22cfea976a722..f60eb5fbc20df 100644 --- a/app/code/Magento/MessageQueue/etc/di.xml +++ b/app/code/Magento/MessageQueue/etc/di.xml @@ -13,10 +13,9 @@ <preference for="Magento\Framework\MessageQueue\EnvelopeInterface" type="Magento\Framework\MessageQueue\Envelope"/> <preference for="Magento\Framework\MessageQueue\ConsumerInterface" type="Magento\Framework\MessageQueue\Consumer"/> <preference for="Magento\Framework\MessageQueue\MergedMessageInterface" type="Magento\Framework\MessageQueue\MergedMessage"/> - <preference for="Magento\MessageQueue\Api\PoisonPillCompareInterface" type="Magento\MessageQueue\Model\PoisonPillCompare"/> - <preference for="Magento\MessageQueue\Api\PoisonPillPutInterface" type="Magento\MessageQueue\Model\ResourceModel\PoisonPill"/> - <preference for="Magento\MessageQueue\Api\PoisonPillReadInterface" type="Magento\MessageQueue\Model\ResourceModel\PoisonPill"/> - <preference for="Magento\Framework\MessageQueue\CallbackInvokerInterface" type="Magento\MessageQueue\Model\CallbackInvoker"/> + <preference for="Magento\Framework\MessageQueue\PoisonPill\PoisonPillCompareInterface" type="Magento\MessageQueue\Model\PoisonPillCompare"/> + <preference for="Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface" type="Magento\MessageQueue\Model\ResourceModel\PoisonPill"/> + <preference for="Magento\Framework\MessageQueue\PoisonPill\PoisonPillReadInterface" type="Magento\MessageQueue\Model\ResourceModel\PoisonPill"/> <type name="Magento\Framework\Console\CommandListInterface"> <arguments> <argument name="commands" xsi:type="array"> diff --git a/app/code/Magento/Store/Model/Group.php b/app/code/Magento/Store/Model/Group.php index 19f104c9f3790..4cd7bc93d3334 100644 --- a/app/code/Magento/Store/Model/Group.php +++ b/app/code/Magento/Store/Model/Group.php @@ -101,7 +101,7 @@ class Group extends \Magento\Framework\Model\AbstractExtensibleModel implements private $eventManager; /** - * @var \Magento\MessageQueue\Api\PoisonPillPutInterface + * @var \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface */ private $pillPut; @@ -117,7 +117,7 @@ class Group extends \Magento\Framework\Model\AbstractExtensibleModel implements * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection * @param array $data * @param \Magento\Framework\Event\ManagerInterface|null $eventManager - * @param \Magento\MessageQueue\Api\PoisonPillPutInterface|null $pillPut + * @param \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface|null $pillPut * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -132,7 +132,7 @@ public function __construct( \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [], \Magento\Framework\Event\ManagerInterface $eventManager = null, - \Magento\MessageQueue\Api\PoisonPillPutInterface $pillPut = null + \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface $pillPut = null ) { $this->_configDataResource = $configDataResource; $this->_storeListFactory = $storeListFactory; @@ -140,7 +140,7 @@ public function __construct( $this->eventManager = $eventManager ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\Event\ManagerInterface::class); $this->pillPut = $pillPut ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\MessageQueue\Api\PoisonPillPutInterface::class); + ->get(\Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface::class); parent::__construct( $context, $registry, diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index 6814ad418bacc..5a47bac1ace78 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -327,7 +327,7 @@ class Store extends AbstractExtensibleModel implements private $eventManager; /** - * @var \Magento\MessageQueue\Api\PoisonPillPutInterface + * @var \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface */ private $pillPut; @@ -357,7 +357,7 @@ class Store extends AbstractExtensibleModel implements * @param bool $isCustomEntryPoint * @param array $data optional generic object data * @param \Magento\Framework\Event\ManagerInterface|null $eventManager - * @param \Magento\MessageQueue\Api\PoisonPillPutInterface|null $pillPut + * @param \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface|null $pillPut * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -387,7 +387,7 @@ public function __construct( $isCustomEntryPoint = false, array $data = [], \Magento\Framework\Event\ManagerInterface $eventManager = null, - \Magento\MessageQueue\Api\PoisonPillPutInterface $pillPut = null + \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface $pillPut = null ) { $this->_coreFileStorageDatabase = $coreFileStorageDatabase; $this->_config = $config; @@ -409,7 +409,7 @@ public function __construct( $this->eventManager = $eventManager ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\Event\ManagerInterface::class); $this->pillPut = $pillPut ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\MessageQueue\Api\PoisonPillPutInterface::class); + ->get(\Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface::class); parent::__construct( $context, $registry, diff --git a/app/code/Magento/Store/Model/Website.php b/app/code/Magento/Store/Model/Website.php index 383b36fd63228..42c89bbe4210d 100644 --- a/app/code/Magento/Store/Model/Website.php +++ b/app/code/Magento/Store/Model/Website.php @@ -160,7 +160,7 @@ class Website extends \Magento\Framework\Model\AbstractExtensibleModel implement protected $_currencyFactory; /** - * @var \Magento\MessageQueue\Api\PoisonPillPutInterface + * @var \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface */ private $pillPut; @@ -179,7 +179,7 @@ class Website extends \Magento\Framework\Model\AbstractExtensibleModel implement * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data - * @param \Magento\MessageQueue\Api\PoisonPillPutInterface|null $pillPut + * @param \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface|null $pillPut * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -197,7 +197,7 @@ public function __construct( \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [], - \Magento\MessageQueue\Api\PoisonPillPutInterface $pillPut = null + \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface $pillPut = null ) { parent::__construct( $context, @@ -216,7 +216,7 @@ public function __construct( $this->_storeManager = $storeManager; $this->_currencyFactory = $currencyFactory; $this->pillPut = $pillPut ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\MessageQueue\Api\PoisonPillPutInterface::class); + ->get(\Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface::class); } /** diff --git a/app/etc/di.xml b/app/etc/di.xml index 476285878650b..9a772ec91e52c 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -1765,4 +1765,8 @@ <argument name="delayTimeout" xsi:type="number">20</argument> </arguments> </type> + <preference for="Magento\Framework\MessageQueue\PoisonPill\PoisonPillCompareInterface" type="Magento\Framework\MessageQueue\PoisonPill\PoisonPillCompare"/> + <preference for="Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface" type="Magento\Framework\MessageQueue\PoisonPill\PoisonPillPut"/> + <preference for="Magento\Framework\MessageQueue\PoisonPill\PoisonPillReadInterface" type="Magento\Framework\MessageQueue\PoisonPill\PoisonPillRead"/> + <preference for="Magento\Framework\MessageQueue\CallbackInvokerInterface" type="Magento\Framework\MessageQueue\CallbackInvoker"/> </config> diff --git a/lib/internal/Magento/Framework/MessageQueue/CallbackInvoker.php b/lib/internal/Magento/Framework/MessageQueue/CallbackInvoker.php index 48c33c48f12e6..fe0a84af3ca93 100644 --- a/lib/internal/Magento/Framework/MessageQueue/CallbackInvoker.php +++ b/lib/internal/Magento/Framework/MessageQueue/CallbackInvoker.php @@ -6,11 +6,41 @@ namespace Magento\Framework\MessageQueue; +use Magento\Framework\MessageQueue\PoisonPill\PoisonPillCompareInterface; +use Magento\Framework\MessageQueue\PoisonPill\PoisonPillReadInterface; + /** * Class CallbackInvoker to invoke callbacks for consumer classes */ class CallbackInvoker implements CallbackInvokerInterface { + /** + * @var PoisonPillReadInterface $poisonPillRead + */ + private $poisonPillRead; + + /** + * @var int $poisonPillVersion + */ + private $poisonPillVersion; + + /** + * @var PoisonPillCompareInterface + */ + private $poisonPillCompare; + + /** + * @param PoisonPillReadInterface $poisonPillRead + * @param PoisonPillCompareInterface $poisonPillCompare + */ + public function __construct( + PoisonPillReadInterface $poisonPillRead, + PoisonPillCompareInterface $poisonPillCompare + ) { + $this->poisonPillRead = $poisonPillRead; + $this->poisonPillCompare = $poisonPillCompare; + } + /** * Run short running process * @@ -21,10 +51,17 @@ class CallbackInvoker implements CallbackInvokerInterface */ public function invoke(QueueInterface $queue, $maxNumberOfMessages, $callback) { + $this->poisonPillVersion = $this->poisonPillRead->getLatestVersion(); for ($i = $maxNumberOfMessages; $i > 0; $i--) { do { $message = $queue->dequeue(); + // phpcs:ignore Magento2.Functions.DiscouragedFunction } while ($message === null && (sleep(1) === 0)); + if (false === $this->poisonPillCompare->isLatestVersion($this->poisonPillVersion)) { + $queue->reject($message); + // phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage + exit(0); + } $callback($message); } } diff --git a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompare.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompare.php new file mode 100644 index 0000000000000..404cf96964f6e --- /dev/null +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompare.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Framework\MessageQueue\PoisonPill; + +/** + * Interface describes how to describes how to compare poison pill with latest in DB. + * + */ +class PoisonPillCompare implements PoisonPillCompareInterface +{ + /** + * Dumb implementation + * + * @todo Will use cache storage after @MC-15997 + * + * @param string $poisonPillVersion + * @return bool + */ + public function isLatestVersion(string $poisonPillVersion): bool + { + return true; + } +} diff --git a/app/code/Magento/MessageQueue/Api/PoisonPillCompareInterface.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompareInterface.php similarity index 69% rename from app/code/Magento/MessageQueue/Api/PoisonPillCompareInterface.php rename to lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompareInterface.php index 3d5b895575597..e26b21d5a5387 100644 --- a/app/code/Magento/MessageQueue/Api/PoisonPillCompareInterface.php +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompareInterface.php @@ -5,20 +5,19 @@ */ declare(strict_types=1); -namespace Magento\MessageQueue\Api; +namespace Magento\Framework\MessageQueue\PoisonPill; /** * Interface describes how to describes how to compare poison pill with latest in DB. * - * @api */ interface PoisonPillCompareInterface { /** * Check if version of current poison pill is latest. * - * @param int $poisonPillVersion + * @param string $poisonPillVersion * @return bool */ - public function isLatestVersion(int $poisonPillVersion): bool; + public function isLatestVersion(string $poisonPillVersion): bool; } diff --git a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPut.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPut.php new file mode 100644 index 0000000000000..08c67567ee5d3 --- /dev/null +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPut.php @@ -0,0 +1,35 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Framework\MessageQueue\PoisonPill; + +use Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface; + +/** + * Command interface describes how to create new version on poison pill. + */ +class PoisonPillPut implements PoisonPillPutInterface +{ + /** + * First version of poison pill. + * + * @var string + */ + private $firstVersion = ''; + + /** + * Dumb framework implementation. + * + * @todo Will use cache storage after @MC-15997 + * + * @return string + */ + public function put(): string + { + return $this->firstVersion; + } +} diff --git a/app/code/Magento/MessageQueue/Api/PoisonPillPutInterface.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPutInterface.php similarity index 75% rename from app/code/Magento/MessageQueue/Api/PoisonPillPutInterface.php rename to lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPutInterface.php index 02293c99bb3f4..dbf300101c453 100644 --- a/app/code/Magento/MessageQueue/Api/PoisonPillPutInterface.php +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPutInterface.php @@ -5,20 +5,18 @@ */ declare(strict_types=1); -namespace Magento\MessageQueue\Api; +namespace Magento\Framework\MessageQueue\PoisonPill; /** * Command interface describes how to create new version on poison pill. - * - * @api */ interface PoisonPillPutInterface { /** * Put new version of poison pill inside DB. * - * @return int + * @return string * @throws \Exception */ - public function put(): int; + public function put(): string; } diff --git a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php new file mode 100644 index 0000000000000..b3013cb8c61c9 --- /dev/null +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Framework\MessageQueue\PoisonPill; + +/** + * Describes how to get latest version of poison pill. + */ +class PoisonPillRead implements PoisonPillReadInterface +{ + /** + * Returns get latest version of poison pill. + * + * @todo Will use cache storage after @MC-15997 + * + * @return string + */ + public function getLatestVersion(): ?string + { + return null; + } +} diff --git a/app/code/Magento/MessageQueue/Api/PoisonPillReadInterface.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillReadInterface.php similarity index 71% rename from app/code/Magento/MessageQueue/Api/PoisonPillReadInterface.php rename to lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillReadInterface.php index db97990ebbad5..55ff5feb2d9b2 100644 --- a/app/code/Magento/MessageQueue/Api/PoisonPillReadInterface.php +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillReadInterface.php @@ -5,19 +5,17 @@ */ declare(strict_types=1); -namespace Magento\MessageQueue\Api; +namespace Magento\Framework\MessageQueue\PoisonPill; /** * Describes how to get latest version of poison pill. - * - * @api */ interface PoisonPillReadInterface { /** * Returns get latest version of poison pill. * - * @return int + * @return string */ - public function getLatestVersion(): int; + public function getLatestVersion(): ?string; } From e73db01922a3165a99304080a2b06a582f7b9941 Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Wed, 24 Apr 2019 20:51:33 -0400 Subject: [PATCH 505/585] Fix condition setting po number from input --- .../QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php index d1dcb4a48a76b..9f5862ef36438 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php @@ -70,7 +70,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $paymentMethodCode = $args['input']['payment_method']['code']; $poNumber = isset($args['input']['payment_method']['purchase_order_number']) - && empty($args['input']['payment_method']['purchase_order_number']) + && !empty($args['input']['payment_method']['purchase_order_number']) ? $args['input']['payment_method']['purchase_order_number'] : null; From 97c416c28898c9d4433a40ef351ce136c112a083 Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Wed, 24 Apr 2019 20:59:18 -0400 Subject: [PATCH 506/585] Test for offline payment methods Fixes #601 --- .../SetOfflinePaymentMethodsOnCartTest.php | 168 ++++++++++++++++++ .../SetOfflinePaymentMethodsOnCartTest.php | 147 +++++++++++++++ 2 files changed, 315 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php new file mode 100644 index 0000000000000..e0f4756177715 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php @@ -0,0 +1,168 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\OfflinePayments\Model\Banktransfer; +use Magento\OfflinePayments\Model\Cashondelivery; +use Magento\OfflinePayments\Model\Checkmo; +use Magento\OfflinePayments\Model\Purchaseorder; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for setting offline payment methods on cart + */ +class SetOfflinePaymentMethodsOnCartTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * + * @param string $methodCode + * @dataProvider offlinePaymentMethodDataProvider + */ + public function testSetOfflinePaymentMethod(string $methodCode) + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery( + $maskedQuoteId, + $methodCode + ); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * + * @param string $methodCode + */ + public function testSetPurchaseOrderPaymentMethod() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $poNumber = 'abc123'; + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "{$maskedQuoteId}", + payment_method: { + code: "{$methodCode}" + purchase_order_number: "{$poNumber}" + } + }) { + cart { + selected_payment_method { + code + purchase_order_number + } + } + } +} +QUERY; + + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertArrayHasKey('purchase_order_number', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + self::assertEquals($poNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); + } + + /** + * @return array + */ + public function offlinePaymentMethodDataProvider(): array + { + return [ + 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE], + 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE], + 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE], + ]; + } + + /** + * @param string $maskedQuoteId + * @param string $methodCode + * @return string + */ + private function getQuery( + string $maskedQuoteId, + string $methodCode + ) : string { + return <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "{$maskedQuoteId}", + payment_method: { + code: "{$methodCode}" + } + }) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php new file mode 100644 index 0000000000000..83fffd9defabf --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php @@ -0,0 +1,147 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\OfflinePayments\Model\Banktransfer; +use Magento\OfflinePayments\Model\Cashondelivery; +use Magento\OfflinePayments\Model\Checkmo; +use Magento\OfflinePayments\Model\Purchaseorder; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for setting offline payment methods on cart + */ +class SetOfflinePaymentMethodsOnCartTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * + * @param string $methodCode + * @dataProvider offlinePaymentMethodDataProvider + */ + public function testSetOfflinePaymentMethod(string $methodCode) + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery( + $maskedQuoteId, + $methodCode + ); + $response = $this->graphQlMutation($query); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * + * @param string $methodCode + */ + public function testSetPurchaseOrderPaymentMethod() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $poNumber = 'abc123'; + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "{$maskedQuoteId}", + payment_method: { + code: "{$methodCode}" + purchase_order_number: "{$poNumber}" + } + }) { + cart { + selected_payment_method { + code + purchase_order_number + } + } + } +} +QUERY; + + $response = $this->graphQlMutation($query); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertArrayHasKey('purchase_order_number', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + self::assertEquals($poNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); + } + + /** + * @return array + */ + public function offlinePaymentMethodDataProvider(): array + { + return [ + 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE], + 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE], + 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE], + ]; + } + + /** + * @param string $maskedQuoteId + * @param string $methodCode + * @return string + */ + private function getQuery( + string $maskedQuoteId, + string $methodCode + ) : string { + return <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "{$maskedQuoteId}", + payment_method: { + code: "{$methodCode}" + } + }) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + } +} From c64fd576dbf1aede214705785b4792b74b08fa48 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 23 Apr 2019 16:00:31 +0300 Subject: [PATCH 507/585] magento/magento2#21963: Functional test fix. --- .../Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml | 2 +- .../app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml index 1a12a68a6874a..1c3cf9cc2b350 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminOrderFormPaymentSection"> - <element name="header" type="text" selector="#shipping-methods span.title"/> + <element name="header" type="text" selector="#order-methods span.title"/> <element name="getShippingMethods" type="text" selector="#order-shipping_method a.action-default" timeout="30"/> <element name="flatRateOption" type="radio" selector="#s_method_flatrate_flatrate" timeout="30"/> <element name="shippingError" type="text" selector="#order[has_shipping]-error"/> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php index 14bc04cfed70c..f460cd91167de 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php @@ -105,7 +105,7 @@ class Create extends Block * * @var string */ - protected $orderMethodsSelector = '#shipping-methods'; + protected $orderMethodsSelector = '#order-methods'; /** * Page header. From 96b6feb5feacb130c7c0e181db79b5718fb8b98b Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Wed, 24 Apr 2019 17:15:17 +0300 Subject: [PATCH 508/585] Decrease overall product repository complexity. --- .../Catalog/Model/ProductRepository.php | 154 ++--------- .../MediaGalleryProcessor.php | 239 ++++++++++++++++++ .../Test/Unit/Model/ProductRepositoryTest.php | 93 ++++--- 3 files changed, 322 insertions(+), 164 deletions(-) create mode 100644 app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index d34fa6bbd6534..c87b6e9763205 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -11,9 +10,9 @@ use Magento\Catalog\Api\Data\ProductExtension; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product\Gallery\MimeTypeExtensionMap; +use Magento\Catalog\Model\ProductRepository\MediaGalleryProcessor; use Magento\Catalog\Model\ResourceModel\Product\Collection; use Magento\Eav\Model\Entity\Attribute\Exception as AttributeException; -use Magento\Framework\Api\Data\ImageContentInterface; use Magento\Framework\Api\Data\ImageContentInterfaceFactory; use Magento\Framework\Api\ImageContentValidatorInterface; use Magento\Framework\Api\ImageProcessorInterface; @@ -26,8 +25,8 @@ use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Framework\Exception\TemporaryState\CouldNotSaveException as TemporaryCouldNotSaveException; use Magento\Framework\Exception\StateException; +use Magento\Framework\Exception\TemporaryState\CouldNotSaveException as TemporaryCouldNotSaveException; use Magento\Framework\Exception\ValidatorException; /** @@ -123,11 +122,15 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa protected $fileSystem; /** + * @deprecated + * * @var ImageContentInterfaceFactory */ protected $contentFactory; /** + * @deprecated + * * @var ImageProcessorInterface */ protected $imageProcessor; @@ -138,10 +141,17 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa protected $extensionAttributesJoinProcessor; /** + * @deprecated + * * @var \Magento\Catalog\Model\Product\Gallery\Processor */ protected $mediaGalleryProcessor; + /** + * @var MediaGalleryProcessor + */ + private $mediaProcessor; + /** * @var CollectionProcessorInterface */ @@ -192,8 +202,8 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa * @param CollectionProcessorInterface $collectionProcessor [optional] * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer * @param int $cacheLimit [optional] - * @param ReadExtensions|null $readExtensions - * @param Magento\Catalog\Api\CategoryLinkManagementInterface|null $linkManagement + * @param ReadExtensions $readExtensions + * @param CategoryLinkManagementInterface $linkManagement * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ @@ -391,6 +401,9 @@ private function assignProductToWebsites(\Magento\Catalog\Model\Product $product /** * Process new gallery media entry. * + * @deprecated + * @see MediaGalleryProcessor::processNewMediaGalleryEntry() + * * @param ProductInterface $product * @param array $newEntry * @return $this @@ -402,40 +415,8 @@ protected function processNewMediaGalleryEntry( ProductInterface $product, array $newEntry ) { - /** @var ImageContentInterface $contentDataObject */ - $contentDataObject = $newEntry['content']; - - /** @var \Magento\Catalog\Model\Product\Media\Config $mediaConfig */ - $mediaConfig = $product->getMediaConfig(); - $mediaTmpPath = $mediaConfig->getBaseTmpMediaPath(); - - $relativeFilePath = $this->imageProcessor->processImageContent($mediaTmpPath, $contentDataObject); - $tmpFilePath = $mediaConfig->getTmpMediaShortUrl($relativeFilePath); + $this->getMediaGalleryProcessor()->processNewMediaGalleryEntry($product, $newEntry); - if (!$product->hasGalleryAttribute()) { - throw new StateException( - __("The product that was requested doesn't exist. Verify the product and try again.") - ); - } - - $imageFileUri = $this->getMediaGalleryProcessor()->addImage( - $product, - $tmpFilePath, - isset($newEntry['types']) ? $newEntry['types'] : [], - true, - isset($newEntry['disabled']) ? $newEntry['disabled'] : true - ); - // Update additional fields that are still empty after addImage call - $this->getMediaGalleryProcessor()->updateImage( - $product, - $imageFileUri, - [ - 'label' => $newEntry['label'], - 'position' => $newEntry['position'], - 'disabled' => $newEntry['disabled'], - 'media_type' => $newEntry['media_type'], - ] - ); return $this; } @@ -510,68 +491,13 @@ private function processLinks(ProductInterface $product, $newLinks) * @return $this * @throws InputException * @throws StateException + * @throws LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function processMediaGallery(ProductInterface $product, $mediaGalleryEntries) { - $existingMediaGallery = $product->getMediaGallery('images'); - $newEntries = []; - $entriesById = []; - if (!empty($existingMediaGallery)) { - foreach ($mediaGalleryEntries as $entry) { - if (isset($entry['value_id'])) { - $entriesById[$entry['value_id']] = $entry; - } else { - $newEntries[] = $entry; - } - } - foreach ($existingMediaGallery as $key => &$existingEntry) { - if (isset($entriesById[$existingEntry['value_id']])) { - $updatedEntry = $entriesById[$existingEntry['value_id']]; - if ($updatedEntry['file'] === null) { - unset($updatedEntry['file']); - } - $existingMediaGallery[$key] = array_merge($existingEntry, $updatedEntry); - } else { - //set the removed flag - $existingEntry['removed'] = true; - } - } - $product->setData('media_gallery', ["images" => $existingMediaGallery]); - } else { - $newEntries = $mediaGalleryEntries; - } - - $images = (array)$product->getMediaGallery('images'); - $images = $this->determineImageRoles($product, $images); - - $this->getMediaGalleryProcessor()->clearMediaAttribute($product, array_keys($product->getMediaAttributes())); - - foreach ($images as $image) { - if (!isset($image['removed']) && !empty($image['types'])) { - $this->getMediaGalleryProcessor()->setMediaAttribute($product, $image['types'], $image['file']); - } - } + $this->getMediaGalleryProcessor()->processMediaGallery($product, $mediaGalleryEntries); - foreach ($newEntries as $newEntry) { - if (!isset($newEntry['content'])) { - throw new InputException(__('The image content is invalid. Verify the content and try again.')); - } - /** @var ImageContentInterface $contentDataObject */ - $contentDataObject = $this->contentFactory->create() - ->setName($newEntry['content']['data'][ImageContentInterface::NAME]) - ->setBase64EncodedData($newEntry['content']['data'][ImageContentInterface::BASE64_ENCODED_DATA]) - ->setType($newEntry['content']['data'][ImageContentInterface::TYPE]); - $newEntry['content'] = $contentDataObject; - $this->processNewMediaGalleryEntry($product, $newEntry); - - $finalGallery = $product->getData('media_gallery'); - $newEntryId = key(array_diff_key($product->getData('media_gallery')['images'], $entriesById)); - $newEntry = array_replace_recursive($newEntry, $finalGallery['images'][$newEntryId]); - $entriesById[$newEntryId] = $newEntry; - $finalGallery['images'][$newEntryId] = $newEntry; - $product->setData('media_gallery', $finalGallery); - } return $this; } @@ -781,44 +707,19 @@ public function cleanCache() $this->instancesById = null; } - /** - * Ascertain image roles, if they are not set against the gallery entries - * - * @param ProductInterface $product - * @param array $images - * @return array - */ - private function determineImageRoles(ProductInterface $product, array $images) : array - { - $imagesWithRoles = []; - foreach ($images as $image) { - if (!isset($image['types'])) { - $image['types'] = []; - if (isset($image['file'])) { - foreach (array_keys($product->getMediaAttributes()) as $attribute) { - if ($image['file'] == $product->getData($attribute)) { - $image['types'][] = $attribute; - } - } - } - } - $imagesWithRoles[] = $image; - } - return $imagesWithRoles; - } - /** * Retrieve media gallery processor. * - * @return Product\Gallery\Processor + * @return MediaGalleryProcessor */ private function getMediaGalleryProcessor() { - if (null === $this->mediaGalleryProcessor) { - $this->mediaGalleryProcessor = \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Catalog\Model\Product\Gallery\Processor::class); + if (null === $this->mediaProcessor) { + $this->mediaProcessor = \Magento\Framework\App\ObjectManager::getInstance() + ->get(MediaGalleryProcessor::class); } - return $this->mediaGalleryProcessor; + + return $this->mediaProcessor; } /** @@ -930,6 +831,7 @@ private function saveProduct($product): void throw new CouldNotSaveException(__($e->getMessage())); } catch (LocalizedException $e) { throw $e; + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (\Exception $e) { throw new CouldNotSaveException( __('The product was unable to be saved. Please try again.'), diff --git a/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php b/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php new file mode 100644 index 0000000000000..70311954f63e9 --- /dev/null +++ b/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php @@ -0,0 +1,239 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\ProductRepository; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\Product\Gallery\Processor; +use Magento\Catalog\Model\Product\Media\Config; +use Magento\Framework\Api\Data\ImageContentInterface; +use Magento\Framework\Api\Data\ImageContentInterfaceFactory; +use Magento\Framework\Api\ImageProcessorInterface; +use Magento\Framework\Exception\InputException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\StateException; + +/** + * Process Media gallery data for ProductRepository before save product. + */ +class MediaGalleryProcessor +{ + /** + * Catalog gallery processor. + * + * @var Processor + */ + private $processor; + + /** + * Image content data object factory. + * + * @var ImageContentInterfaceFactory + */ + private $contentFactory; + + /** + * Image processor. + * + * @var ImageProcessorInterface + */ + private $imageProcessor; + + /** + * @param Processor $processor + * @param ImageContentInterfaceFactory $contentFactory + * @param ImageProcessorInterface $imageProcessor + */ + public function __construct( + Processor $processor, + ImageContentInterfaceFactory $contentFactory, + ImageProcessorInterface $imageProcessor + ) { + $this->processor = $processor; + $this->contentFactory = $contentFactory; + $this->imageProcessor = $imageProcessor; + } + + /** + * Process Media gallery data before save product. + * + * Compare Media Gallery Entries Data with existing Media Gallery + * * If Media entry has not value_id set it as new + * * If Existing entry 'value_id' absent in Media Gallery set 'removed' flag + * * Merge Existing and new media gallery + * + * @param ProductInterface $product contains only existing media gallery items + * @param array $mediaGalleryEntries array which contains all media gallery items + * @return void + * @throws InputException + * @throws StateException + * @throws LocalizedException + */ + public function processMediaGallery(ProductInterface $product, array $mediaGalleryEntries) :void + { + $existingMediaGallery = $product->getMediaGallery('images'); + $newEntries = []; + $entriesById = []; + if (!empty($existingMediaGallery)) { + foreach ($mediaGalleryEntries as $entry) { + if (isset($entry['value_id'])) { + $entriesById[$entry['value_id']] = $entry; + } else { + $newEntries[] = $entry; + } + } + foreach ($existingMediaGallery as $key => &$existingEntry) { + if (isset($entriesById[$existingEntry['value_id']])) { + $updatedEntry = $entriesById[$existingEntry['value_id']]; + if ($updatedEntry['file'] === null) { + unset($updatedEntry['file']); + } + $existingMediaGallery[$key] = array_merge($existingEntry, $updatedEntry); + } else { + //set the removed flag + $existingEntry['removed'] = true; + } + } + $product->setData('media_gallery', ["images" => $existingMediaGallery]); + } else { + $newEntries = $mediaGalleryEntries; + } + + $images = (array)$product->getMediaGallery('images'); + $images = $this->determineImageRoles($product, $images); + + $this->processor->clearMediaAttribute($product, array_keys($product->getMediaAttributes())); + + $this->processMediaAttributes($product, $images); + $this->processEntries($product, $newEntries, $entriesById); + } + + /** + * Process new gallery media entry. + * + * @param ProductInterface $product + * @param array $newEntry + * @return void + * @throws InputException + * @throws StateException + * @throws LocalizedException + */ + public function processNewMediaGalleryEntry( + ProductInterface $product, + array $newEntry + ) :void { + /** @var ImageContentInterface $contentDataObject */ + $contentDataObject = $newEntry['content']; + + /** @var Config $mediaConfig */ + $mediaConfig = $product->getMediaConfig(); + $mediaTmpPath = $mediaConfig->getBaseTmpMediaPath(); + + $relativeFilePath = $this->imageProcessor->processImageContent($mediaTmpPath, $contentDataObject); + $tmpFilePath = $mediaConfig->getTmpMediaShortUrl($relativeFilePath); + + if (!$product->hasGalleryAttribute()) { + throw new StateException( + __("The product that was requested doesn't exist. Verify the product and try again.") + ); + } + + $imageFileUri = $this->processor->addImage( + $product, + $tmpFilePath, + isset($newEntry['types']) ? $newEntry['types'] : [], + true, + isset($newEntry['disabled']) ? $newEntry['disabled'] : true + ); + // Update additional fields that are still empty after addImage call + $this->processor->updateImage( + $product, + $imageFileUri, + [ + 'label' => $newEntry['label'], + 'position' => $newEntry['position'], + 'disabled' => $newEntry['disabled'], + 'media_type' => $newEntry['media_type'], + ] + ); + } + + /** + * Ascertain image roles, if they are not set against the gallery entries. + * + * @param ProductInterface $product + * @param array $images + * @return array + */ + private function determineImageRoles(ProductInterface $product, array $images) : array + { + $imagesWithRoles = []; + foreach ($images as $image) { + if (!isset($image['types'])) { + $image['types'] = []; + if (isset($image['file'])) { + foreach (array_keys($product->getMediaAttributes()) as $attribute) { + if ($image['file'] == $product->getData($attribute)) { + $image['types'][] = $attribute; + } + } + } + } + $imagesWithRoles[] = $image; + } + + return $imagesWithRoles; + } + + /** + * Convert entries into product media gallery data and set to product. + * + * @param ProductInterface $product + * @param array $newEntries + * @param array $entriesById + * @throws InputException + * @throws LocalizedException + * @throws StateException + */ + private function processEntries(ProductInterface $product, array $newEntries, array $entriesById): void + { + foreach ($newEntries as $newEntry) { + if (!isset($newEntry['content'])) { + throw new InputException(__('The image content is invalid. Verify the content and try again.')); + } + /** @var ImageContentInterface $contentDataObject */ + $contentDataObject = $this->contentFactory->create() + ->setName($newEntry['content']['data'][ImageContentInterface::NAME]) + ->setBase64EncodedData($newEntry['content']['data'][ImageContentInterface::BASE64_ENCODED_DATA]) + ->setType($newEntry['content']['data'][ImageContentInterface::TYPE]); + $newEntry['content'] = $contentDataObject; + $this->processNewMediaGalleryEntry($product, $newEntry); + + $finalGallery = $product->getData('media_gallery'); + $newEntryId = key(array_diff_key($product->getData('media_gallery')['images'], $entriesById)); + $newEntry = array_replace_recursive($newEntry, $finalGallery['images'][$newEntryId]); + $entriesById[$newEntryId] = $newEntry; + $finalGallery['images'][$newEntryId] = $newEntry; + $product->setData('media_gallery', $finalGallery); + } + } + + /** + * Set media attribute values. + * + * @param ProductInterface $product + * @param array $images + */ + private function processMediaAttributes(ProductInterface $product, array $images): void + { + foreach ($images as $image) { + if (!isset($image['removed']) && !empty($image['types'])) { + $this->processor->setMediaAttribute($product, $image['types'], $image['file']); + } + } + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php index 6d3b4713b830d..cb92cc6c2d523 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -9,30 +8,41 @@ namespace Magento\Catalog\Test\Unit\Model; use Magento\Catalog\Api\Data\ProductExtensionInterface; +use Magento\Catalog\Api\Data\ProductSearchResultsInterface; use Magento\Catalog\Api\Data\ProductSearchResultsInterfaceFactory; use Magento\Catalog\Api\ProductAttributeRepositoryInterface; use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Gallery\MimeTypeExtensionMap; +use Magento\Catalog\Model\Product\Gallery\Processor; use Magento\Catalog\Model\Product\LinkTypeProvider; +use Magento\Catalog\Model\Product\Media\Config; +use Magento\Catalog\Model\Product\Option; +use Magento\Catalog\Model\Product\Option\Value; use Magento\Catalog\Model\ProductFactory; +use Magento\Catalog\Model\ProductLink\Link; use Magento\Catalog\Model\ProductRepository; +use Magento\Catalog\Model\ResourceModel\Product\Collection; use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; +use Magento\Framework\Api\Data\ImageContentInterface; use Magento\Framework\Api\Data\ImageContentInterfaceFactory; use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\Api\ImageContent; use Magento\Framework\Api\ImageContentValidator; use Magento\Framework\Api\ImageContentValidatorInterface; use Magento\Framework\Api\ImageProcessorInterface; -use Magento\Framework\Api\Data\ImageContentInterface; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\DB\Adapter\ConnectionException; use Magento\Framework\Filesystem; use Magento\Framework\Serialize\Serializer\Json; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Store\Api\Data\StoreInterface; +use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; +use PHPUnit\Framework\TestCase; use PHPUnit_Framework_MockObject_MockObject as MockObject; /** @@ -42,12 +52,12 @@ * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ -class ProductRepositoryTest extends \PHPUnit\Framework\TestCase +class ProductRepositoryTest extends TestCase { /** * @var Product|MockObject */ - protected $product; + private $product; /** * @var Product|MockObject @@ -153,12 +163,12 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase private $storeManager; /** - * @var \Magento\Catalog\Model\Product\Gallery\Processor|\PHPUnit_Framework_MockObject_MockObject + * @var Processor|MockObject */ - private $mediaGalleryProcessor; + private $processor; /** - * @var CollectionProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CollectionProcessorInterface|MockObject */ private $collectionProcessor; @@ -168,7 +178,7 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase private $productExtension; /** - * @var Json|\PHPUnit_Framework_MockObject_MockObject + * @var Json|MockObject */ private $serializerMock; @@ -185,12 +195,12 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase protected function setUp() { $this->productFactory = $this->createPartialMock( - \Magento\Catalog\Model\ProductFactory::class, + ProductFactory::class, ['create', 'setData'] ); $this->product = $this->createPartialMock( - \Magento\Catalog\Model\Product::class, + Product::class, [ 'getId', 'getSku', @@ -206,7 +216,7 @@ protected function setUp() ); $this->initializedProduct = $this->createPartialMock( - \Magento\Catalog\Model\Product::class, + Product::class, [ 'getWebsiteIds', 'setProductOptions', @@ -234,7 +244,7 @@ protected function setUp() $this->searchCriteriaBuilder = $this->createMock(SearchCriteriaBuilder::class); $this->metadataService = $this->createMock(ProductAttributeRepositoryInterface::class); $this->searchResultsFactory = $this->createPartialMock( - \Magento\Catalog\Api\Data\ProductSearchResultsInterfaceFactory::class, + ProductSearchResultsInterfaceFactory::class, ['create'] ); $this->resourceModel = $this->createMock(\Magento\Catalog\Model\ResourceModel\Product::class); @@ -282,10 +292,10 @@ protected function setUp() ->setMethods([]) ->getMockForAbstractClass(); $storeMock->expects($this->any())->method('getWebsiteId')->willReturn('1'); - $storeMock->expects($this->any())->method('getCode')->willReturn(\Magento\Store\Model\Store::ADMIN_CODE); + $storeMock->expects($this->any())->method('getCode')->willReturn(Store::ADMIN_CODE); $this->storeManager->expects($this->any())->method('getStore')->willReturn($storeMock); - $this->mediaGalleryProcessor = $this->createMock(\Magento\Catalog\Model\Product\Gallery\Processor::class); + $this->processor = $this->createMock(Processor::class); $this->collectionProcessor = $this->getMockBuilder(CollectionProcessorInterface::class) ->getMock(); @@ -301,6 +311,14 @@ function ($value) { ) ); + $mediaProcessor = $this->objectManager->getObject( + ProductRepository\MediaGalleryProcessor::class, + [ + 'processor' => $this->processor, + 'contentFactory' => $this->contentFactory, + 'imageProcessor' => $this->imageProcessor, + ] + ); $this->model = $this->objectManager->getObject( ProductRepository::class, [ @@ -315,17 +333,16 @@ function ($value) { 'extensibleDataObjectConverter' => $this->extensibleDataObjectConverter, 'contentValidator' => $this->contentValidator, 'fileSystem' => $this->fileSystem, - 'contentFactory' => $this->contentFactory, 'mimeTypeExtensionMap' => $this->mimeTypeExtensionMap, 'linkTypeProvider' => $this->linkTypeProvider, - 'imageProcessor' => $this->imageProcessor, 'storeManager' => $this->storeManager, - 'mediaGalleryProcessor' => $this->mediaGalleryProcessor, + 'mediaGalleryProcessor' => $this->processor, 'collectionProcessor' => $this->collectionProcessor, 'serializer' => $this->serializerMock, 'cacheLimit' => $this->cacheLimit ] ); + $this->objectManager->setBackwardCompatibleProperty($this->model, 'mediaProcessor', $mediaProcessor); } /** @@ -508,7 +525,7 @@ private function getProductMocksForReducedCache($productsCount) $productMocks = []; for ($i = 1; $i <= $productsCount; $i++) { - $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + $productMock = $this->getMockBuilder(Product::class) ->disableOriginalConstructor() ->setMethods([ 'getId', @@ -761,8 +778,8 @@ public function testDeleteById() public function testGetList() { - $searchCriteriaMock = $this->createMock(\Magento\Framework\Api\SearchCriteriaInterface::class); - $collectionMock = $this->createMock(\Magento\Catalog\Model\ResourceModel\Product\Collection::class); + $searchCriteriaMock = $this->createMock(SearchCriteriaInterface::class); + $collectionMock = $this->createMock(Collection::class); $this->collectionFactory->expects($this->once())->method('create')->willReturn($collectionMock); $this->product->method('getSku')->willReturn('simple'); $collectionMock->expects($this->once())->method('addAttributeToSelect')->with('*'); @@ -777,7 +794,7 @@ public function testGetList() $collectionMock->expects($this->once())->method('addCategoryIds'); $collectionMock->expects($this->atLeastOnce())->method('getItems')->willReturn([$this->product]); $collectionMock->expects($this->once())->method('getSize')->willReturn(128); - $searchResultsMock = $this->createMock(\Magento\Catalog\Api\Data\ProductSearchResultsInterface::class); + $searchResultsMock = $this->createMock(ProductSearchResultsInterface::class); $searchResultsMock->expects($this->once())->method('setSearchCriteria')->with($searchCriteriaMock); $searchResultsMock->expects($this->once())->method('setItems')->with([$this->product]); $this->searchResultsFactory->expects($this->once())->method('create')->willReturn($searchResultsMock); @@ -911,8 +928,8 @@ public function saveExistingWithOptionsDataProvider() ], ]; - /** @var \Magento\Catalog\Model\Product\Option|\PHPUnit_Framework_MockObject_MockObject $existingOption1 */ - $existingOption1 = $this->getMockBuilder(\Magento\Catalog\Model\Product\Option::class) + /** @var Option|MockObject $existingOption1 */ + $existingOption1 = $this->getMockBuilder(Option::class) ->disableOriginalConstructor() ->setMethods(null) ->getMock(); @@ -922,8 +939,8 @@ public function saveExistingWithOptionsDataProvider() "type" => "drop_down", ] ); - /** @var \Magento\Catalog\Model\Product\Option\Value $existingOptionValue1 */ - $existingOptionValue1 = $this->getMockBuilder(\Magento\Catalog\Model\Product\Option\Value::class) + /** @var Value $existingOptionValue1 */ + $existingOptionValue1 = $this->getMockBuilder(Value::class) ->disableOriginalConstructor() ->setMethods(null) ->getMock(); @@ -934,7 +951,7 @@ public function saveExistingWithOptionsDataProvider() "price" => 5, ] ); - $existingOptionValue2 = $this->getMockBuilder(\Magento\Catalog\Model\Product\Option\Value::class) + $existingOptionValue2 = $this->getMockBuilder(Value::class) ->disableOriginalConstructor() ->setMethods(null) ->getMock(); @@ -951,7 +968,7 @@ public function saveExistingWithOptionsDataProvider() "9" => $existingOptionValue2, ] ); - $existingOption2 = $this->getMockBuilder(\Magento\Catalog\Model\Product\Option::class) + $existingOption2 = $this->getMockBuilder(Option::class) ->disableOriginalConstructor() ->setMethods(null) ->getMock(); @@ -1016,8 +1033,8 @@ public function saveExistingWithOptionsDataProvider() * @param array $existingLinks * @param array $expectedData * @dataProvider saveWithLinksDataProvider - * @throws \Magento\Framework\Exception\CouldNotSaveException - * @throws \Magento\Framework\Exception\InputException + * @throws CouldNotSaveException + * @throws InputException */ public function testSaveWithLinks(array $newLinks, array $existingLinks, array $expectedData) { @@ -1045,7 +1062,7 @@ public function testSaveWithLinks(array $newLinks, array $existingLinks, array $ ->expects($this->any())->method('getProductsIdsBySkus') ->willReturn([$newLinks['linked_product_sku'] => $newLinks['linked_product_sku']]); - $inputLink = $this->objectManager->getObject(\Magento\Catalog\Model\ProductLink\Link::class); + $inputLink = $this->objectManager->getObject(Link::class); $inputLink->setProductSku($newLinks['product_sku']); $inputLink->setLinkType($newLinks['link_type']); $inputLink->setLinkedProductSku($newLinks['linked_product_sku']); @@ -1089,7 +1106,7 @@ public function testSaveWithLinks(array $newLinks, array $existingLinks, array $ $outputLinks = []; if (!empty($expectedData)) { foreach ($expectedData as $link) { - $outputLink = $this->objectManager->getObject(\Magento\Catalog\Model\ProductLink\Link::class); + $outputLink = $this->objectManager->getObject(Link::class); $outputLink->setProductSku($link['product_sku']); $outputLink->setLinkType($link['link_type']); $outputLink->setLinkedProductSku($link['linked_product_sku']); @@ -1243,10 +1260,10 @@ public function testSaveExistingWithNewMediaGalleryEntries() $mediaTmpPath = '/tmp'; $absolutePath = '/a/b/filename.jpg'; - $this->mediaGalleryProcessor->expects($this->once())->method('clearMediaAttribute') + $this->processor->expects($this->once())->method('clearMediaAttribute') ->with($this->initializedProduct, ['image', 'small_image']); - $mediaConfigMock = $this->getMockBuilder(\Magento\Catalog\Model\Product\Media\Config::class) + $mediaConfigMock = $this->getMockBuilder(Config::class) ->disableOriginalConstructor() ->getMock(); $mediaConfigMock->expects($this->once()) @@ -1258,7 +1275,7 @@ public function testSaveExistingWithNewMediaGalleryEntries() ->willReturn($mediaConfigMock); //verify new entries - $contentDataObject = $this->getMockBuilder(\Magento\Framework\Api\ImageContent::class) + $contentDataObject = $this->getMockBuilder(ImageContent::class) ->disableOriginalConstructor() ->setMethods(null) ->getMock(); @@ -1271,10 +1288,10 @@ public function testSaveExistingWithNewMediaGalleryEntries() ->willReturn($absolutePath); $imageFileUri = "imageFileUri"; - $this->mediaGalleryProcessor->expects($this->once())->method('addImage') + $this->processor->expects($this->once())->method('addImage') ->with($this->initializedProduct, $mediaTmpPath . $absolutePath, ['image', 'small_image'], true, false) ->willReturn($imageFileUri); - $this->mediaGalleryProcessor->expects($this->once())->method('updateImage') + $this->processor->expects($this->once())->method('updateImage') ->with( $this->initializedProduct, $imageFileUri, @@ -1394,9 +1411,9 @@ public function testSaveExistingWithMediaGalleryEntries() ->method('getMediaAttributes') ->willReturn(["image" => "filename1", "small_image" => "filename2"]); - $this->mediaGalleryProcessor->expects($this->once())->method('clearMediaAttribute') + $this->processor->expects($this->once())->method('clearMediaAttribute') ->with($this->initializedProduct, ['image', 'small_image']); - $this->mediaGalleryProcessor->expects($this->once()) + $this->processor->expects($this->once()) ->method('setMediaAttribute') ->with($this->initializedProduct, ['image', 'small_image'], 'filename1'); $this->initializedProduct->expects($this->atLeastOnce()) From 2f2cfc82c54c22b2b28f9b45b8ef05d6bbc9ece6 Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Thu, 25 Apr 2019 12:22:58 +0300 Subject: [PATCH 509/585] MC-5831: Apply cross border taxes, product with category --- .../tests/app/Magento/Checkout/Test/Block/Cart/Totals.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php index f632cdc3d7464..1d3950091d064 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php @@ -117,6 +117,7 @@ public function getGrandTotal() */ public function getGrandTotalIncludingTax() { + $this->waitForGrandTotal(); $priceElement = $this->_rootElement->find($this->grandTotalInclTax, Locator::SELECTOR_CSS); return $priceElement->isVisible() ? $this->escapeCurrency($priceElement->getText()) : null; } From d0ca45c81f61ea56e7320f5e3c5f3237438092d2 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Thu, 25 Apr 2019 12:31:57 +0300 Subject: [PATCH 510/585] MC-5279: Create product without tax class and tier price --- .../Product/CreateSimpleProductEntityPartOneTest.xml | 4 ++++ .../Product/CreateSimpleProductEntityPartTwoTest.xml | 10 ++++++++++ .../TestCase/Product/CreateSimpleProductEntityTest.php | 1 - .../TestCase/Product/CreateSimpleProductEntityTest.xml | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartOneTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartOneTest.xml index 4a3d80b0b6090..f97735304baa5 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartOneTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartOneTest.xml @@ -25,6 +25,8 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductInventoryMaxAllowedQty" /> </variation> <variation name="CreateSimpleProductEntityTestVariation13"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> + <data name="issue" xsi:type="string">MAGETWO-48850: Filtering Category Products using scope selector</data> <data name="description" xsi:type="string">Create simple product and check search by sku</data> <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> @@ -42,6 +44,8 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductPage" /> </variation> <variation name="CreateSimpleProductEntityTestVariation14"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> + <data name="issue" xsi:type="string">MC-6220: Add products to wishlist from Category page with multiple wishlist enabled</data> <data name="description" xsi:type="string">Create simple product and check visibility in category</data> <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartTwoTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartTwoTest.xml index a40c715bb3ac3..d6b75e5c3a6e4 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartTwoTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartTwoTest.xml @@ -8,6 +8,8 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Catalog\Test\TestCase\Product\CreateSimpleProductEntityPartTwoTest" summary="Create Simple Product" ticketId="MAGETWO-23414"> <variation name="CreateSimpleProductEntityTestVariation23" summary="Create Simple Product with Creating New Category (Required Fields Only)" ticketId="MAGETWO-27293"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> + <data name="issue" xsi:type="string">MC-234: Admin should be able to create category from the product page</data> <data name="product/data/category_ids/new_category" xsi:type="string">yes</data> <data name="product/data/category_ids/dataset" xsi:type="string">default_subcategory_without_url_key</data> <data name="product/data/website_ids/0/dataset" xsi:type="string">default</data> @@ -23,6 +25,8 @@ <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteProductInGrid" /> </variation> <variation name="CreateSimpleProductEntityTestVariation24" summary="Create Simple Product and Assigning It to Category" ticketId="MAGETWO-12514"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> + <data name="issue" xsi:type="string">MAGETWO-23414: Create Simple Product</data> <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data> @@ -79,6 +83,8 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> </variation> <variation name="CreateSimpleProductEntityTestVariation28" summary="Create product with tier price for not logged in customer"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> + <data name="issue" xsi:type="string">MAGETWO-68921: Apply Tier Price to a product</data> <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data> @@ -118,6 +124,8 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductInCart" /> </variation> <variation name="CreateSimpleProductEntityWithTierPriceTestVariation1" summary="Create Simple Product with fixed tier price."> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> + <data name="issue" xsi:type="string">MAGETWO-68921: Apply Tier Price to a product</data> <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data> @@ -127,6 +135,8 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductTierPriceInCart" /> </variation> <variation name="CreateSimpleProductEntityWithTierPriceTestVariation2" summary="Create Simple Product with percentage tier price."> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> + <data name="issue" xsi:type="string">MAGETWO-68921: Apply Tier Price to a product</data> <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.php index 7a677dbea983c..4d866f716d70c 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.php @@ -79,7 +79,6 @@ public function testCreate( $flushCache = false, $configData = null ) { - $this->markTestIncomplete('https://github.com/magento-engcom/msi/issues/1620'); $this->configData = $configData; $this->flushCache = $flushCache; diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml index 8732157e5c657..2d4a607d3c93f 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml @@ -182,6 +182,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductPage" /> </variation> <variation name="CreateSimpleProductEntityTestVariation10" summary="Create in stock product and check threshold" ticketId="MAGETWO-43345"> + <data name="issue" xsi:type="string">https://github.com/magento-engcom/msi/issues/1620</data> <data name="configData" xsi:type="string">inventory_threshold_5</data> <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> From 2faf142b4b7faa1827999911b0fe4c66f9a3f72f Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Thu, 25 Apr 2019 14:32:59 +0300 Subject: [PATCH 511/585] MC-5279: Create product without tax class and tier price --- .../Test/TestCase/Product/CreateSimpleProductEntityTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml index 2d4a607d3c93f..840dc0b0812b2 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml @@ -183,6 +183,7 @@ </variation> <variation name="CreateSimpleProductEntityTestVariation10" summary="Create in stock product and check threshold" ticketId="MAGETWO-43345"> <data name="issue" xsi:type="string">https://github.com/magento-engcom/msi/issues/1620</data> + <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="configData" xsi:type="string">inventory_threshold_5</data> <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> From 767abdc609fce4e309d80662508ec5c3c205bba7 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Thu, 25 Apr 2019 09:57:20 -0500 Subject: [PATCH 512/585] magento-engcom/magento2ce#2792: Suppressed code style violation --- .../Magento/Catalog/Model/ResourceModel/Product/Collection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index cbcc7d513d36b..281f827a55c79 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -1981,6 +1981,7 @@ protected function _productLimitationPrice($joinLeft = false) } // Set additional field filters foreach ($this->_priceDataFieldFilters as $filterData) { + // phpcs:disable Magento2.Functions.DiscouragedFunction $select->where(call_user_func_array('sprintf', $filterData)); } } else { From 91bdb745e71d96ca092d48877ba0a11d708984e3 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Thu, 25 Apr 2019 09:59:37 -0500 Subject: [PATCH 513/585] MC-16005: Deferred loading / parsing of JS p2 --- .../Magento/Backend/etc/adminhtml/system.xml | 4 ++ .../Controller/Result/JsFooterPlugin.php | 64 +++++++++++++------ app/code/Magento/Theme/etc/config.xml | 5 ++ app/code/Magento/Theme/etc/system.xml | 19 ++++++ 4 files changed, 73 insertions(+), 19 deletions(-) create mode 100644 app/code/Magento/Theme/etc/system.xml diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml index 98b8e702b1c53..f278d2d582598 100644 --- a/app/code/Magento/Backend/etc/adminhtml/system.xml +++ b/app/code/Magento/Backend/etc/adminhtml/system.xml @@ -182,6 +182,10 @@ <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> <comment>Minification is not applied in developer mode.</comment> </field> + <field id="move_inline_to_bottom" translate="label" type="select" sortOrder="25" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <label>Move JS code to the bottom of the page</label> + <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> + </field> </group> <group id="css" translate="label" type="text" sortOrder="110" showInDefault="1" showInWebsite="1" showInStore="1"> <label>CSS Settings</label> diff --git a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php index a81f29280af96..bf2a6c28709ac 100644 --- a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php @@ -5,34 +5,60 @@ */ namespace Magento\Theme\Controller\Result; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Framework\App\Response\Http; + /** - * Plugin for putting messages to cookies + * Plugin for putting all js to footer. */ class JsFooterPlugin { + const XML_PATH_DEV_MOVE_JS_TO_BOTTOM = 'dev/js/move_inline_to_bottom'; + + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * @param ScopeConfigInterface $scopeConfig + */ + public function __construct(ScopeConfigInterface $scopeConfig) + { + $this->scopeConfig = $scopeConfig; + } + /** - * Put all javascript to footer before sending the response + * Put all javascript to footer before sending the response. * - * @param \Magento\Framework\App\Response\Http $subject + * @param Http $subject * @return void */ - public function beforeSendResponse(\Magento\Framework\App\Response\Http $subject) + public function beforeSendResponse(Http $subject) { - $content = $subject->getContent(); - $script = []; - if (strpos($content, '</body') !== false) { - $pattern = '#<script[^>]*+(?<!text/x-magento-template.)>.*?</script>#is'; - $content = preg_replace_callback( - $pattern, - function ($matchPart) use (&$script) { - $script[] = $matchPart[0]; - return ''; - }, - $content - ); - $subject->setContent( - str_replace('</body', implode("\n", $script) . "\n</body", $content) - ); + if ( + $this->scopeConfig->isSetFlag( + self::XML_PATH_DEV_MOVE_JS_TO_BOTTOM, + ScopeInterface::SCOPE_STORE + ) + ) { + $content = $subject->getContent(); + $script = []; + if (strpos($content, '</body') !== false) { + $pattern = '#<script[^>]*+(?<!text/x-magento-template.)>.*?</script>#is'; + $content = preg_replace_callback( + $pattern, + function ($matchPart) use (&$script) { + $script[] = $matchPart[0]; + return ''; + }, + $content + ); + $subject->setContent( + str_replace('</body', implode("\n", $script) . "\n</body", $content) + ); + } } } } diff --git a/app/code/Magento/Theme/etc/config.xml b/app/code/Magento/Theme/etc/config.xml index b44691c0df963..37841789c0e10 100644 --- a/app/code/Magento/Theme/etc/config.xml +++ b/app/code/Magento/Theme/etc/config.xml @@ -66,6 +66,11 @@ Disallow: /*SID= <static> <sign>1</sign> </static> + <dev> + <js> + <move_inline_to_bottom>0</move_inline_to_bottom> + </js> + </dev> </dev> </default> </config> diff --git a/app/code/Magento/Theme/etc/system.xml b/app/code/Magento/Theme/etc/system.xml new file mode 100644 index 0000000000000..4abc87e845122 --- /dev/null +++ b/app/code/Magento/Theme/etc/system.xml @@ -0,0 +1,19 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> + <system> + <section id="dev" translate="label" type="text" sortOrder="920" showInDefault="1" showInWebsite="1" showInStore="1"> + <group id="js" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1"> + <field id="move_inline_to_bottom" translate="label" type="select" sortOrder="25" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <label>Move JS code to the bottom of the page</label> + <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> + </field> + </group> + </section> + </system> +</config> From 62abb3c6bbb894e13403da4145336a977170b44c Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Thu, 25 Apr 2019 10:28:24 -0500 Subject: [PATCH 514/585] MC-13613: Product mass update --- .../Framework/MessageQueue/PoisonPill/PoisonPillCompare.php | 5 ++--- .../MessageQueue/PoisonPill/PoisonPillCompareInterface.php | 3 +-- .../Framework/MessageQueue/PoisonPill/PoisonPillPut.php | 4 +--- .../Framework/MessageQueue/PoisonPill/PoisonPillRead.php | 2 +- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompare.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompare.php index 404cf96964f6e..0b85fbb61472a 100644 --- a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompare.php +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompare.php @@ -8,13 +8,12 @@ namespace Magento\Framework\MessageQueue\PoisonPill; /** - * Interface describes how to describes how to compare poison pill with latest in DB. - * + * Describes how to compare given version of poison pill with latest in DB. */ class PoisonPillCompare implements PoisonPillCompareInterface { /** - * Dumb implementation + * Stub implementation * * @todo Will use cache storage after @MC-15997 * diff --git a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompareInterface.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompareInterface.php index e26b21d5a5387..acf78f5014ef6 100644 --- a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompareInterface.php +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillCompareInterface.php @@ -8,8 +8,7 @@ namespace Magento\Framework\MessageQueue\PoisonPill; /** - * Interface describes how to describes how to compare poison pill with latest in DB. - * + * Interface describes how to compare given version of poison pill with latest in DB. */ interface PoisonPillCompareInterface { diff --git a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPut.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPut.php index 08c67567ee5d3..7e6828633aea9 100644 --- a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPut.php +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillPut.php @@ -7,8 +7,6 @@ namespace Magento\Framework\MessageQueue\PoisonPill; -use Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface; - /** * Command interface describes how to create new version on poison pill. */ @@ -22,7 +20,7 @@ class PoisonPillPut implements PoisonPillPutInterface private $firstVersion = ''; /** - * Dumb framework implementation. + * Stub implementation. * * @todo Will use cache storage after @MC-15997 * diff --git a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php index b3013cb8c61c9..68048996ed0f9 100644 --- a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php @@ -13,7 +13,7 @@ class PoisonPillRead implements PoisonPillReadInterface { /** - * Returns get latest version of poison pill. + * Stub implementation. * * @todo Will use cache storage after @MC-15997 * From 406bcfd39c864fbe6e29931f54b4cc7b1181019b Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Thu, 25 Apr 2019 11:17:29 -0500 Subject: [PATCH 515/585] MAGETWO-99402: [MFTF] One Page Checkout with Addresses Search - Custom customer address attribute --- .../AdminEditCustomerAddressesFromActionGroup.xml | 9 +++++++++ .../Customer/Test/Mftf/Data/CustomerData.xml | 14 ++++++++++++++ .../Section/AdminEditCustomerAddressesSection.xml | 1 + 3 files changed, 24 insertions(+) diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml index 594337c1a6922..9c38f23739b10 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml @@ -39,4 +39,13 @@ <click selector="{{AdminEditCustomerAddressesSection.defaultBillingAddressButton}}" stepKey="setDefaultBilling" before="setDefaultShipping"/> <click selector="{{AdminEditCustomerAddressesSection.defaultShippingAddressButton}}" stepKey="setDefaultShipping" before="fillPrefixName"/> </actionGroup> + <actionGroup name="SelectDropdownCustomerAddressAttributeValueActionGroup"> + <arguments> + <argument name="customerAddressAttribute"/> + <argument name="optionValue" type="string"/> + </arguments> + <selectOption selector="{{AdminEditCustomerAddressesSection.dropDownAttribute(customerAddressAttribute.code)}}" userInput="{{optionValue}}" stepKey="selectOptionValue"/> + <click selector="{{AdminEditCustomerAddressesSection.save}}" stepKey="saveAddress"/> + <waitForPageLoad stepKey="waitForAddressSaved"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index f561e413a01f1..f8943dcfe8369 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -216,4 +216,18 @@ <data key="store_id">0</data> <data key="website_id">0</data> </entity> + <entity name="Simple_US_Customer_Two_Addresses" type="customer"> + <data key="group_id">0</data> + <data key="default_billing">true</data> + <data key="default_shipping">true</data> + <data key="email" unique="prefix">John.Doe@example.com</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="fullname">John Doe</data> + <data key="password">pwdTest123!</data> + <data key="store_id">0</data> + <data key="website_id">0</data> + <requiredEntity type="address">US_Address_TX</requiredEntity> + <requiredEntity type="address">US_Address_NY_Not_Default_Address</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerAddressesSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerAddressesSection.xml index ffddc6292ef5d..4d66b40ee660b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerAddressesSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerAddressesSection.xml @@ -25,6 +25,7 @@ <element name="city" type="text" selector="//*[@class='modal-component']//input[@name='city']" /> <element name="country" type="select" selector="//*[@class='modal-component']//select[@name='country_id']" /> <element name="state" type="select" selector="//*[@class='modal-component']//select[@name='region_id']" /> + <element name="dropDownAttribute" type="select" selector="//select[@name='{{var1}}']" parameterized="true"/> <element name="zipCode" type="text" selector="//*[@class='modal-component']//input[@name='postcode']" /> <element name="phone" type="text" selector="//*[@class='modal-component']//input[@name='telephone']" /> <element name="vat" type="text" selector="input[name='vat_id']" /> From 694dc09c90fd90a2b484e834c4949f6f44af41f3 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@adobe.com> Date: Thu, 25 Apr 2019 11:33:14 -0500 Subject: [PATCH 516/585] magento/magento2#22074: Added strict type to the introduced method --- app/code/Magento/Catalog/Controller/Category/View.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Controller/Category/View.php b/app/code/Magento/Catalog/Controller/Category/View.php index 5129692146ff6..da3d99a8d2745 100644 --- a/app/code/Magento/Catalog/Controller/Category/View.php +++ b/app/code/Magento/Catalog/Controller/Category/View.php @@ -230,7 +230,7 @@ public function execute() * @param Category $category * @return string */ - private function getPageType(Category $category) + private function getPageType(Category $category) : string { $hasChildren = $category->hasChildren(); if ($category->getIsAnchor()) { From 23e9dc45b1f6cc48b4bf42ad6a1f3980dddd083b Mon Sep 17 00:00:00 2001 From: Maksym Aposov <maposov@magento.com> Date: Thu, 25 Apr 2019 12:06:12 -0500 Subject: [PATCH 517/585] MC-16040: Fix data cleanup after test --- ...oriesAfterChangingUrlKeyForStoreViewAndMovingCategoryTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategoryTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategoryTest.xml index ee3682c8ad4d7..52dce4d67f698 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategoryTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategoryTest.xml @@ -40,6 +40,7 @@ <deleteData createDataKey="createSecondCategory" stepKey="deleteSecondCategory"/> <deleteData createDataKey="createFirstSimpleProduct" stepKey="deleteFirstSimpleProduct"/> <deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"/> <actionGroup ref="logout" stepKey="logout"/> </after> From a9c4e569cc2fe5544a99f9ad8d95d7d89cbcbc12 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Thu, 25 Apr 2019 12:12:25 -0500 Subject: [PATCH 518/585] MC-16005: Deferred loading / parsing of JS p2 --- .../Theme/Controller/Result/JsFooterPlugin.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php index bf2a6c28709ac..ba2df6d66430e 100644 --- a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php @@ -37,15 +37,15 @@ public function __construct(ScopeConfigInterface $scopeConfig) */ public function beforeSendResponse(Http $subject) { - if ( - $this->scopeConfig->isSetFlag( - self::XML_PATH_DEV_MOVE_JS_TO_BOTTOM, - ScopeInterface::SCOPE_STORE - ) - ) { - $content = $subject->getContent(); - $script = []; - if (strpos($content, '</body') !== false) { + $content = $subject->getContent(); + $script = []; + if (strpos($content, '</body') !== false) { + if ( + $this->scopeConfig->isSetFlag( + self::XML_PATH_DEV_MOVE_JS_TO_BOTTOM, + ScopeInterface::SCOPE_STORE + ) + ) { $pattern = '#<script[^>]*+(?<!text/x-magento-template.)>.*?</script>#is'; $content = preg_replace_callback( $pattern, From f96f890338dea8b1ca0eca02800244874a7de29b Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Thu, 25 Apr 2019 13:33:11 -0500 Subject: [PATCH 519/585] MC-13613 Product mass update --- .../MessageQueue/Test/Unit/ConsumerTest.php | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/MessageQueue/Test/Unit/ConsumerTest.php b/lib/internal/Magento/Framework/MessageQueue/Test/Unit/ConsumerTest.php index 5eb7cd587aaa2..7a3eb3b16baca 100644 --- a/lib/internal/Magento/Framework/MessageQueue/Test/Unit/ConsumerTest.php +++ b/lib/internal/Magento/Framework/MessageQueue/Test/Unit/ConsumerTest.php @@ -6,6 +6,8 @@ namespace Magento\Framework\MessageQueue\Test\Unit; +use Magento\Framework\MessageQueue\PoisonPill\PoisonPillCompareInterface; +use Magento\Framework\MessageQueue\PoisonPill\PoisonPillReadInterface; use Magento\Framework\Phrase; /** @@ -65,6 +67,16 @@ class ConsumerTest extends \PHPUnit\Framework\TestCase */ private $consumer; + /** + * @var PoisonPillReadInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $poisonPillRead; + + /** + * @var PoisonPillCompareInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $poisonPillCompare; + /** * Set up. * @@ -85,8 +97,15 @@ protected function setUp() ->disableOriginalConstructor()->getMock(); $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->poisonPillCompare = $this->getMockBuilder(PoisonPillCompareInterface::class) + ->disableOriginalConstructor()->getMock(); + $this->poisonPillRead = $this->getMockBuilder(PoisonPillReadInterface::class) + ->disableOriginalConstructor()->getMock(); //Hard dependency used because CallbackInvoker invokes closure logic defined inside of Customer class. - $this->callbackInvoker = new \Magento\Framework\MessageQueue\CallbackInvoker(); + $this->callbackInvoker = new \Magento\Framework\MessageQueue\CallbackInvoker( + $this->poisonPillRead, + $this->poisonPillCompare + ); $this->consumer = $objectManager->getObject( \Magento\Framework\MessageQueue\Consumer::class, [ @@ -134,7 +153,8 @@ public function testProcessWithNotFoundException() $numberOfMessages = 1; $consumerName = 'consumer.name'; $exceptionPhrase = new Phrase('Exception successfully thrown'); - + $this->poisonPillRead->expects($this->atLeastOnce())->method('getLatestVersion')->willReturn('version-1'); + $this->poisonPillCompare->expects($this->atLeastOnce())->method('isLatestVersion')->willReturn(true); $queue = $this->getMockBuilder(\Magento\Framework\MessageQueue\QueueInterface::class) ->disableOriginalConstructor()->getMock(); $this->configuration->expects($this->once())->method('getQueue')->willReturn($queue); From 2d7d5f4e61c63c6fab302e329fe0cb4e9617acca Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Thu, 25 Apr 2019 15:04:02 -0500 Subject: [PATCH 520/585] MAGETWO-99418: Deliver critical PR for 2.3.2 --- app/code/Magento/Config/composer.json | 1 - .../Model/ResourceModel/PoisonPill.php | 14 -------------- app/code/Magento/Store/composer.json | 1 - .../Theme/Controller/Result/JsFooterPlugin.php | 5 ++--- 4 files changed, 2 insertions(+), 19 deletions(-) diff --git a/app/code/Magento/Config/composer.json b/app/code/Magento/Config/composer.json index 3312fb630ccda..57c067d2cae27 100644 --- a/app/code/Magento/Config/composer.json +++ b/app/code/Magento/Config/composer.json @@ -7,7 +7,6 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/framework": "*", - "magento/module-message-queue": "*", "magento/module-backend": "*", "magento/module-cron": "*", "magento/module-deploy": "*", diff --git a/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php b/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php index e7dbc1af3f2b8..20687ca4cede2 100644 --- a/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php +++ b/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php @@ -9,7 +9,6 @@ use Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface; use Magento\Framework\MessageQueue\PoisonPill\PoisonPillReadInterface; -use Magento\Framework\Model\ResourceModel\Db\Context; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; /** @@ -22,19 +21,6 @@ class PoisonPill extends AbstractDb implements PoisonPillPutInterface, PoisonPil */ const QUEUE_POISON_PILL_TABLE = 'queue_poison_pill'; - /** - * PoisonPill constructor. - * - * @param Context $context - * @param string|null $connectionName - */ - public function __construct( - Context $context, - string $connectionName = null - ) { - parent::__construct($context, $connectionName); - } - /** * @inheritdoc */ diff --git a/app/code/Magento/Store/composer.json b/app/code/Magento/Store/composer.json index da408f105ccb6..ebaa32b95f48b 100644 --- a/app/code/Magento/Store/composer.json +++ b/app/code/Magento/Store/composer.json @@ -7,7 +7,6 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/framework": "*", - "magento/module-message-queue": "*", "magento/module-catalog": "*", "magento/module-config": "*", "magento/module-directory": "*", diff --git a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php index ba2df6d66430e..14043f950ae16 100644 --- a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php @@ -40,11 +40,10 @@ public function beforeSendResponse(Http $subject) $content = $subject->getContent(); $script = []; if (strpos($content, '</body') !== false) { - if ( - $this->scopeConfig->isSetFlag( + if ($this->scopeConfig->isSetFlag( self::XML_PATH_DEV_MOVE_JS_TO_BOTTOM, ScopeInterface::SCOPE_STORE - ) + ) ) { $pattern = '#<script[^>]*+(?<!text/x-magento-template.)>.*?</script>#is'; $content = preg_replace_callback( From 13111837518928df29ffe191e85bb3438e23e933 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 25 Apr 2019 16:19:28 -0500 Subject: [PATCH 521/585] Issue-230: adding varnish - fixing dispatch --- .../Resolver/Category/CategoriesIdentity.php | 2 +- .../Category/CategoryTreeIdentity.php | 2 +- .../Model/Resolver/Product/Identity.php | 2 +- .../Model/Resolver/Block/Identity.php | 2 +- .../Model/Resolver/Page/Identity.php | 2 +- .../Magento/GraphQl/Controller/GraphQl.php | 22 ++++++++++----- .../Controller/Plugin/GraphQl.php | 27 ++++++++----------- .../Magento/GraphQlCache/etc/graphql/di.xml | 1 + .../Controller/GraphQlControllerTest.php | 23 +++------------- .../Framework/App/PageCache/Kernel.php | 2 +- .../Query/Resolver/IdentityInterface.php | 2 +- .../MetaReader/CacheTagReader.php | 2 +- .../MetaReader/FieldMetaReader.php | 9 ++----- .../GraphQlReader/Reader/InputObjectType.php | 9 ++----- .../GraphQlReader/Reader/InterfaceType.php | 9 ++----- .../GraphQlReader/Reader/ObjectType.php | 9 ++----- 16 files changed, 47 insertions(+), 78 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php index d81f6db574a3d..aba2d7b198dbd 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php @@ -18,7 +18,7 @@ class CategoriesIdentity implements IdentityInterface * Get category IDs from resolved data * * @param array $resolvedData - * @return array + * @return string[] */ public function getIdentities(array $resolvedData): array { diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php index 8cc77b53c5aaa..e4970f08b3eb7 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php @@ -18,7 +18,7 @@ class CategoryTreeIdentity implements IdentityInterface * Get category ID from resolved data * * @param array $resolvedData - * @return array + * @return string[] */ public function getIdentities(array $resolvedData): array { diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php index bbb0057befc7a..198b1c112dca2 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php @@ -18,7 +18,7 @@ class Identity implements IdentityInterface * Get product ids for cache tag * * @param array $resolvedData - * @return array + * @return string[] */ public function getIdentities(array $resolvedData): array { diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php index 9431d20692187..a40d23968c3c6 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php @@ -19,7 +19,7 @@ class Identity implements IdentityInterface * Get block identities from resolved data * * @param array $resolvedData - * @return array + * @return string[] */ public function getIdentities(array $resolvedData): array { diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php index 5a11587f4b1e5..abc306451e309 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php @@ -19,7 +19,7 @@ class Identity implements IdentityInterface * Get page ID from resolved data * * @param array $resolvedData - * @return array + * @return string[] */ public function getIdentities(array $resolvedData): array { diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index f31492f8389f6..4271ac3f6c585 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -15,8 +15,8 @@ use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; use Magento\Framework\GraphQl\Schema\SchemaGeneratorInterface; use Magento\Framework\Serialize\SerializerInterface; -use Magento\Framework\Controller\ResultInterface; use Magento\Framework\Webapi\Response; +use Magento\Framework\App\Response\Http as HttpResponse; use Magento\Framework\GraphQl\Query\Fields as QueryFields; use Magento\Framework\Controller\Result\JsonFactory; use Magento\Framework\App\ObjectManager; @@ -30,7 +30,7 @@ class GraphQl implements FrontControllerInterface { /** - * @var Response + * @var \Magento\Framework\Webapi\Response * @deprecated */ private $response; @@ -75,6 +75,11 @@ class GraphQl implements FrontControllerInterface */ private $jsonFactory; + /** + * @var HttpResponse + */ + private $httpResponse; + /** * @param Response $response * @param SchemaGeneratorInterface $schemaGenerator @@ -85,6 +90,8 @@ class GraphQl implements FrontControllerInterface * @param HttpRequestProcessor $requestProcessor * @param QueryFields $queryFields * @param JsonFactory|null $jsonFactory + * @param HttpResponse|null $httpResponse + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( Response $response, @@ -95,7 +102,8 @@ public function __construct( ContextInterface $resolverContext, HttpRequestProcessor $requestProcessor, QueryFields $queryFields, - JsonFactory $jsonFactory = null + JsonFactory $jsonFactory = null, + HttpResponse $httpResponse = null ) { $this->response = $response; $this->schemaGenerator = $schemaGenerator; @@ -106,15 +114,16 @@ public function __construct( $this->requestProcessor = $requestProcessor; $this->queryFields = $queryFields; $this->jsonFactory = $jsonFactory ?:ObjectManager::getInstance()->get(JsonFactory::class); + $this->httpResponse = $httpResponse ?:ObjectManager::getInstance()->get(HttpResponse::class); } /** * Handle GraphQL request * * @param RequestInterface $request - * @return ResultInterface + * @return Response */ - public function dispatch(RequestInterface $request) + public function dispatch(RequestInterface $request) : HttpResponse { $statusCode = 200; $jsonResult = $this->jsonFactory->create(); @@ -145,7 +154,8 @@ public function dispatch(RequestInterface $request) $jsonResult->setHttpResponseCode($statusCode); $jsonResult->setData($result); - return $jsonResult; + $jsonResult->renderResult($this->httpResponse); + return $this->httpResponse; } /** diff --git a/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php b/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php index 588aa851e880a..7c026e7d4136e 100644 --- a/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php +++ b/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php @@ -9,15 +9,15 @@ use Magento\Framework\App\FrontControllerInterface; use Magento\Framework\App\RequestInterface; -use Magento\Framework\App\ResponseInterface; use Magento\GraphQlCache\Model\CacheableQuery; use Magento\Framework\App\Response\Http as HttpResponse; use Magento\Framework\Controller\ResultInterface; use Magento\PageCache\Model\Config; use Magento\GraphQl\Controller\HttpRequestProcessor; +use Magento\Framework\App\Response\Http as ResponseHttp; /** - * Class Plugin + * Plugin for handling controller after controller tags and pre-controller validation. */ class GraphQl { @@ -76,24 +76,19 @@ public function beforeDispatch( } /** - * Plugin for GraphQL after dispatch to set tag and cache headers + * Plugin for GraphQL after render from dispatch to set tag and cache headers * - * The $response doesn't have a set type because it's alternating between ResponseInterface and ResultInterface - * depending if it comes from builtin cache or the dispatch. + * @param ResultInterface $subject + * @param ResultInterface $result + * @param ResponseHttp $response + * @return ResultInterface * - * @param FrontControllerInterface $subject - * @param ResponseInterface|ResultInterface $response - * @param RequestInterface $request - * @return ResponseInterface|ResultInterface * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function afterDispatch( - FrontControllerInterface $subject, - $response, - RequestInterface $request - ) { + public function afterRenderResult(ResultInterface $subject, ResultInterface $result, ResponseHttp $response) + { $sendNoCacheHeaders = false; - if ($this->config->isEnabled() && $request->isGet()) { + if ($this->config->isEnabled()) { if ($this->cacheableQuery->shouldPopulateCacheHeadersWithTags()) { $this->response->setPublicHeaders($this->config->getTtl()); $this->response->setHeader('X-Magento-Tags', implode(',', $this->cacheableQuery->getCacheTags()), true); @@ -108,6 +103,6 @@ public function afterDispatch( $this->response->setNoCacheHeaders(); } - return $response; + return $result; } } diff --git a/app/code/Magento/GraphQlCache/etc/graphql/di.xml b/app/code/Magento/GraphQlCache/etc/graphql/di.xml index 6636ebacf9e5c..5dd8c816ce929 100644 --- a/app/code/Magento/GraphQlCache/etc/graphql/di.xml +++ b/app/code/Magento/GraphQlCache/etc/graphql/di.xml @@ -19,6 +19,7 @@ type="Magento\GraphQlCache\Model\Plugin\App\PageCache\Identifier" sortOrder="1"/> </type> <type name="Magento\Framework\Controller\ResultInterface"> + <plugin name="graphql-result-plugin" type="Magento\GraphQlCache\Controller\Plugin\GraphQl"/> <plugin name="result-builtin-cache" type="Magento\PageCache\Model\Controller\Result\BuiltinPlugin"/> <plugin name="result-varnish-cache" type="Magento\PageCache\Model\Controller\Result\VarnishPlugin"/> </type> diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php index 49cdca8372593..d0d746812ec44 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php @@ -101,11 +101,7 @@ public function testDispatch() : void $headers = $this->objectManager->create(\Zend\Http\Headers::class) ->addHeaders(['Content-Type' => 'application/json']); $this->request->setHeaders($headers); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->create(\Magento\Framework\App\Response\Http::class); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); - $result->renderResult($response); + $response = $this->graphql->dispatch($this->request); $output = $this->jsonSerializer->unserialize($response->getContent()); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); @@ -147,11 +143,7 @@ public function testDispatchWithGet() : void $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->create(\Magento\Framework\App\Response\Http::class); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); - $result->renderResult($response); + $response = $this->graphql->dispatch($this->request); $output = $this->jsonSerializer->unserialize($response->getContent()); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); @@ -203,11 +195,6 @@ public function testDispatchGetWithParameterizedVariables() : void $this->request->setMethod('GET'); $this->request->setParams($queryParams); $response = $this->graphql->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->create(\Magento\Framework\App\Response\Http::class); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); - $result->renderResult($response); $output = $this->jsonSerializer->unserialize($response->getContent()); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); @@ -257,11 +244,7 @@ public function testError() : void $headers = $this->objectManager->create(\Zend\Http\Headers::class) ->addHeaders(['Content-Type' => 'application/json']); $this->request->setHeaders($headers); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->create(\Magento\Framework\App\Response\Http::class); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); - $result->renderResult($response); + $response = $this->graphql->dispatch($this->request); $outputResponse = $this->jsonSerializer->unserialize($response->getContent()); if (isset($outputResponse['errors'][0])) { if (is_array($outputResponse['errors'][0])) { diff --git a/lib/internal/Magento/Framework/App/PageCache/Kernel.php b/lib/internal/Magento/Framework/App/PageCache/Kernel.php index f89fe93957a97..b507e2e5ca43a 100644 --- a/lib/internal/Magento/Framework/App/PageCache/Kernel.php +++ b/lib/internal/Magento/Framework/App/PageCache/Kernel.php @@ -69,7 +69,7 @@ class Kernel * @param \Magento\Framework\App\Response\HttpFactory|null $httpFactory * @param \Magento\Framework\Serialize\SerializerInterface|null $serializer * @param AppState|null $state - * @param \Magento\PageCache\Model\Cache\Type $fullPageCache + * @param \Magento\PageCache\Model\Cache\Type|null $fullPageCache */ public function __construct( \Magento\Framework\App\PageCache\Cache $cache, diff --git a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php index b0cad2f133a7e..d65e86a37550d 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php @@ -14,7 +14,7 @@ interface IdentityInterface * Get identities from resolved data * * @param array $resolvedData - * @return array + * @return string[] */ public function getIdentities(array $resolvedData) : array; } diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php index 666dfa8d3e8a9..2613b2829e79a 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php @@ -8,7 +8,7 @@ namespace Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader; /** - * Reads documentation from the annotation @cacheable of an AST node + * Reads documentation from the annotation @cache of an AST node */ class CacheTagReader { diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php index c20a3875e71fb..554d2636cf8c3 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php @@ -39,13 +39,8 @@ public function __construct( ) { $this->typeMetaReader = $typeMetaReader; $this->docReader = $docReader; - if ($cacheTagReader) { - $this->cacheTagReader = $cacheTagReader; - } else { - $this->cacheTagReader = \Magento\Framework\App\ObjectManager::getInstance()->get( - CacheTagReader::class - ); - } + $this->cacheTagReader = $cacheTagReader ?? \Magento\Framework\App\ObjectManager::getInstance() + ->get(CacheTagReader::class); } /** diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php index 92ac22607b981..2eda79ce68b04 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php @@ -44,13 +44,8 @@ public function __construct( ) { $this->typeMetaReader = $typeMetaReader; $this->docReader = $docReader; - if ($cacheTagReader) { - $this->cacheTagReader = $cacheTagReader; - } else { - $this->cacheTagReader = \Magento\Framework\App\ObjectManager::getInstance()->get( - CacheTagReader::class - ); - } + $this->cacheTagReader = $cacheTagReader ?? \Magento\Framework\App\ObjectManager::getInstance() + ->get(CacheTagReader::class); } /** diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php index bd21e6361d4c4..7c040cd2e104c 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php @@ -44,13 +44,8 @@ public function __construct( ) { $this->fieldMetaReader = $fieldMetaReader; $this->docReader = $docReader; - if ($cacheTagReader) { - $this->cacheTagReader = $cacheTagReader; - } else { - $this->cacheTagReader = \Magento\Framework\App\ObjectManager::getInstance()->get( - CacheTagReader::class - ); - } + $this->cacheTagReader = $cacheTagReader ?? \Magento\Framework\App\ObjectManager::getInstance() + ->get(CacheTagReader::class); } /** diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php index 361eb30423a98..77a44460f00ae 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php @@ -54,13 +54,8 @@ public function __construct( $this->fieldMetaReader = $fieldMetaReader; $this->docReader = $docReader; $this->implementsAnnotation = $implementsAnnotation; - if ($cacheTagReader) { - $this->cacheTagReader = $cacheTagReader; - } else { - $this->cacheTagReader = \Magento\Framework\App\ObjectManager::getInstance()->get( - CacheTagReader::class - ); - } + $this->cacheTagReader = $cacheTagReader ?? \Magento\Framework\App\ObjectManager::getInstance() + ->get(CacheTagReader::class); } /** From 4c8e768b4907bd81105a89e574b62b61d58be820 Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Thu, 25 Apr 2019 16:37:45 -0500 Subject: [PATCH 522/585] MC-15960: Separate Graphql cache handing in VCL for the /graphql area - Modified vcls to separate graphql cache handling --- app/code/Magento/PageCache/etc/varnish4.vcl | 16 +++++++++++----- app/code/Magento/PageCache/etc/varnish5.vcl | 6 ++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/PageCache/etc/varnish4.vcl b/app/code/Magento/PageCache/etc/varnish4.vcl index 67c097241f868..2ee0aaa945fcd 100644 --- a/app/code/Magento/PageCache/etc/varnish4.vcl +++ b/app/code/Magento/PageCache/etc/varnish4.vcl @@ -123,11 +123,8 @@ sub vcl_hash { hash_data(server.ip); } - if (req.http.Store) { - hash_data(req.http.Store); - } - if (req.http.Content-Currency) { - hash_data(req.http.Content-Currency); + if (req.url ~ "graphql") { + call process_graphql_headers; } # To make sure http users don't see ssl warning @@ -137,6 +134,15 @@ sub vcl_hash { /* {{ design_exceptions_code }} */ } +sub process_graphql_headers { + if (req.http.Store) { + hash_data(req.http.Store); + } + if (req.http.Content-Currency) { + hash_data(req.http.Content-Currency); + } +} + sub vcl_backend_response { set beresp.grace = 3d; diff --git a/app/code/Magento/PageCache/etc/varnish5.vcl b/app/code/Magento/PageCache/etc/varnish5.vcl index 72a6e734f2628..1a8c552ac7550 100644 --- a/app/code/Magento/PageCache/etc/varnish5.vcl +++ b/app/code/Magento/PageCache/etc/varnish5.vcl @@ -130,6 +130,12 @@ sub vcl_hash { } /* {{ design_exceptions_code }} */ + if (req.url ~ "graphql") { + call process_graphql_headers; + } +} + +sub process_graphql_headers { if (req.http.Store) { hash_data(req.http.Store); } From db3b5e1dd6977a35591b90cea310a81df7710714 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 25 Apr 2019 16:46:11 -0500 Subject: [PATCH 523/585] Issue-230: adding varnish - fixing dispatch tests --- .../Framework/GraphQl/Config/GraphQlReaderTest.php | 6 +----- .../Catalog/CategoriesWithProductsCacheTest.php | 6 +----- .../Controller/Catalog/CategoryCacheTest.php | 7 +------ .../Catalog/DeepNestedCategoriesAndProductsTest.php | 6 +----- .../Controller/Catalog/ProductsCacheTest.php | 13 ++----------- .../GraphQlCache/Controller/Cms/BlockCacheTest.php | 6 +----- .../Controller/Cms/CmsPageCacheTest.php | 6 +----- 7 files changed, 8 insertions(+), 42 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php index f6994931562c2..af8d1c7af134b 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php @@ -187,11 +187,7 @@ enumValues(includeDeprecated: true) { ->addHeaders(['Content-Type' => 'application/json']); $request->setHeaders($headers); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->create(\Magento\Framework\App\Response\Http::class); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphQlController->dispatch($request); - $result->renderResult($response); + $response = $this->graphQlController->dispatch($request); $output = $this->jsonSerializer->unserialize($response->getContent()); $expectedOutput = require __DIR__ . '/../_files/schema_response_sdl_description.php'; diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php index f137a2aca8d4c..62cda28a4493a 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php @@ -94,11 +94,7 @@ public function testToCheckRequestCacheTagsForCategoryWithProducts(): void $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setParams($queryParams); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphqlController->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - $result->renderResult($response); + $response = $this->graphqlController->dispatch($this->request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'cat_p','cat_p_' . $product->getId(),'FPC']; $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php index 3c2f46e1474b9..96f6685233f2c 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php @@ -62,12 +62,7 @@ public function testToCheckRequestCacheTagsForForCategory(): void $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphqlController->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ - $result->renderResult($response); + $response = $this->graphqlController->dispatch($this->request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'FPC']; diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php index f8cc7f0e59105..7f992a0843f7c 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php @@ -115,11 +115,7 @@ public function testDispatchForCacheHeadersOnDeepNestedQueries(): void $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphql->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - $result->renderResult($response); + $response = $this->graphql->dispatch($this->request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $this->assertEmpty( diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php index ec55bfcb4928b..78534176a3525 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php @@ -74,12 +74,7 @@ public function testToCheckRequestCacheTagsForProducts(): void $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphqlController->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - /** @var $registry \Magento\Framework\Registry */ - $result->renderResult($response); + $response = $this->graphqlController->dispatch($this->request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; @@ -111,11 +106,7 @@ public function testToCheckRequestNoTagsForProducts(): void $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphqlController->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - $result->renderResult($response); + $response = $this->graphqlController->dispatch($this->request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['FPC']; diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php index 6e9d2ca0f491b..160f5f9109f30 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php @@ -68,11 +68,7 @@ public function testCmsBlocksRequestHasCorrectTags(): void $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphqlController->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - $result->renderResult($response); + $response = $this->graphqlController->dispatch($this->request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $expectedCacheTags = ['cms_b', 'cms_b_' . $block->getId(), 'cms_b_' . $block->getIdentifier(), 'FPC']; $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index fc797b01658ec..8d4bbfc0f2b17 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -71,11 +71,7 @@ public function testToCheckCmsPageRequestCacheTags(): void $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setQueryValue('query', $query); - /** @var \Magento\Framework\Controller\Result\Json $result */ - $result = $this->graphqlController->dispatch($this->request); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->objectManager->get(\Magento\Framework\App\Response\Http::class); - $result->renderResult($response); + $response = $this->graphqlController->dispatch($this->request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId , 'FPC']; From cbe4d208ed610e45a4225c5a85249a600cc02714 Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov <ishakhsuvarov@magento.com> Date: Thu, 25 Apr 2019 17:09:32 -0500 Subject: [PATCH 524/585] magento-engcom/msi#2110: Unskip MFTF for MAGETWO-44165 --- .../Test/Mftf/Test/AdminCreateAndSwitchProductType.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndSwitchProductType.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndSwitchProductType.xml index 93df31a7d89e5..2cc71964042a4 100755 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndSwitchProductType.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndSwitchProductType.xml @@ -53,9 +53,6 @@ <testCaseId value="MC-10930"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MSI-2110"/> - </skip> </annotations> <before> <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> @@ -93,10 +90,6 @@ <useCaseId value="MAGETWO-44165"/> <testCaseId value="MAGETWO-29398"/> <group value="catalog"/> - <group value="mtf_migrated"/> - <skip> - <issueId value="MSI-2110"/> - </skip> </annotations> <before> <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> @@ -139,9 +132,6 @@ <testCaseId value="MAGETWO-29398"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MSI-2110"/> - </skip> </annotations> <before> <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> From a7d21949bff10054751e7d9411292981420f64a6 Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov <ishakhsuvarov@magento.com> Date: Thu, 25 Apr 2019 17:12:13 -0500 Subject: [PATCH 525/585] MSI 1.1.2 Release preparation --- .../Magento/Test/Php/_files/phpcpd/blacklist/common.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt index 35ba5803b09cc..055a3faf70be7 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt +++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt @@ -214,3 +214,4 @@ Magento/Elasticsearch/Model/Layer/Search Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/FieldName/Resolver Magento/Elasticsearch6/Model/Client Magento/Config/App/Config/Type +Magento/InventoryReservationCli/Test/Integration From f9767ec1495fab540d3a0290d6dac8e52049e35d Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 25 Apr 2019 17:13:01 -0500 Subject: [PATCH 526/585] Issue-230: adding varnish - fixing controller type --- app/code/Magento/GraphQl/Controller/GraphQl.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index 4271ac3f6c585..5c6ed5feb5fd0 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -10,6 +10,7 @@ use Magento\Framework\App\FrontControllerInterface; use Magento\Framework\App\Request\Http; use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\ResponseInterface; use Magento\Framework\GraphQl\Exception\ExceptionFormatter; use Magento\Framework\GraphQl\Query\QueryProcessor; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; @@ -121,9 +122,9 @@ public function __construct( * Handle GraphQL request * * @param RequestInterface $request - * @return Response + * @return ResponseInterface */ - public function dispatch(RequestInterface $request) : HttpResponse + public function dispatch(RequestInterface $request) : ResponseInterface { $statusCode = 200; $jsonResult = $this->jsonFactory->create(); From b50dbca8693b6ca49dd633cf121edecec99da128 Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov <ishakhsuvarov@magento.com> Date: Thu, 25 Apr 2019 17:14:51 -0500 Subject: [PATCH 527/585] MC-15534: [MSI] Remove blacklisted dependency --- .../Integrity/DeclarativeDependencyTest.php | 34 ------------------- .../blacklisted_dependencies_ce.php | 9 ----- 2 files changed, 43 deletions(-) delete mode 100644 dev/tests/static/testsuite/Magento/Test/Integrity/_files/dependency_test/blacklisted_dependencies_ce.php diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/DeclarativeDependencyTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/DeclarativeDependencyTest.php index 87cc5afd5ecb3..46bbc93db49e9 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/DeclarativeDependencyTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/DeclarativeDependencyTest.php @@ -22,11 +22,6 @@ class DeclarativeDependencyTest extends \PHPUnit\Framework\TestCase */ private $dependencyProvider; - /** - * @var array - */ - private $blacklistedDependencies = []; - /** * Sets up data * @@ -50,14 +45,6 @@ protected function setUp() */ public function testUndeclaredDependencies() { - /** TODO: Remove this temporary solution after MC-15534 is closed */ - $filePattern = __DIR__ . '/_files/dependency_test/blacklisted_dependencies_*.php'; - $blacklistedDependencies = []; - foreach (glob($filePattern) as $fileName) { - $blacklistedDependencies = array_merge($blacklistedDependencies, require $fileName); - } - $this->blacklistedDependencies = $blacklistedDependencies; - $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this); $invoker( /** @@ -84,9 +71,6 @@ function ($file) { $result = []; foreach ($undeclaredDependency as $name => $modules) { $modules = array_unique($modules); - if ($this->filterBlacklistedDependencies($foundModuleName, $modules)) { - $result[] = $this->getErrorMessage($name) . "\n" . implode("\t\n", $modules) . "\n"; - } } if (!empty($result)) { $this->fail( @@ -98,24 +82,6 @@ function ($file) { ); } - /** - * Filter blacklisted dependencies. - * - * @todo Remove this temporary solution after MC-15534 is closed - * - * @param string $moduleName - * @param array $dependencies - * @return array - */ - private function filterBlacklistedDependencies(string $moduleName, array $dependencies): array - { - if (!empty($this->blacklistedDependencies[$moduleName])) { - $dependencies = array_diff($dependencies, $this->blacklistedDependencies[$moduleName]); - } - - return $dependencies; - } - /** * Convert file list to data provider structure. * diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/dependency_test/blacklisted_dependencies_ce.php b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/dependency_test/blacklisted_dependencies_ce.php deleted file mode 100644 index 270cb99c29caa..0000000000000 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/dependency_test/blacklisted_dependencies_ce.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); -return [ - "Magento\InventorySales" => ["Magento\Inventory"], -]; From 059ac0d5cc760d2adadec46892a1f91f4afa706d Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Thu, 25 Apr 2019 17:31:54 -0500 Subject: [PATCH 528/585] MC-15960: Separate Graphql cache handing in VCL for the /graphql area - Modified vcls to separate graphql cache handling for queries starting with /graphql --- app/code/Magento/PageCache/etc/varnish4.vcl | 2 +- app/code/Magento/PageCache/etc/varnish5.vcl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/PageCache/etc/varnish4.vcl b/app/code/Magento/PageCache/etc/varnish4.vcl index 2ee0aaa945fcd..6de6b4e917044 100644 --- a/app/code/Magento/PageCache/etc/varnish4.vcl +++ b/app/code/Magento/PageCache/etc/varnish4.vcl @@ -123,7 +123,7 @@ sub vcl_hash { hash_data(server.ip); } - if (req.url ~ "graphql") { + if (req.url ~ "/graphql") { call process_graphql_headers; } diff --git a/app/code/Magento/PageCache/etc/varnish5.vcl b/app/code/Magento/PageCache/etc/varnish5.vcl index 1a8c552ac7550..4505e74629714 100644 --- a/app/code/Magento/PageCache/etc/varnish5.vcl +++ b/app/code/Magento/PageCache/etc/varnish5.vcl @@ -130,7 +130,7 @@ sub vcl_hash { } /* {{ design_exceptions_code }} */ - if (req.url ~ "graphql") { + if (req.url ~ "/graphql") { call process_graphql_headers; } } From 32443776da0b10507eacf8c49f97999101e926e7 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Thu, 25 Apr 2019 17:48:57 -0500 Subject: [PATCH 529/585] MAGETWO-99418: Deliver critical PR for 2.3.2 --- app/code/Magento/MessageQueue/Model/PoisonPillCompare.php | 2 +- .../MessageQueue/Model/ResourceModel/PoisonPill.php | 8 ++++---- .../Framework/MessageQueue/PoisonPill/PoisonPillRead.php | 4 ++-- .../MessageQueue/PoisonPill/PoisonPillReadInterface.php | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/MessageQueue/Model/PoisonPillCompare.php b/app/code/Magento/MessageQueue/Model/PoisonPillCompare.php index a4c89fd26506b..ffa478aecf36c 100644 --- a/app/code/Magento/MessageQueue/Model/PoisonPillCompare.php +++ b/app/code/Magento/MessageQueue/Model/PoisonPillCompare.php @@ -35,6 +35,6 @@ public function __construct( */ public function isLatestVersion(string $poisonPillVersion): bool { - return (string) $poisonPillVersion === (string) $this->poisonPillRead->getLatestVersion(); + return $poisonPillVersion === $this->poisonPillRead->getLatestVersion(); } } diff --git a/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php b/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php index 20687ca4cede2..bc4b43c419780 100644 --- a/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php +++ b/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php @@ -50,7 +50,7 @@ public function put(): string /** * @inheritdoc */ - public function getLatestVersion(): ?string + public function getLatestVersion(): string { return $this->getVersionFromDb(); } @@ -58,9 +58,9 @@ public function getLatestVersion(): ?string /** * Returns version form DB or null. * - * @return string|null + * @return string */ - private function getVersionFromDb(): ?string + private function getVersionFromDb(): string { $select = $this->getConnection()->select()->from( $this->getTable(self::QUEUE_POISON_PILL_TABLE), @@ -69,6 +69,6 @@ private function getVersionFromDb(): ?string $result = $this->getConnection()->fetchOne($select); - return $result === false ? null : $result; + return (string)$result; } } diff --git a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php index 68048996ed0f9..0f0ed5a807473 100644 --- a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillRead.php @@ -19,8 +19,8 @@ class PoisonPillRead implements PoisonPillReadInterface * * @return string */ - public function getLatestVersion(): ?string + public function getLatestVersion(): string { - return null; + return ''; } } diff --git a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillReadInterface.php b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillReadInterface.php index 55ff5feb2d9b2..6748e3208611f 100644 --- a/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillReadInterface.php +++ b/lib/internal/Magento/Framework/MessageQueue/PoisonPill/PoisonPillReadInterface.php @@ -17,5 +17,5 @@ interface PoisonPillReadInterface * * @return string */ - public function getLatestVersion(): ?string; + public function getLatestVersion(): string; } From 32a6114c4d8a1471fa1fd6fe8b4b87aa56916aef Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov <ishakhsuvarov@magento.com> Date: Thu, 25 Apr 2019 18:13:33 -0500 Subject: [PATCH 530/585] MC-15534: [MSI] Remove blacklisted dependency --- .../Magento/Test/Integrity/DeclarativeDependencyTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/DeclarativeDependencyTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/DeclarativeDependencyTest.php index 46bbc93db49e9..e090338f90c65 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/DeclarativeDependencyTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/DeclarativeDependencyTest.php @@ -71,6 +71,7 @@ function ($file) { $result = []; foreach ($undeclaredDependency as $name => $modules) { $modules = array_unique($modules); + $result[] = $this->getErrorMessage($name) . "\n" . implode("\t\n", $modules) . "\n"; } if (!empty($result)) { $this->fail( From 97bdecc78dde3a0c6d8eeaad98ecdfe50e8575be Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Fri, 26 Apr 2019 10:48:30 +0300 Subject: [PATCH 531/585] magento/magento2#22302 Static test fix --- app/code/Magento/Cms/Block/Block.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Cms/Block/Block.php b/app/code/Magento/Cms/Block/Block.php index 4fc37b50dcbc0..c611f4b1e9f05 100644 --- a/app/code/Magento/Cms/Block/Block.php +++ b/app/code/Magento/Cms/Block/Block.php @@ -86,7 +86,7 @@ public function getIdentities() } /** - * {@inheritdoc} + * @inheritdoc */ public function getCacheKeyInfo() { From 0a0b32b177b66a3d87b91347eec828cbc5086449 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Fri, 26 Apr 2019 09:20:53 -0500 Subject: [PATCH 532/585] Issue-230: adding varnish - fixing static --- app/code/Magento/GraphQl/Controller/GraphQl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index 5c6ed5feb5fd0..75b3ad277c603 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -114,8 +114,8 @@ public function __construct( $this->resolverContext = $resolverContext; $this->requestProcessor = $requestProcessor; $this->queryFields = $queryFields; - $this->jsonFactory = $jsonFactory ?:ObjectManager::getInstance()->get(JsonFactory::class); - $this->httpResponse = $httpResponse ?:ObjectManager::getInstance()->get(HttpResponse::class); + $this->jsonFactory = $jsonFactory ?: ObjectManager::getInstance()->get(JsonFactory::class); + $this->httpResponse = $httpResponse ?: ObjectManager::getInstance()->get(HttpResponse::class); } /** From c1ba453f6bf1a6cb59af3cf6cf10dce8d22ab83a Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Fri, 26 Apr 2019 10:30:47 -0500 Subject: [PATCH 533/585] MAGETWO-99418: Deliver critical PR for 2.3.2 --- .../Magento/MessageQueue/Model/ResourceModel/PoisonPill.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php b/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php index bc4b43c419780..e59abec8724fb 100644 --- a/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php +++ b/app/code/Magento/MessageQueue/Model/ResourceModel/PoisonPill.php @@ -38,7 +38,7 @@ public function put(): string $table = $this->getMainTable(); $uuid = uniqid('version-'); $version = $this->getVersionFromDb(); - if ($version !== null) { + if ($version !== '') { $connection->update($table, ['version' => $uuid]); } else { $connection->insert($table, ['version' => $uuid]); From 64bf6ddd8017b8566e094b25a7da22619b964295 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Fri, 26 Apr 2019 11:28:05 -0500 Subject: [PATCH 534/585] =?UTF-8?q?GraphQL-608:=20Remove=20=E2=80=9Ccart?= =?UTF-8?q?=5Faddress=5Fid=E2=80=9D=20from=20=E2=80=9CShippingMethodInput?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup/performance-toolkit/benchmark.jmx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 5521f7024722b..22af21f07abc5 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -44214,7 +44214,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setShippingMethodsOnCart(input: \n {\n cart_id: \"${quote_id}\", \n shipping_methods: [{\n cart_address_id: ${address_id}\n carrier_code: \"flatrate\"\n method_code: \"flatrate\"\n }]\n }) {\n cart {\n shipping_addresses {\n selected_shipping_method {\n carrier_code\n method_code\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n setShippingMethodsOnCart(input: \n {\n cart_id: \"${quote_id}\", \n shipping_methods: [{\n carrier_code: \"flatrate\"\n method_code: \"flatrate\"\n }]\n }) {\n cart {\n shipping_addresses {\n selected_shipping_method {\n carrier_code\n method_code\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> From 16adb974aa7f3043239a481703305f2a3fc01aa2 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Fri, 26 Apr 2019 11:50:31 -0500 Subject: [PATCH 535/585] MAGETWO-99418: Deliver critical PR for 2.3.2 --- app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php index 14043f950ae16..a234cd589904c 100644 --- a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php @@ -14,7 +14,7 @@ */ class JsFooterPlugin { - const XML_PATH_DEV_MOVE_JS_TO_BOTTOM = 'dev/js/move_inline_to_bottom'; + private const XML_PATH_DEV_MOVE_JS_TO_BOTTOM = 'dev/js/move_inline_to_bottom'; /** * @var ScopeConfigInterface From 157f52095f541a51f2a0f86d9f32d35a89156840 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Fri, 26 Apr 2019 12:21:56 -0500 Subject: [PATCH 536/585] GraphQL-601: [Test Coverage] Offline payments methods --- .../Model/Resolver/SelectedPaymentMethod.php | 1 + .../Magento/QuoteGraphQl/etc/schema.graphqls | 7 ++- .../SetOfflinePaymentMethodsOnCartTest.php | 59 +++++++++++-------- .../SetOfflinePaymentMethodsOnCartTest.php | 58 ++++++++++-------- 4 files changed, 73 insertions(+), 52 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php index 7a99b04638ac3..8cda06eba3c91 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php @@ -36,6 +36,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value return [ 'code' => $payment->getMethod(), + 'title' => $payment->getMethodInstance()->getTitle(), 'purchase_order_number' => $payment->getPoNumber(), ]; } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index a9784e97c8952..67e40faae40a0 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -241,12 +241,13 @@ type AvailableShippingMethod { } type AvailablePaymentMethod { - code: String @doc(description: "The payment method code") - title: String @doc(description: "The payment method title.") + code: String! @doc(description: "The payment method code") + title: String! @doc(description: "The payment method title.") } type SelectedPaymentMethod { - code: String @doc(description: "The payment method code") + code: String! @doc(description: "The payment method code") + title: String! @doc(description: "The payment method title.") purchase_order_number: String @doc(description: "The purchase order number.") } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php index e0f4756177715..0fe7aec2d6347 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php @@ -50,23 +50,38 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php * * @param string $methodCode + * @param string $methodTitle * @dataProvider offlinePaymentMethodDataProvider */ - public function testSetOfflinePaymentMethod(string $methodCode) + public function testSetOfflinePaymentMethod(string $methodCode, string $methodTitle) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery( - $maskedQuoteId, - $methodCode - ); + $query = $this->getQuery($maskedQuoteId, $methodCode); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); - self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + + $selectedPaymentMethod = $response['setPaymentMethodOnCart']['cart']['selected_payment_method']; + self::assertArrayHasKey('code', $selectedPaymentMethod); + self::assertEquals($methodCode, $selectedPaymentMethod['code']); + + self::assertArrayHasKey('title', $selectedPaymentMethod); + self::assertEquals($methodTitle, $selectedPaymentMethod['title']); + } + + /** + * @return array + */ + public function offlinePaymentMethodDataProvider(): array + { + return [ + 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE, 'Check / Money order'], + 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE, 'Bank Transfer Payment'], + 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE, 'Cash On Delivery'], + ]; } /** @@ -76,12 +91,11 @@ public function testSetOfflinePaymentMethod(string $methodCode) * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php - * - * @param string $methodCode */ public function testSetPurchaseOrderPaymentMethod() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $methodTitle = 'Purchase Order'; $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; $poNumber = 'abc123'; @@ -97,34 +111,28 @@ public function testSetPurchaseOrderPaymentMethod() cart { selected_payment_method { code + title purchase_order_number } } } } QUERY; - $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); - self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertArrayHasKey('purchase_order_number', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); - self::assertEquals($poNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); - } - /** - * @return array - */ - public function offlinePaymentMethodDataProvider(): array - { - return [ - 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE], - 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE], - 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE], - ]; + $selectedPaymentMethod = $response['setPaymentMethodOnCart']['cart']['selected_payment_method']; + self::assertArrayHasKey('code', $selectedPaymentMethod); + self::assertEquals($methodCode, $selectedPaymentMethod['code']); + + self::assertArrayHasKey('title', $selectedPaymentMethod); + self::assertEquals($methodTitle, $selectedPaymentMethod['title']); + + self::assertArrayHasKey('purchase_order_number', $selectedPaymentMethod); + self::assertEquals($poNumber, $selectedPaymentMethod['purchase_order_number']); } /** @@ -147,6 +155,7 @@ private function getQuery( cart { selected_payment_method { code + title } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php index 83fffd9defabf..7ec3148ea85a0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php @@ -42,23 +42,38 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php * * @param string $methodCode + * @param string $methodTitle * @dataProvider offlinePaymentMethodDataProvider */ - public function testSetOfflinePaymentMethod(string $methodCode) + public function testSetOfflinePaymentMethod(string $methodCode, string $methodTitle) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery( - $maskedQuoteId, - $methodCode - ); + $query = $this->getQuery($maskedQuoteId, $methodCode); $response = $this->graphQlMutation($query); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); - self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + + $selectedPaymentMethod = $response['setPaymentMethodOnCart']['cart']['selected_payment_method']; + self::assertArrayHasKey('code', $selectedPaymentMethod); + self::assertEquals($methodCode, $selectedPaymentMethod['code']); + + self::assertArrayHasKey('title', $selectedPaymentMethod); + self::assertEquals($methodTitle, $selectedPaymentMethod['title']); + } + + /** + * @return array + */ + public function offlinePaymentMethodDataProvider(): array + { + return [ + 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE, 'Check / Money order'], + 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE, 'Bank Transfer Payment'], + 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE, 'Cash On Delivery'], + ]; } /** @@ -67,13 +82,12 @@ public function testSetOfflinePaymentMethod(string $methodCode) * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php - * - * @param string $methodCode */ public function testSetPurchaseOrderPaymentMethod() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $methodTitle = 'Purchase Order'; $poNumber = 'abc123'; $query = <<<QUERY @@ -88,6 +102,7 @@ public function testSetPurchaseOrderPaymentMethod() cart { selected_payment_method { code + title purchase_order_number } } @@ -100,22 +115,16 @@ public function testSetPurchaseOrderPaymentMethod() self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); - self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertArrayHasKey('purchase_order_number', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); - self::assertEquals($poNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); - } - /** - * @return array - */ - public function offlinePaymentMethodDataProvider(): array - { - return [ - 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE], - 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE], - 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE], - ]; + $selectedPaymentMethod = $response['setPaymentMethodOnCart']['cart']['selected_payment_method']; + self::assertArrayHasKey('code', $selectedPaymentMethod); + self::assertEquals($methodCode, $selectedPaymentMethod['code']); + + self::assertArrayHasKey('title', $selectedPaymentMethod); + self::assertEquals($methodTitle, $selectedPaymentMethod['title']); + + self::assertArrayHasKey('purchase_order_number', $selectedPaymentMethod); + self::assertEquals($poNumber, $selectedPaymentMethod['purchase_order_number']); } /** @@ -138,6 +147,7 @@ private function getQuery( cart { selected_payment_method { code + title } } } From 692cd9dc92234b256e40c9aeb09055fd7207d4f0 Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Sun, 28 Apr 2019 19:35:39 +0100 Subject: [PATCH 537/585] magento/magento2#21150: Fixed static tests --- .../Magento/blank/web/css/source/components/_modals_extend.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less b/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less index 2ab9f061c60c1..764a63bd88064 100644 --- a/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less +++ b/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less @@ -150,7 +150,7 @@ } .modal-popup { - pointer-events: auto; + pointer-events: auto; &.modal-slide { .modal-inner-wrap[class] { .lib-css(background-color, @modal-slide-mobile__background-color); From ee8778b330a4f327dffdaa90add23c51da8b3492 Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Sun, 28 Apr 2019 19:36:04 +0100 Subject: [PATCH 538/585] magento/magento2#21150: Fixed static tests --- .../Magento/luma/web/css/source/components/_modals_extend.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less b/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less index 441b6669b545f..855700806fdba 100644 --- a/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less +++ b/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less @@ -150,7 +150,7 @@ } .modal-popup { - pointer-events: auto; + pointer-events: auto; &.modal-slide { .modal-inner-wrap[class] { .lib-css(background-color, @modal-slide-mobile__background-color); From 9b71d809edbf43e4d9eae6915add74286db187dc Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Sun, 28 Apr 2019 23:11:43 +0100 Subject: [PATCH 539/585] magento/magento2#21549: Fixed static tests --- lib/internal/Magento/Framework/HTTP/Adapter/Curl.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php index 96af9be49f340..f2a703a193e28 100644 --- a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php +++ b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php @@ -4,11 +4,6 @@ * See COPYING.txt for license details. */ -/** - * HTTP CURL Adapter - * - * @author Magento Core Team <core@magentocommerce.com> - */ namespace Magento\Framework\HTTP\Adapter; /** @@ -115,8 +110,8 @@ public function setOptions(array $options = []) /** * Add additional option to cURL * - * @param int $option the CURLOPT_* constants - * @param mixed $value + * @param int $option the CURLOPT_* constants + * @param mixed $value * @return $this */ public function addOption($option, $value) From e161862468831a99cfb6fee8b77930909551c702 Mon Sep 17 00:00:00 2001 From: sanjay <sanjay.chouhan180@webkul.com> Date: Mon, 29 Apr 2019 09:56:56 +0530 Subject: [PATCH 540/585] fixed issue 22527 wishlist and compare icon alignment --- .../blank/Magento_Catalog/web/css/source/module/_listings.less | 1 + .../luma/Magento_Catalog/web/css/source/module/_listings.less | 1 + 2 files changed, 2 insertions(+) diff --git a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module/_listings.less b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module/_listings.less index b7af69fd5ca82..f96538b59a70f 100644 --- a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module/_listings.less +++ b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module/_listings.less @@ -104,6 +104,7 @@ .actions-primary { display: inline-block; + vertical-align: middle; } } diff --git a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less index 77fb53a2ab02a..eeec441c74aca 100644 --- a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less +++ b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less @@ -107,6 +107,7 @@ .actions-primary { display: inline-block; + vertical-align: middle; } } From 46d56fe5a9e732eaf2c11e1c51b21eb81427f291 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Mon, 29 Apr 2019 10:19:12 +0530 Subject: [PATCH 541/585] code cleanup (http to https) --- app/code/Magento/Backend/Block/Store/Switcher.php | 2 +- app/code/Magento/Braintree/etc/adminhtml/system.xml | 2 +- .../Ui/DataProvider/Product/Form/Modifier/Websites.php | 2 +- .../view/adminhtml/ui_component/catalog_rule_form.xml | 2 +- .../Customer/view/base/ui_component/customer_form.xml | 2 +- app/code/Magento/Paypal/etc/adminhtml/system.xml | 10 +++++----- .../Paypal/etc/adminhtml/system/express_checkout.xml | 2 +- .../Paypal/etc/adminhtml/system/payflow_advanced.xml | 2 +- .../Paypal/etc/adminhtml/system/payflow_link.xml | 2 +- .../adminhtml/system/payments_pro_hosted_solution.xml | 2 +- .../Paypal/etc/adminhtml/system/paypal_payflowpro.xml | 2 +- .../view/adminhtml/ui_component/sales_rule_form.xml | 2 +- .../adminhtml/ui_component/search_synonyms_form.xml | 2 +- app/code/Magento/Tax/etc/config.xml | 2 +- .../Model/Config/Structure/Reader/_files/config.xml | 10 +++++----- 15 files changed, 23 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/Backend/Block/Store/Switcher.php b/app/code/Magento/Backend/Block/Store/Switcher.php index 1468df2b0b442..709f44a879a3f 100644 --- a/app/code/Magento/Backend/Block/Store/Switcher.php +++ b/app/code/Magento/Backend/Block/Store/Switcher.php @@ -17,7 +17,7 @@ class Switcher extends \Magento\Backend\Block\Template /** * URL for store switcher hint */ - const HINT_URL = 'http://docs.magento.com/m2/ce/user_guide/configuration/scope.html'; + const HINT_URL = 'https://docs.magento.com/m2/ce/user_guide/configuration/scope.html'; /** * Name of website variable diff --git a/app/code/Magento/Braintree/etc/adminhtml/system.xml b/app/code/Magento/Braintree/etc/adminhtml/system.xml index 5215dbc00b7ef..67c47f8ea9dc3 100644 --- a/app/code/Magento/Braintree/etc/adminhtml/system.xml +++ b/app/code/Magento/Braintree/etc/adminhtml/system.xml @@ -41,7 +41,7 @@ </requires> </field> <group id="configuration_details" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="4"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/braintree.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/braintree.html</comment> <frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint</frontend_model> </group> <group id="braintree_required" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="5"> diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php index 9cbbb86a2c555..7d1d5d4d77d1b 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php @@ -165,7 +165,7 @@ protected function getFieldsForFieldset() $websitesList = $this->getWebsitesList(); $isNewProduct = !$this->locator->getProduct()->getId(); $tooltip = [ - 'link' => 'http://docs.magento.com/m2/ce/user_guide/configuration/scope.html', + 'link' => 'https://docs.magento.com/m2/ce/user_guide/configuration/scope.html', 'description' => __( 'If your Magento installation has multiple websites, ' . 'you can edit the scope to use the product on specific sites.' diff --git a/app/code/Magento/CatalogRule/view/adminhtml/ui_component/catalog_rule_form.xml b/app/code/Magento/CatalogRule/view/adminhtml/ui_component/catalog_rule_form.xml index fb34a3ac4bb3b..8174434a06c49 100644 --- a/app/code/Magento/CatalogRule/view/adminhtml/ui_component/catalog_rule_form.xml +++ b/app/code/Magento/CatalogRule/view/adminhtml/ui_component/catalog_rule_form.xml @@ -136,7 +136,7 @@ </validation> <dataType>number</dataType> <tooltip> - <link>http://docs.magento.com/m2/ce/user_guide/configuration/scope.html</link> + <link>https://docs.magento.com/m2/ce/user_guide/configuration/scope.html</link> <description>What is this?</description> </tooltip> <label translate="true">Websites</label> diff --git a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml index 7e6b7bbe9cd09..495b3d13645d9 100644 --- a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml +++ b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml @@ -118,7 +118,7 @@ </validation> <dataType>number</dataType> <tooltip> - <link>http://docs.magento.com/m2/ce/user_guide/configuration/scope.html</link> + <link>https://docs.magento.com/m2/ce/user_guide/configuration/scope.html</link> <description translate="true">If your Magento installation has multiple websites, you can edit the scope to associate the customer with a specific site.</description> </tooltip> <imports> diff --git a/app/code/Magento/Paypal/etc/adminhtml/system.xml b/app/code/Magento/Paypal/etc/adminhtml/system.xml index ea48aa65132e8..ca886c7827ffd 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system.xml @@ -75,7 +75,7 @@ <label>Payments Pro</label> <attribute type="activity_path">payment/paypal_payment_pro/active</attribute> <group id="configuration_details"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html</comment> </group> <group id="paypal_payflow_required" showInDefault="1" showInWebsite="1" sortOrder="10"> <field id="enable_paypal_payflow"> @@ -95,7 +95,7 @@ <comment>Accept credit card and PayPal payments securely.</comment> <attribute type="activity_path">payment/wps_express/active</attribute> <group id="configuration_details"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> </group> <group id="express_checkout_required"> <group id="express_checkout_required_express_checkout"> @@ -174,7 +174,7 @@ <comment>Accept credit card and PayPal payments securely.</comment> <attribute type="activity_path">payment/wps_express/active</attribute> <group id="configuration_details"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> </group> <group id="express_checkout_required"> <group id="express_checkout_required_express_checkout" translate="label"> @@ -245,7 +245,7 @@ <comment>Accept credit card and PayPal payments securely.</comment> <attribute type="activity_path">payment/wps_express/active</attribute> <group id="configuration_details"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> </group> <group id="express_checkout_required"> <group id="express_checkout_required_express_checkout" translate="label"> @@ -290,7 +290,7 @@ <label>Website Payments Pro</label> <attribute type="activity_path">payment/paypal_payment_pro/active</attribute> <group id="configuration_details"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html</comment> </group> <group id="paypal_payflow_required" translate="label" showInDefault="1" showInWebsite="1" sortOrder="10"> <group id="paypal_payflow_api_settings"> diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml b/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml index 7abefbe1a674e..d5287659ee7d2 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml @@ -13,7 +13,7 @@ <comment>Add PayPal as an additional payment method to your checkout page.</comment> <attribute type="activity_path">payment/paypal_express/active</attribute> <group id="configuration_details" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="4"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-express-checkout.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-express-checkout.html</comment> <frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint</frontend_model> </group> <group id="express_checkout_required" translate="label" showInDefault="1" showInWebsite="1" sortOrder="10"> diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/payflow_advanced.xml b/app/code/Magento/Paypal/etc/adminhtml/system/payflow_advanced.xml index e7de9c0d641a7..cba36916c3305 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/payflow_advanced.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/payflow_advanced.xml @@ -13,7 +13,7 @@ <comment><![CDATA[Accept payments with a PCI-compliant checkout that keeps customers on your site. (<u>Includes Express Checkout</u>)]]></comment> <attribute type="activity_path">payment/payflow_advanced/active</attribute> <group id="configuration_details" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="4"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-advanced.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-advanced.html</comment> <frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint</frontend_model> </group> <group id="required_settings" translate="label" showInDefault="1" showInWebsite="1" sortOrder="10"> diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/payflow_link.xml b/app/code/Magento/Paypal/etc/adminhtml/system/payflow_link.xml index 647bc7a60975a..ed11e8ba18d07 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/payflow_link.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/payflow_link.xml @@ -13,7 +13,7 @@ <comment><![CDATA[Connect your merchant account with a PCI-compliant gateway that lets customers pay without leaving your site. (<u>Includes Express Checkout</u>)]]></comment> <attribute type="activity_path">payment/payflow_link/active</attribute> <group id="configuration_details" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="4"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payflow-link.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payflow-link.html</comment> <frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint</frontend_model> </group> <group id="payflow_link_required" translate="label" showInDefault="1" showInWebsite="1" sortOrder="10"> diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution.xml b/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution.xml index 35cd844204843..727bffdaf27e3 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution.xml @@ -14,7 +14,7 @@ <comment><![CDATA[Accept payments with a PCI compliant checkout that keeps customers on your site. (<u>Includes Express Checkout</u>)]]></comment> <attribute type="paypal_ec_separate">1</attribute> <group id="configuration_details" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="4"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html</comment> <frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint</frontend_model> </group> <group id="pphs_required_settings" translate="label" showInDefault="1" showInWebsite="1" sortOrder="10"> diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro.xml b/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro.xml index fcf3fb39d1b7d..e5a0319bdc1bf 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro.xml @@ -14,7 +14,7 @@ <attribute type="activity_path">payment/payflowpro/active</attribute> <attribute type="paypal_ec_separate">1</attribute> <group id="configuration_details" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="4"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payflow-pro.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payflow-pro.html</comment> <frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint</frontend_model> </group> <group id="paypal_payflow_required" translate="label" showInDefault="1" showInWebsite="1" sortOrder="10"> diff --git a/app/code/Magento/SalesRule/view/adminhtml/ui_component/sales_rule_form.xml b/app/code/Magento/SalesRule/view/adminhtml/ui_component/sales_rule_form.xml index 570eb0bf151f0..639e12006232b 100644 --- a/app/code/Magento/SalesRule/view/adminhtml/ui_component/sales_rule_form.xml +++ b/app/code/Magento/SalesRule/view/adminhtml/ui_component/sales_rule_form.xml @@ -128,7 +128,7 @@ </validation> <dataType>number</dataType> <tooltip> - <link>http://docs.magento.com/m2/ce/user_guide/configuration/scope.html</link> + <link>https://docs.magento.com/m2/ce/user_guide/configuration/scope.html</link> <description>What is this?</description> </tooltip> <label translate="true">Websites</label> diff --git a/app/code/Magento/Search/view/adminhtml/ui_component/search_synonyms_form.xml b/app/code/Magento/Search/view/adminhtml/ui_component/search_synonyms_form.xml index 9194bd5f741d6..09e5149004f3e 100644 --- a/app/code/Magento/Search/view/adminhtml/ui_component/search_synonyms_form.xml +++ b/app/code/Magento/Search/view/adminhtml/ui_component/search_synonyms_form.xml @@ -72,7 +72,7 @@ </validation> <dataType>int</dataType> <tooltip> - <link>http://docs.magento.com/m2/ce/user_guide/stores/websites-stores-views.html</link> + <link>https://docs.magento.com/m2/ce/user_guide/stores/websites-stores-views.html</link> <description translate="true">You can adjust the scope of this synonym group by selecting an option from the list.</description> </tooltip> <label translate="true">Scope</label> diff --git a/app/code/Magento/Tax/etc/config.xml b/app/code/Magento/Tax/etc/config.xml index 0b837944a3614..afe7bd7861168 100644 --- a/app/code/Magento/Tax/etc/config.xml +++ b/app/code/Magento/Tax/etc/config.xml @@ -49,7 +49,7 @@ <zero_tax>0</zero_tax> </sales_display> <notification> - <info_url>http://docs.magento.com/m2/ce/user_guide/tax/warning-messages.html</info_url> + <info_url>https://docs.magento.com/m2/ce/user_guide/tax/warning-messages.html</info_url> </notification> </tax> </default> diff --git a/dev/tests/integration/testsuite/Magento/Config/Model/Config/Structure/Reader/_files/config.xml b/dev/tests/integration/testsuite/Magento/Config/Model/Config/Structure/Reader/_files/config.xml index 95b9c7bd73e63..f473af1bce37c 100644 --- a/dev/tests/integration/testsuite/Magento/Config/Model/Config/Structure/Reader/_files/config.xml +++ b/dev/tests/integration/testsuite/Magento/Config/Model/Config/Structure/Reader/_files/config.xml @@ -74,7 +74,7 @@ <label>Payments Pro</label> <attribute type="activity_path">payment/paypal_payment_pro/active</attribute> <group id="configuration_details"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html</comment> </group> <group id="paypal_payflow_required" translate="label" showInDefault="1" showInWebsite="1" sortOrder="10"> <field id="enable_paypal_payflow"> @@ -94,7 +94,7 @@ <comment>Accept credit card and PayPal payments securely.</comment> <attribute type="activity_path">payment/wps_express/active</attribute> <group id="configuration_details"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> </group> <group id="express_checkout_required"> <group id="express_checkout_required_express_checkout"> @@ -162,7 +162,7 @@ <comment>Accept credit card and PayPal payments securely.</comment> <attribute type="activity_path">payment/wps_express/active</attribute> <group id="configuration_details"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> </group> <group id="express_checkout_required"> <group id="express_checkout_required_express_checkout"> @@ -233,7 +233,7 @@ <comment>Accept credit card and PayPal payments securely.</comment> <attribute type="activity_path">payment/wps_express/active</attribute> <group id="configuration_details"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html</comment> </group> <group id="express_checkout_required"> <group id="express_checkout_required_express_checkout"> @@ -278,7 +278,7 @@ <label>Website Payments Pro</label> <attribute type="activity_path">payment/paypal_payment_pro/active</attribute> <group id="configuration_details"> - <comment>http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html</comment> + <comment>https://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html</comment> </group> <group id="paypal_payflow_required" translate="label" showInDefault="1" showInWebsite="1" sortOrder="10"> <group id="paypal_payflow_api_settings"> From aaa28b8368625daf3d879d5d9c4a44b2927b75c8 Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Mon, 29 Apr 2019 08:30:54 +0100 Subject: [PATCH 542/585] magento/magento2#22132: Fixed static tests --- app/code/Magento/Theme/Model/Design/Backend/File.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Theme/Model/Design/Backend/File.php b/app/code/Magento/Theme/Model/Design/Backend/File.php index 1dacf59559486..27636b4d574cd 100644 --- a/app/code/Magento/Theme/Model/Design/Backend/File.php +++ b/app/code/Magento/Theme/Model/Design/Backend/File.php @@ -104,6 +104,7 @@ public function beforeSave() return $this; } + //phpcs:ignore Magento2.Functions.DiscouragedFunction $this->updateMediaDirectory(basename($file), $value['url']); return $this; @@ -116,6 +117,7 @@ public function afterLoad() { $value = $this->getValue(); if ($value && !is_array($value)) { + //phpcs:ignore Magento2.Functions.DiscouragedFunction $fileName = $this->_getUploadDir() . '/' . basename($value); $fileInfo = null; if ($this->_mediaDirectory->isExist($fileName)) { @@ -126,6 +128,7 @@ public function afterLoad() 'url' => $url, 'file' => $value, 'size' => is_array($stat) ? $stat['size'] : 0, + //phpcs:ignore Magento2.Functions.DiscouragedFunction 'name' => basename($value), 'type' => $this->getMimeType($fileName), 'exists' => true, From e8f136991728d9ef709b3a817533cc417dcc65ee Mon Sep 17 00:00:00 2001 From: Oscar Recio <osrecio@gmail.com> Date: Thu, 25 Apr 2019 16:45:56 +0200 Subject: [PATCH 543/585] #631 Rename qty by quantity Rename CartItemQuantityInput by CartItemUpdateQuantityInput Rename CartItemInput by CartItemQuantityInput Adapt tests --- .../ConfigurableProductGraphQl/etc/schema.graphqls | 2 +- .../Model/Cart/AddSimpleProductToCart.php | 4 ++-- .../QuoteGraphQl/Model/Resolver/CartItems.php | 2 +- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 14 +++++++------- .../CatalogInventory/AddProductToCartTest.php | 4 ++-- .../AddConfigurableProductToCartTest.php | 6 +++--- ...AddSimpleProductWithCustomOptionsToCartTest.php | 4 ++-- ...ddVirtualProductWithCustomOptionsToCartTest.php | 4 ++-- .../Quote/Customer/AddSimpleProductToCartTest.php | 6 +++--- .../Quote/Customer/AddVirtualProductToCartTest.php | 6 +++--- .../Quote/Customer/CheckoutEndToEndTest.php | 4 ++-- .../Magento/GraphQl/Quote/Customer/GetCartTest.php | 6 +++--- .../Quote/Customer/RemoveItemFromCartTest.php | 4 ++-- .../Quote/Customer/SetPaymentMethodOnCartTest.php | 2 +- .../GraphQl/Quote/Customer/UpdateCartItemsTest.php | 10 +++++----- .../Quote/Guest/AddSimpleProductToCartTest.php | 6 +++--- .../Quote/Guest/AddVirtualProductToCartTest.php | 6 +++--- .../GraphQl/Quote/Guest/CheckoutEndToEndTest.php | 4 ++-- .../Magento/GraphQl/Quote/Guest/GetCartTest.php | 6 +++--- .../GraphQl/Quote/Guest/RemoveItemFromCartTest.php | 4 ++-- .../Quote/Guest/SetPaymentMethodOnCartTest.php | 2 +- .../GraphQl/Quote/Guest/UpdateCartItemsTest.php | 10 +++++----- 22 files changed, 58 insertions(+), 58 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index d4780c5c0867a..bf4ff723a646f 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -49,7 +49,7 @@ type AddConfigurableProductsToCartOutput { } input ConfigurableProductCartItemInput { - data: CartItemInput! + data: CartItemQuantityInput! variant_sku: String! customizable_options:[CustomizableOptionInput!] } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index 6868ce3f7f1ff..ef9830bc75993 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -121,9 +121,9 @@ private function extractSku(array $cartItemData): string */ private function extractQty(array $cartItemData): float { - $qty = $this->arrayManager->get('data/qty', $cartItemData); + $qty = $this->arrayManager->get('data/quantity', $cartItemData); if (!isset($qty)) { - throw new GraphQlInputException(__('Missing key "qty" in cart item data')); + throw new GraphQlInputException(__('Missing key "quantity" in cart item data')); } return (float)$qty; } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php index da6619d15a489..f259dcd4a78ff 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php @@ -38,7 +38,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $itemsData[] = [ 'id' => $cartItem->getItemId(), - 'qty' => $cartItem->getQty(), + 'quantity' => $cartItem->getQty(), 'product' => $productData, 'model' => $cartItem, ]; diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index a9784e97c8952..5da3c57851e74 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -31,7 +31,7 @@ input AddSimpleProductsToCartInput { } input SimpleProductCartItemInput { - data: CartItemInput! + data: CartItemQuantityInput! customizable_options:[CustomizableOptionInput!] } @@ -41,13 +41,13 @@ input AddVirtualProductsToCartInput { } input VirtualProductCartItemInput { - data: CartItemInput! + data: CartItemQuantityInput! customizable_options:[CustomizableOptionInput!] } -input CartItemInput { +input CartItemQuantityInput { sku: String! - qty: Float! + quantity: Float! } input CustomizableOptionInput { @@ -62,10 +62,10 @@ input ApplyCouponToCartInput { input UpdateCartItemsInput { cart_id: String! - cart_items: [CartItemQuantityInput!]! + cart_items: [CartItemUpdateQuantityInput!]! } -input CartItemQuantityInput { +input CartItemUpdateQuantityInput { cart_item_id: Int! quantity: Float! } @@ -297,7 +297,7 @@ type VirtualCartItem implements CartItemInterface @doc(description: "Virtual Car interface CartItemInterface @typeResolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CartItemTypeResolver") { id: String! - qty: Float! + quantity: Float! product: ProductInterface! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 99f1dc004c50f..097e975130c70 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -97,7 +97,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty) : string cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" } } @@ -106,7 +106,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty) : string ) { cart { items { - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php index d22cd14a4ae26..fa45263e65548 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php @@ -44,7 +44,7 @@ public function testAddConfigurableProductToCart() $response = $this->graphQlMutation($query); $cartItems = $response['addConfigurableProductsToCart']['cart']['items']; - self::assertEquals($qty, $cartItems[0]['qty']); + self::assertEquals($qty, $cartItems[0]['quantity']); self::assertEquals($variantSku, $cartItems[0]['product']['sku']); } @@ -97,7 +97,7 @@ private function getQuery(string $maskedQuoteId, string $variantSku, int $qty): { variant_sku: "{$variantSku}" data: { - qty: {$qty} + quantity: {$qty} sku: "{$variantSku}" } } @@ -107,7 +107,7 @@ private function getQuery(string $maskedQuoteId, string $variantSku, int $qty): cart { items { id - qty + quantity product { name sku diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index f33ccce82fcb7..714447f1e36a5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -62,7 +62,7 @@ public function testAddSimpleProductWithOptions() cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" }, customizable_options: $queryCustomizableOptions @@ -121,7 +121,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index ffd52bcf7fb15..6172403c74086 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -62,7 +62,7 @@ public function testAddVirtualProductWithOptions() cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" }, customizable_options: $queryCustomizableOptions @@ -121,7 +121,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index 73b3e39721866..775d2733464ac 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -49,7 +49,7 @@ public function testAddSimpleProductToCart() $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -142,7 +142,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: {$qty} + quantity: {$qty} sku: "{$sku}" } } @@ -151,7 +151,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cart { items { id - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index 4ec25bb030079..86444f767ca78 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -49,7 +49,7 @@ public function testAddVirtualProductToCart() $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); - self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -142,7 +142,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: {$qty} + quantity: {$qty} sku: "{$sku}" } } @@ -151,7 +151,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cart { items { id - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index 8592a986c5dce..a67c199f244f3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -216,7 +216,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void cartItems: [ { data: { - qty: {$qty} + quantity: {$qty} sku: "{$sku}" } } @@ -225,7 +225,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void ) { cart { items { - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php index 19b72b9e3ca4c..0e60277948e0f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php @@ -54,11 +54,11 @@ public function testGetCart() self::assertCount(2, $response['cart']['items']); self::assertNotEmpty($response['cart']['items'][0]['id']); - self::assertEquals(2, $response['cart']['items'][0]['qty']); + self::assertEquals(2, $response['cart']['items'][0]['quantity']); self::assertEquals('simple_product', $response['cart']['items'][0]['product']['sku']); self::assertNotEmpty($response['cart']['items'][1]['id']); - self::assertEquals(2, $response['cart']['items'][1]['qty']); + self::assertEquals(2, $response['cart']['items'][1]['quantity']); self::assertEquals('virtual-product', $response['cart']['items'][1]['product']['sku']); } @@ -187,7 +187,7 @@ private function getQuery(string $maskedQuoteId): string cart(cart_id: "{$maskedQuoteId}") { items { id - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php index 39803f8d58447..5f953d43355fd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php @@ -107,7 +107,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string ) { cart { items { - qty + quantity } } } @@ -216,7 +216,7 @@ private function getQuery(string $maskedQuoteId, int $itemId): string ) { cart { items { - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 2604ec5f0a0f9..593bb8c9fcb78 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -196,7 +196,7 @@ public function testSetPaymentMethodWithoutRequiredParameters(string $input, str ) { cart { items { - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php index 35e2d62214fb2..5ab0213db6074 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php @@ -76,7 +76,7 @@ public function testUpdateCartItemQty() $item = current($responseCart['items']); $this->assertEquals($itemId, $item['id']); - $this->assertEquals($qty, $item['qty']); + $this->assertEquals($qty, $item['quantity']); } /** @@ -229,7 +229,7 @@ public function testUpdateWithMissedCartItemId() cart { items { id - qty + quantity } } } @@ -259,7 +259,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string cart { items { id - qty + quantity } } } @@ -285,7 +285,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_cart_item_qty' => [ 'cart_items: [{ cart_item_id: 1 }]', - 'Required parameter "quantity" for "cart_items" is missing.' + 'Field CartItemUpdateQuantityInput.quantity of required type Float! was not provided.' ], ]; } @@ -312,7 +312,7 @@ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): strin cart { items { id - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index 9e0693b160851..04c2daf755c1a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -44,7 +44,7 @@ public function testAddSimpleProductToCart() $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -115,7 +115,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" } } @@ -124,7 +124,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string ) { cart { items { - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index 3f2d734635c3e..def3306d4e822 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -44,7 +44,7 @@ public function testAddVirtualProductToCart() $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); - self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -116,7 +116,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: {$qty} + quantity: {$qty} sku: "{$sku}" } } @@ -125,7 +125,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string ) { cart { items { - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index f5114b9253a40..fc7bcdba86243 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -176,7 +176,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void cartItems: [ { data: { - qty: {$qty} + quantity: {$qty} sku: "{$sku}" } } @@ -185,7 +185,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void ) { cart { items { - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php index 832e15058a4ee..64170079676b9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php @@ -46,11 +46,11 @@ public function testGetCart() self::assertCount(2, $response['cart']['items']); self::assertNotEmpty($response['cart']['items'][0]['id']); - self::assertEquals(2, $response['cart']['items'][0]['qty']); + self::assertEquals(2, $response['cart']['items'][0]['quantity']); self::assertEquals('simple_product', $response['cart']['items'][0]['product']['sku']); self::assertNotEmpty($response['cart']['items'][1]['id']); - self::assertEquals(2, $response['cart']['items'][1]['qty']); + self::assertEquals(2, $response['cart']['items'][1]['quantity']); self::assertEquals('virtual-product', $response['cart']['items'][1]['product']['sku']); } @@ -156,7 +156,7 @@ private function getQuery(string $maskedQuoteId): string cart(cart_id: "{$maskedQuoteId}") { items { id - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php index 27f3f6367f662..77a057e52f686 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php @@ -96,7 +96,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string ) { cart { items { - qty + quantity } } } @@ -179,7 +179,7 @@ private function getQuery(string $maskedQuoteId, int $itemId): string ) { cart { items { - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php index 4ea7eac290f80..1b2ceecd213ab 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php @@ -164,7 +164,7 @@ public function testSetPaymentMethodWithoutRequiredParameters(string $input, str ) { cart { items { - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php index 1b8cf2e1c57f7..0d03b49125ce3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php @@ -69,7 +69,7 @@ public function testUpdateCartItemQty() $item = current($responseCart['items']); $this->assertEquals($itemId, $item['id']); - $this->assertEquals($qty, $item['qty']); + $this->assertEquals($qty, $item['quantity']); } /** @@ -180,7 +180,7 @@ public function testUpdateWithMissedCartItemId() cart { items { id - qty + quantity } } } @@ -210,7 +210,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string cart { items { id - qty + quantity } } } @@ -236,7 +236,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_cart_item_qty' => [ 'cart_items: [{ cart_item_id: 1 }]', - 'Required parameter "quantity" for "cart_items" is missing.' + 'Field CartItemUpdateQuantityInput.quantity of required type Float! was not provided.' ], ]; } @@ -263,7 +263,7 @@ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): strin cart { items { id - qty + quantity } } } From 33c322ba0f05fc1f3258d95ed1a8a746e6dbca0b Mon Sep 17 00:00:00 2001 From: Oscar Recio <osrecio@gmail.com> Date: Mon, 29 Apr 2019 12:07:10 +0200 Subject: [PATCH 544/585] #628 Check if email or password are empty --- .../Model/Resolver/GenerateCustomerToken.php | 4 +- .../Customer/GenerateCustomerTokenTest.php | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php index 1bd77fe1cde8f..2a7cb8a734a50 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php @@ -44,11 +44,11 @@ public function resolve( array $value = null, array $args = null ) { - if (!isset($args['email'])) { + if (!isset($args['email']) || empty($args['email'])) { throw new GraphQlInputException(__('Specify the "email" value.')); } - if (!isset($args['password'])) { + if (!isset($args['password']) || empty($args['password'])) { throw new GraphQlInputException(__('Specify the "password" value.')); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php index 88eaeaa8f9dd5..e13c1974e3067 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php @@ -68,4 +68,54 @@ public function testGenerateCustomerTokenWithInvalidCredentials() 'was incorrect or your account is disabled temporarily. Please wait and try again later.'); $this->graphQlMutation($mutation); } + + /** + * Verify customer with empty email + */ + public function testGenerateCustomerTokenWithEmptyEmail() + { + $email = ''; + $password = 'bad-password'; + + $mutation + = <<<MUTATION +mutation { + generateCustomerToken( + email: "{$email}" + password: "{$password}" + ) { + token + } +} +MUTATION; + + $this->expectException(\Exception::class); + $this->expectExceptionMessage('GraphQL response contains errors: Specify the "email" value.'); + $this->graphQlMutation($mutation); + } + + /** + * Verify customer with empty password + */ + public function testGenerateCustomerTokenWithEmptyPassword() + { + $email = 'customer@example.com'; + $password = ''; + + $mutation + = <<<MUTATION +mutation { + generateCustomerToken( + email: "{$email}" + password: "{$password}" + ) { + token + } +} +MUTATION; + + $this->expectException(\Exception::class); + $this->expectExceptionMessage('GraphQL response contains errors: Specify the "password" value.'); + $this->graphQlMutation($mutation); + } } From f52ad9a9f3e1651092e85e6d2394f1142522de64 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 10:10:47 -0500 Subject: [PATCH 545/585] =?UTF-8?q?GraphQL-608:=20Remove=20=E2=80=9Ccart?= =?UTF-8?q?=5Faddress=5Fid=E2=80=9D=20from=20=E2=80=9CShippingMethodInput?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup/performance-toolkit/benchmark.jmx | 28 ++++++++----------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 22af21f07abc5..00982dbc619bd 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -40986,7 +40986,7 @@ vars.putObject("randomIntGenerator", random); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41010,7 +41010,7 @@ vars.putObject("randomIntGenerator", random); <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1671866339">{"data":{"setShippingAddressesOnCart":{"cart":{"shipping_addresses":[{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"SHIPPING"}]}}}}</stringProp> + <stringProp name="-1671866339">{"data":{"setShippingAddressesOnCart":{"cart":{"shipping_addresses":[{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"}}]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -41176,7 +41176,7 @@ vars.putObject("randomIntGenerator", random); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41200,7 +41200,7 @@ vars.putObject("randomIntGenerator", random); <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"BILLING"}}}}}</stringProp> + <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"}}}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -44059,7 +44059,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -44083,7 +44083,7 @@ vars.put("product_sku", product.get("sku")); <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"BILLING"}}}}}</stringProp> + <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"}}}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -44098,7 +44098,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -44122,7 +44122,7 @@ vars.put("product_sku", product.get("sku")); <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1671866339">{"data":{"setShippingAddressesOnCart":{"cart":{"shipping_addresses":[{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"SHIPPING"}]}}}}</stringProp> + <stringProp name="-1671866339">{"data":{"setShippingAddressesOnCart":{"cart":{"shipping_addresses":[{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"}}]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -44176,7 +44176,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n shipping_addresses {\n address_id\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n shipping_addresses {\n postcode\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -44197,16 +44197,6 @@ vars.put("product_sku", product.get("sku")); <stringProp name="HTTPSampler.embedded_url_re"/> <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_current_shipping_address.jmx</stringProp> </HTTPSamplerProxy> - <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">address_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.shipping_addresses[0].address_id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - </hashTree> <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Shipping Method On Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> From e04f566bc9574a3aea93615e05b2ccd0d2b7b50b Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 10:26:56 -0500 Subject: [PATCH 546/585] =?UTF-8?q?GraphQL-608:=20Remove=20=E2=80=9Ccart?= =?UTF-8?q?=5Faddress=5Fid=E2=80=9D=20from=20=E2=80=9CShippingMethodInput?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup/performance-toolkit/benchmark.jmx | 1 + 1 file changed, 1 insertion(+) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 00982dbc619bd..384832532ae00 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -44197,6 +44197,7 @@ vars.put("product_sku", product.get("sku")); <stringProp name="HTTPSampler.embedded_url_re"/> <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_current_shipping_address.jmx</stringProp> </HTTPSamplerProxy> + <hashTree/> <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Shipping Method On Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> From 5899e77a318994cbbc01ece2dd0073d243f4fa66 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 11:39:30 -0500 Subject: [PATCH 547/585] GraphQL-530: [Cart Operations] Update Cart Items validation messages --- .../Magento/GraphQl/CatalogInventory/AddProductToCartTest.php | 2 +- .../Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index df93fea7d9009..a97d30fef803f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -94,7 +94,7 @@ public function testAddProductIfQuantityIsDecimal() $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->expectExceptionMessage( - "Could not add the product with SKU {$sku} to the shopping cart: The fewest you may purchase is 1." + "Could not add the product with SKU {$sku} to the shopping cart: The fewest you may purchase is 1" ); $this->graphQlMutation($query); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php index 27ec288204048..b13277136fadb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php @@ -48,7 +48,7 @@ public function testUpdateCartItemDecimalQty() $qty = 0.5; $this->expectExceptionMessage( - "Could not update the product with SKU simple_product: The fewest you may purchase is 1." + "Could not update the product with SKU simple_product: The fewest you may purchase is 1" ); $query = $this->getQuery($maskedQuoteId, $itemId, $qty); $this->graphQlMutation($query); From 035f60268d0a85594ce578eb41fb47225c45018f Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 12:06:51 -0500 Subject: [PATCH 548/585] GraphQL-631: Schema inconsistency of "Quantity / Qty" declaration --- .../etc/schema.graphqls | 2 +- .../Model/Cart/AddSimpleProductToCart.php | 22 ++++++++--------- .../Model/Resolver/UpdateCartItems.php | 6 ++--- .../Magento/QuoteGraphQl/etc/schema.graphqls | 10 ++++---- .../CatalogInventory/AddProductToCartTest.php | 8 +++---- .../AddConfigurableProductToCartTest.php | 20 ++++++++-------- ...mpleProductWithCustomOptionsToCartTest.php | 8 +++---- ...tualProductWithCustomOptionsToCartTest.php | 8 +++---- .../Customer/AddSimpleProductToCartTest.php | 16 ++++++------- .../Customer/AddVirtualProductToCartTest.php | 12 +++++----- .../Quote/Customer/CheckoutEndToEndTest.php | 4 ++-- .../Quote/Customer/UpdateCartItemsTest.php | 18 +++++++------- .../Guest/AddSimpleProductToCartTest.php | 24 +++++++++---------- .../Guest/AddVirtualProductToCartTest.php | 24 +++++++++---------- .../Quote/Guest/CheckoutEndToEndTest.php | 10 ++++---- .../Quote/Guest/UpdateCartItemsTest.php | 18 +++++++------- 16 files changed, 105 insertions(+), 105 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index bf4ff723a646f..d4780c5c0867a 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -49,7 +49,7 @@ type AddConfigurableProductsToCartOutput { } input ConfigurableProductCartItemInput { - data: CartItemQuantityInput! + data: CartItemInput! variant_sku: String! customizable_options:[CustomizableOptionInput!] } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index ef9830bc75993..ad730288e5cc2 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -66,8 +66,8 @@ public function __construct( public function execute(Quote $cart, array $cartItemData): void { $sku = $this->extractSku($cartItemData); - $qty = $this->extractQty($cartItemData); - if ($qty <= 0) { + $quantity = $this->extractQuantity($cartItemData); + if ($quantity <= 0) { throw new GraphQlInputException( __('Please enter a number greater than 0 in this field.') ); @@ -81,7 +81,7 @@ public function execute(Quote $cart, array $cartItemData): void } try { - $result = $cart->addProduct($product, $this->createBuyRequest($qty, $customizableOptions)); + $result = $cart->addProduct($product, $this->createBuyRequest($quantity, $customizableOptions)); } catch (\Exception $e) { throw new GraphQlInputException( __( @@ -113,19 +113,19 @@ private function extractSku(array $cartItemData): string } /** - * Extract Qty from cart item data + * Extract quantity from cart item data * * @param array $cartItemData * @return float * @throws GraphQlInputException */ - private function extractQty(array $cartItemData): float + private function extractQuantity(array $cartItemData): float { - $qty = $this->arrayManager->get('data/quantity', $cartItemData); - if (!isset($qty)) { + $quantity = $this->arrayManager->get('data/quantity', $cartItemData); + if (!isset($quantity)) { throw new GraphQlInputException(__('Missing key "quantity" in cart item data')); } - return (float)$qty; + return (float)$quantity; } /** @@ -148,15 +148,15 @@ private function extractCustomizableOptions(array $cartItemData): array /** * Format GraphQl input data to a shape that buy request has * - * @param float $qty + * @param float $quantity * @param array $customOptions * @return DataObject */ - private function createBuyRequest(float $qty, array $customOptions): DataObject + private function createBuyRequest(float $quantity, array $customOptions): DataObject { return $this->dataObjectFactory->create([ 'data' => [ - 'qty' => $qty, + 'qty' => $quantity, 'options' => $customOptions, ], ]); diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php index 78a07506556c0..59ca5a3f17fbf 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -98,7 +98,7 @@ private function processCartItems(Quote $cart, array $items): void if (!isset($item['quantity'])) { throw new GraphQlInputException(__('Required parameter "quantity" for "cart_items" is missing.')); } - $qty = (float)$item['quantity']; + $quantity = (float)$item['quantity']; $cartItem = $cart->getItemById($itemId); if ($cartItem === false) { @@ -107,10 +107,10 @@ private function processCartItems(Quote $cart, array $items): void ); } - if ($qty <= 0.0) { + if ($quantity <= 0.0) { $this->cartItemRepository->deleteById((int)$cart->getId(), $itemId); } else { - $cartItem->setQty($qty); + $cartItem->setQty($quantity); $this->cartItemRepository->save($cartItem); } } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 5da3c57851e74..d805bb32958de 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -31,7 +31,7 @@ input AddSimpleProductsToCartInput { } input SimpleProductCartItemInput { - data: CartItemQuantityInput! + data: CartItemInput! customizable_options:[CustomizableOptionInput!] } @@ -41,11 +41,11 @@ input AddVirtualProductsToCartInput { } input VirtualProductCartItemInput { - data: CartItemQuantityInput! + data: CartItemInput! customizable_options:[CustomizableOptionInput!] } -input CartItemQuantityInput { +input CartItemInput { sku: String! quantity: Float! } @@ -62,10 +62,10 @@ input ApplyCouponToCartInput { input UpdateCartItemsInput { cart_id: String! - cart_items: [CartItemUpdateQuantityInput!]! + cart_items: [CartItemUpdateInput!]! } -input CartItemUpdateQuantityInput { +input CartItemUpdateInput { cart_item_id: Int! quantity: Float! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 097e975130c70..91b55903174d7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -39,10 +39,10 @@ protected function setUp() public function testAddProductIfQuantityIsNotAvailable() { $sku = 'simple'; - $qty = 200; + $quantity = 200; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -58,10 +58,10 @@ public function testAddMoreProductsThatAllowed() $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/167'); $sku = 'custom-design-simple-product'; - $qty = 7; + $quantity = 7; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php index fa45263e65548..6810f9d44ce91 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php @@ -37,14 +37,14 @@ protected function setUp() public function testAddConfigurableProductToCart() { $variantSku = 'simple_41'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); + $query = $this->getQuery($maskedQuoteId, $variantSku, $quantity); $response = $this->graphQlMutation($query); $cartItems = $response['addConfigurableProductsToCart']['cart']['items']; - self::assertEquals($qty, $cartItems[0]['quantity']); + self::assertEquals($quantity, $cartItems[0]['quantity']); self::assertEquals($variantSku, $cartItems[0]['product']['sku']); } @@ -57,10 +57,10 @@ public function testAddConfigurableProductToCart() public function testAddProductIfQuantityIsNotAvailable() { $variantSku = 'simple_41'; - $qty = 200; + $quantity = 200; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); + $query = $this->getQuery($maskedQuoteId, $variantSku, $quantity); $this->graphQlMutation($query); } @@ -73,20 +73,20 @@ public function testAddProductIfQuantityIsNotAvailable() public function testAddOutOfStockProduct() { $variantSku = 'simple_1010'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); + $query = $this->getQuery($maskedQuoteId, $variantSku, $quantity); $this->graphQlMutation($query); } /** * @param string $maskedQuoteId * @param string $variantSku - * @param int $qty + * @param int $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $variantSku, int $qty): string + private function getQuery(string $maskedQuoteId, string $variantSku, int $quantity): string { return <<<QUERY mutation { @@ -97,7 +97,7 @@ private function getQuery(string $maskedQuoteId, string $variantSku, int $qty): { variant_sku: "{$variantSku}" data: { - quantity: {$qty} + quantity: {$quantity} sku: "{$variantSku}" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index 714447f1e36a5..63546298304b0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -46,7 +46,7 @@ protected function setUp() public function testAddSimpleProductWithOptions() { $sku = 'simple'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); @@ -62,7 +62,7 @@ public function testAddSimpleProductWithOptions() cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" }, customizable_options: $queryCustomizableOptions @@ -110,7 +110,7 @@ public function testAddSimpleProductWithOptions() public function testAddSimpleProductWithNoRequiredOptionsSet() { $sku = 'simple'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = <<<QUERY @@ -121,7 +121,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index 6172403c74086..94ac11ad8e0b1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -46,7 +46,7 @@ protected function setUp() public function testAddVirtualProductWithOptions() { $sku = 'virtual'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); @@ -62,7 +62,7 @@ public function testAddVirtualProductWithOptions() cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" }, customizable_options: $queryCustomizableOptions @@ -110,7 +110,7 @@ public function testAddVirtualProductWithOptions() public function testAddVirtualProductWithNoRequiredOptionsSet() { $sku = 'virtual'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = <<<QUERY @@ -121,7 +121,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index 775d2733464ac..be22d860df122 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -43,13 +43,13 @@ protected function setUp() public function testAddSimpleProductToCart() { $sku = 'simple_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); + self::assertEquals($quantity, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -63,10 +63,10 @@ public function testAddSimpleProductToCart() public function testAddProductToNonExistentCart() { $sku = 'simple_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } @@ -130,10 +130,10 @@ public function testAddSimpleProductToAnotherCustomerCart() /** * @param string $maskedQuoteId * @param string $sku - * @param int $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + private function getQuery(string $maskedQuoteId, string $sku, float $quantity): string { return <<<QUERY mutation { @@ -142,7 +142,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - quantity: {$qty} + quantity: {$quantity} sku: "{$sku}" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index 86444f767ca78..1269b9d8e7b3d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -43,13 +43,13 @@ protected function setUp() public function testAddVirtualProductToCart() { $sku = 'virtual_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); - self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); + self::assertEquals($quantity, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -130,10 +130,10 @@ public function testAddVirtualProductToAnotherCustomerCart() /** * @param string $maskedQuoteId * @param string $sku - * @param int $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + private function getQuery(string $maskedQuoteId, string $sku, float $quantity): string { return <<<QUERY mutation { @@ -142,7 +142,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - quantity: {$qty} + quantity: {$quantity} sku: "{$sku}" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index a67c199f244f3..b1af14c982ab6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -81,7 +81,7 @@ protected function setUp() */ public function testCheckoutWorkflow() { - $qty = 2; + $quantity = 2; $this->createCustomer(); $token = $this->loginCustomer(); @@ -89,7 +89,7 @@ public function testCheckoutWorkflow() $sku = $this->findProduct(); $cartId = $this->createEmptyCart(); - $this->addProductToCart($cartId, $qty, $sku); + $this->addProductToCart($cartId, $quantity, $sku); $this->setBillingAddress($cartId); $shippingAddress = $this->setShippingAddress($cartId); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php index 5ab0213db6074..f0539084ec5b2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php @@ -58,15 +58,15 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php */ - public function testUpdateCartItemQty() + public function testUpdateCartItemQuantity() { $quote = $this->quoteFactory->create(); $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); - $qty = 2; + $quantity = 2; - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $query = $this->getQuery($maskedQuoteId, $itemId, $quantity); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); $this->assertArrayHasKey('updateCartItems', $response); @@ -76,7 +76,7 @@ public function testUpdateCartItemQty() $item = current($responseCart['items']); $this->assertEquals($itemId, $item['id']); - $this->assertEquals($qty, $item['quantity']); + $this->assertEquals($quantity, $item['quantity']); } /** @@ -88,9 +88,9 @@ public function testRemoveCartItemIfQuantityIsZero() $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); - $qty = 0; + $quantity = 0; - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $query = $this->getQuery($maskedQuoteId, $itemId, $quantity); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); $this->assertArrayHasKey('updateCartItems', $response); @@ -293,10 +293,10 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array /** * @param string $maskedQuoteId * @param int $itemId - * @param float $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, int $itemId, float $qty): string + private function getQuery(string $maskedQuoteId, int $itemId, float $quantity): string { return <<<QUERY mutation { @@ -305,7 +305,7 @@ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): strin cart_items:[ { cart_item_id: {$itemId} - quantity: {$qty} + quantity: {$quantity} } ] }) { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index 04c2daf755c1a..8b20320fc2f02 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -37,14 +37,14 @@ protected function setUp() public function testAddSimpleProductToCart() { $sku = 'simple_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); + self::assertEquals($quantity, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -57,10 +57,10 @@ public function testAddSimpleProductToCart() public function testAddProductToNonExistentCart() { $sku = 'simple_product'; - $qty = 1; + $quantity = 1; $maskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -73,10 +73,10 @@ public function testAddProductToNonExistentCart() public function testNonExistentProductToCart() { $sku = 'simple_product'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -88,9 +88,9 @@ public function testNonExistentProductToCart() public function testAddSimpleProductToCustomerCart() { $sku = 'simple_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" @@ -102,10 +102,10 @@ public function testAddSimpleProductToCustomerCart() /** * @param string $maskedQuoteId * @param string $sku - * @param int $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + private function getQuery(string $maskedQuoteId, string $sku, float $quantity): string { return <<<QUERY mutation { @@ -115,7 +115,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index def3306d4e822..cb429e7b9cb9e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -37,14 +37,14 @@ protected function setUp() public function testAddVirtualProductToCart() { $sku = 'virtual_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); - self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); + self::assertEquals($quantity, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -57,10 +57,10 @@ public function testAddVirtualProductToCart() public function testAddVirtualToNonExistentCart() { $sku = 'virtual_product'; - $qty = 1; + $quantity = 1; $maskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -73,10 +73,10 @@ public function testAddVirtualToNonExistentCart() public function testNonExistentProductToCart() { $sku = 'virtual_product'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -89,9 +89,9 @@ public function testNonExistentProductToCart() public function testAddVirtualProductToCustomerCart() { $sku = 'virtual_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" @@ -103,10 +103,10 @@ public function testAddVirtualProductToCustomerCart() /** * @param string $maskedQuoteId * @param string $sku - * @param int $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + private function getQuery(string $maskedQuoteId, string $sku, float $quantity): string { return <<<QUERY mutation { @@ -116,7 +116,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - quantity: {$qty} + quantity: {$quantity} sku: "{$sku}" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index fc7bcdba86243..7245996df3288 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -69,12 +69,12 @@ protected function setUp() */ public function testCheckoutWorkflow() { - $qty = 2; + $quantity = 2; $sku = $this->findProduct(); $cartId = $this->createEmptyCart(); $this->setGuestEmailOnCart($cartId); - $this->addProductToCart($cartId, $qty, $sku); + $this->addProductToCart($cartId, $quantity, $sku); $this->setBillingAddress($cartId); $shippingAddress = $this->setShippingAddress($cartId); @@ -162,11 +162,11 @@ private function setGuestEmailOnCart(string $cartId): void /** * @param string $cartId - * @param float $qty + * @param float $quantity * @param string $sku * @return void */ - private function addProductToCart(string $cartId, float $qty, string $sku): void + private function addProductToCart(string $cartId, float $quantity, string $sku): void { $query = <<<QUERY mutation { @@ -176,7 +176,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void cartItems: [ { data: { - quantity: {$qty} + quantity: {$quantity} sku: "{$sku}" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php index 0d03b49125ce3..539dcaea2aaa6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php @@ -51,15 +51,15 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php */ - public function testUpdateCartItemQty() + public function testUpdateCartItemQuantity() { $quote = $this->quoteFactory->create(); $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); - $qty = 2; + $quantity = 2; - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $query = $this->getQuery($maskedQuoteId, $itemId, $quantity); $response = $this->graphQlMutation($query); $this->assertArrayHasKey('updateCartItems', $response); @@ -69,7 +69,7 @@ public function testUpdateCartItemQty() $item = current($responseCart['items']); $this->assertEquals($itemId, $item['id']); - $this->assertEquals($qty, $item['quantity']); + $this->assertEquals($quantity, $item['quantity']); } /** @@ -81,9 +81,9 @@ public function testRemoveCartItemIfQuantityIsZero() $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); - $qty = 0; + $quantity = 0; - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $query = $this->getQuery($maskedQuoteId, $itemId, $quantity); $response = $this->graphQlMutation($query); $this->assertArrayHasKey('updateCartItems', $response); @@ -244,10 +244,10 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array /** * @param string $maskedQuoteId * @param int $itemId - * @param float $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, int $itemId, float $qty): string + private function getQuery(string $maskedQuoteId, int $itemId, float $quantity): string { return <<<QUERY mutation { @@ -256,7 +256,7 @@ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): strin cart_items: [ { cart_item_id: {$itemId} - quantity: {$qty} + quantity: {$quantity} } ] }) { From 604e22389830707a5f3af4fbdcf17391dd5548be Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 13:43:49 -0500 Subject: [PATCH 549/585] GraphQL-621: BillingAddress and ShippingAddress should have different fields but share the common interface --- .../Model/Cart/ExtractQuoteAddressData.php | 9 ----- .../Resolver/CartAddressTypeResolver.php | 40 +++++++++++++++++++ .../Magento/QuoteGraphQl/etc/schema.graphqls | 20 +++++----- .../Quote/Customer/CheckoutEndToEndTest.php | 2 +- .../GetSpecifiedBillingAddressTest.php | 6 +-- .../Customer/SetBillingAddressOnCartTest.php | 12 +++--- .../Customer/SetShippingAddressOnCartTest.php | 4 +- .../Quote/Guest/CheckoutEndToEndTest.php | 2 +- .../Guest/GetSpecifiedBillingAddressTest.php | 6 +-- .../Guest/SetBillingAddressOnCartTest.php | 12 +++--- .../Guest/SetShippingAddressOnCartTest.php | 4 +- 11 files changed, 74 insertions(+), 43 deletions(-) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php index 4d832f603cd91..c4d795293220f 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php @@ -41,16 +41,7 @@ public function execute(QuoteAddress $address): array $addressData = $this->dataObjectConverter->toFlatArray($address, [], AddressInterface::class); $addressData['model'] = $address; - if ($address->getAddressType() == AbstractAddress::TYPE_SHIPPING) { - $addressType = 'SHIPPING'; - } elseif ($address->getAddressType() == AbstractAddress::TYPE_BILLING) { - $addressType = 'BILLING'; - } else { - $addressType = null; - } - $addressData = array_merge($addressData, [ - 'address_type' => $addressType, 'country' => [ 'code' => $address->getCountryId(), 'label' => $address->getCountry() diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php new file mode 100644 index 0000000000000..14c1dc76590a4 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Model\Resolver; + +use Magento\Customer\Model\Address\AbstractAddress; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\GraphQl\Query\Resolver\TypeResolverInterface; +use Magento\Quote\Model\Quote\Address; + +/** + * @inheritdoc + */ +class CartAddressTypeResolver implements TypeResolverInterface +{ + /** + * @inheritdoc + */ + public function resolveType(array $data) : string + { + if (!isset($data['model'])) { + throw new LocalizedException(__('Missing key "model" in cart address data')); + } + /** @var Address $address */ + $address = $data['model']; + + if ($address->getAddressType() == AbstractAddress::TYPE_SHIPPING) { + $addressType = 'ShippingCartAddress'; + } elseif ($address->getAddressType() == AbstractAddress::TYPE_BILLING) { + $addressType = 'BillingCartAddress'; + } else { + throw new LocalizedException( __('Unsupported cart address type')); + } + return $addressType; + } +} diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 6d94685ac4d0f..dd32753bba9ca 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -183,14 +183,14 @@ type Cart { items: [CartItemInterface] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartItems") applied_coupon: AppliedCoupon @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\AppliedCoupon") email: String @resolver (class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartEmail") - shipping_addresses: [CartAddress]! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddresses") - billing_address: CartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress") + shipping_addresses: [ShippingCartAddress]! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddresses") + billing_address: BillingCartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress") available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") selected_payment_method: SelectedPaymentMethod @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SelectedPaymentMethod") prices: CartPrices @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartPrices") } -type CartAddress { +interface CartAddressInterface @typeResolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartAddressTypeResolver") { firstname: String lastname: String company: String @@ -200,14 +200,19 @@ type CartAddress { postcode: String country: CartAddressCountry telephone: String - address_type: AdressTypeEnum + customer_notes: String +} + +type ShippingCartAddress implements CartAddressInterface { available_shipping_methods: [AvailableShippingMethod] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddress\\AvailableShippingMethods") selected_shipping_method: SelectedShippingMethod @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddress\\SelectedShippingMethod") items_weight: Float - customer_notes: String cart_items: [CartItemQuantity] } +type BillingCartAddress implements CartAddressInterface { +} + type CartItemQuantity { cart_item_id: Int! quantity: Float! @@ -257,11 +262,6 @@ type SelectedPaymentMethod { type SelectedPaymentMethodAdditionalData { } -enum AdressTypeEnum { - SHIPPING - BILLING -} - type AppliedCoupon { code: String! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index a49b84e20a8a6..b5095bfabf0db 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -266,7 +266,7 @@ private function setBillingAddress(string $cartId): void ) { cart { billing_address { - address_type + __typename } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php index 1ba94346073db..e10d12d73e7a6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php @@ -71,7 +71,7 @@ public function testGeSpecifiedBillingAddress() 'label' => 'US', ], 'telephone' => '3468676', - 'address_type' => 'BILLING', + '__typename' => 'BillingCartAddress', 'customer_notes' => null, ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); @@ -110,7 +110,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() 'label' => null, ], 'telephone' => null, - 'address_type' => 'BILLING', + '__typename' => null, 'customer_notes' => null, ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); @@ -197,7 +197,7 @@ private function getQuery(string $maskedQuoteId): string label } telephone - address_type + __typename customer_notes } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php index 6b15f947a2477..fc73d88be1f87 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php @@ -99,7 +99,7 @@ public function testSetNewBillingAddress() code label } - address_type + __typename } } } @@ -159,7 +159,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() code label } - address_type + __typename } shipping_addresses { firstname @@ -173,7 +173,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() code label } - address_type + __typename } } } @@ -188,7 +188,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() self::assertArrayHasKey('shipping_addresses', $cartResponse); $shippingAddressResponse = current($cartResponse['shipping_addresses']); $this->assertNewAddressFields($billingAddressResponse); - $this->assertNewAddressFields($shippingAddressResponse, 'SHIPPING'); + $this->assertNewAddressFields($shippingAddressResponse, 'ShippingCartAddress'); } /** @@ -560,7 +560,7 @@ public function testSetNewBillingAddressWithRedundantStreetLine() * @param array $addressResponse * @param string $addressType */ - private function assertNewAddressFields(array $addressResponse, string $addressType = 'BILLING'): void + private function assertNewAddressFields(array $addressResponse, string $addressType = 'BillingCartAddress'): void { $assertionMap = [ ['response_field' => 'firstname', 'expected_value' => 'test firstname'], @@ -571,7 +571,7 @@ private function assertNewAddressFields(array $addressResponse, string $addressT ['response_field' => 'postcode', 'expected_value' => '887766'], ['response_field' => 'telephone', 'expected_value' => '88776655'], ['response_field' => 'country', 'expected_value' => ['code' => 'US', 'label' => 'US']], - ['response_field' => 'address_type', 'expected_value' => $addressType] + ['response_field' => '__typename', 'expected_value' => $addressType] ]; $this->assertResponseFields($addressResponse, $assertionMap); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php index 6b097e028ffe5..5d7a073d2d6d5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php @@ -101,7 +101,7 @@ public function testSetNewShippingAddressOnCartWithSimpleProduct() label code } - address_type + __typename } } } @@ -548,7 +548,7 @@ private function assertNewShippingAddressFields(array $shippingAddressResponse): ['response_field' => 'postcode', 'expected_value' => '887766'], ['response_field' => 'telephone', 'expected_value' => '88776655'], ['response_field' => 'country', 'expected_value' => ['code' => 'US', 'label' => 'US']], - ['response_field' => 'address_type', 'expected_value' => 'SHIPPING'] + ['response_field' => '__typename', 'expected_value' => 'ShippingCartAddress'] ]; $this->assertResponseFields($shippingAddressResponse, $assertionMap); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index 7cd4e06a19e23..570c34d448073 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -226,7 +226,7 @@ private function setBillingAddress(string $cartId): void ) { cart { billing_address { - address_type + __typename } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php index d592443aed499..48bff73226894 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php @@ -63,7 +63,7 @@ public function testGeSpecifiedBillingAddress() 'label' => 'US', ], 'telephone' => '3468676', - 'address_type' => 'BILLING', + '__typename' => 'BillingCartAddress', ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); } @@ -100,7 +100,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() 'label' => null, ], 'telephone' => null, - 'address_type' => 'BILLING', + '__typename' => 'BillingCartAddress', ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); } @@ -161,7 +161,7 @@ private function getQuery(string $maskedQuoteId): string label } telephone - address_type + __typename } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php index d2d53220f0042..d8d95040eea45 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php @@ -70,7 +70,7 @@ public function testSetNewBillingAddress() code label } - address_type + __typename } } } @@ -129,7 +129,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() code label } - address_type + __typename } shipping_addresses { firstname @@ -143,7 +143,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() code label } - address_type + __typename } } } @@ -158,7 +158,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() self::assertArrayHasKey('shipping_addresses', $cartResponse); $shippingAddressResponse = current($cartResponse['shipping_addresses']); $this->assertNewAddressFields($billingAddressResponse); - $this->assertNewAddressFields($shippingAddressResponse, 'SHIPPING'); + $this->assertNewAddressFields($shippingAddressResponse, 'ShippingCartAddress'); } /** @@ -380,7 +380,7 @@ public function testSetNewBillingAddressRedundantStreetLine() * @param array $addressResponse * @param string $addressType */ - private function assertNewAddressFields(array $addressResponse, string $addressType = 'BILLING'): void + private function assertNewAddressFields(array $addressResponse, string $addressType = 'BillingCartAddress'): void { $assertionMap = [ ['response_field' => 'firstname', 'expected_value' => 'test firstname'], @@ -391,7 +391,7 @@ private function assertNewAddressFields(array $addressResponse, string $addressT ['response_field' => 'postcode', 'expected_value' => '887766'], ['response_field' => 'telephone', 'expected_value' => '88776655'], ['response_field' => 'country', 'expected_value' => ['code' => 'US', 'label' => 'US']], - ['response_field' => 'address_type', 'expected_value' => $addressType] + ['response_field' => '__typename', 'expected_value' => $addressType] ]; $this->assertResponseFields($addressResponse, $assertionMap); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php index 888b0e87734b6..c58098c6c2547 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php @@ -72,7 +72,7 @@ public function testSetNewShippingAddressOnCartWithSimpleProduct() code label } - address_type + __typename } } } @@ -383,7 +383,7 @@ private function assertNewShippingAddressFields(array $shippingAddressResponse): ['response_field' => 'postcode', 'expected_value' => '887766'], ['response_field' => 'telephone', 'expected_value' => '88776655'], ['response_field' => 'country', 'expected_value' => ['code' => 'US', 'label' => 'US']], - ['response_field' => 'address_type', 'expected_value' => 'SHIPPING'] + ['response_field' => '__typename', 'expected_value' => 'ShippingCartAddress'] ]; $this->assertResponseFields($shippingAddressResponse, $assertionMap); From 63a740b04d223f96f148e4e1a16c892eeb2ea7a0 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 13:53:34 -0500 Subject: [PATCH 550/585] GraphQL-631: Schema inconsistency of "Quantity / Qty" declaration --- .../Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php | 2 +- .../Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php index f0539084ec5b2..bc88bd1ddb438 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php @@ -285,7 +285,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_cart_item_qty' => [ 'cart_items: [{ cart_item_id: 1 }]', - 'Field CartItemUpdateQuantityInput.quantity of required type Float! was not provided.' + 'Field CartItemUpdateInput.quantity of required type Float! was not provided.' ], ]; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php index 539dcaea2aaa6..1e1fb0a176992 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php @@ -236,7 +236,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_cart_item_qty' => [ 'cart_items: [{ cart_item_id: 1 }]', - 'Field CartItemUpdateQuantityInput.quantity of required type Float! was not provided.' + 'Field CartItemUpdateInput.quantity of required type Float! was not provided.' ], ]; } From 5766e1430b4243e984afb5bf6d079eb5c1f2656a Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 14:38:01 -0500 Subject: [PATCH 551/585] GraphQL-601: [Test Coverage] Offline payments methods --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 3250e94761b12..6039a82357d36 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -191,7 +191,6 @@ type Cart { } type CartAddress { - address_id: Int firstname: String lastname: String company: String From 109182ede4519f2b81f1bce2b1f28600620077a0 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 14:49:10 -0500 Subject: [PATCH 552/585] GraphQL-631: Schema inconsistency of "Quantity / Qty" declaration --- setup/performance-toolkit/benchmark.jmx | 52 ++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 384832532ae00..c1d21a08f9e2d 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -40796,7 +40796,7 @@ vars.putObject("randomIntGenerator", random); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -40947,7 +40947,7 @@ vars.putObject("randomIntGenerator", random); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41137,7 +41137,7 @@ vars.putObject("randomIntGenerator", random); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41347,7 +41347,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41567,7 +41567,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41739,7 +41739,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41779,7 +41779,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41820,13 +41820,13 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product quantity In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n quantity\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41850,7 +41850,7 @@ vars.put("product_sku", product.get("sku")); <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","quantity":5}]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -42045,7 +42045,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42085,7 +42085,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42126,13 +42126,13 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product quantity In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n quantity\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42156,7 +42156,7 @@ vars.put("product_sku", product.get("sku")); <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","quantity":5}]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -42303,7 +42303,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42343,7 +42343,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42390,7 +42390,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n quantity\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42609,7 +42609,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42649,7 +42649,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42696,7 +42696,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n quantity\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42867,7 +42867,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43094,7 +43094,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43852,7 +43852,7 @@ vars.putObject("randomIntGenerator", random); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43959,7 +43959,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -44019,7 +44019,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> From c44df1ce0d64de8ec774278eebcffe58f43991af Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 15:12:53 -0500 Subject: [PATCH 553/585] GraphQL-631: Schema inconsistency of "Quantity / Qty" declaration --- .../Model/Resolver/CartAddressTypeResolver.php | 4 ++-- .../CatalogInventory/AddProductToCartTest.php | 16 ++++++++-------- .../CatalogInventory/UpdateCartItemsTest.php | 14 +++++++------- .../Guest/GetSpecifiedBillingAddressTest.php | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php index 14c1dc76590a4..6f7c70b09cb0c 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php @@ -20,7 +20,7 @@ class CartAddressTypeResolver implements TypeResolverInterface /** * @inheritdoc */ - public function resolveType(array $data) : string + public function resolveType(array $data): string { if (!isset($data['model'])) { throw new LocalizedException(__('Missing key "model" in cart address data')); @@ -33,7 +33,7 @@ public function resolveType(array $data) : string } elseif ($address->getAddressType() == AbstractAddress::TYPE_BILLING) { $addressType = 'BillingCartAddress'; } else { - throw new LocalizedException( __('Unsupported cart address type')); + throw new LocalizedException(__('Unsupported cart address type')); } return $addressType; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 1633c83895e67..6f27693eeb4a7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -71,13 +71,13 @@ public function testAddMoreProductsThatAllowed() * @expectedException \Exception * @expectedExceptionMessage Please enter a number greater than 0 in this field. */ - public function testAddSimpleProductToCartWithNegativeQty() + public function testAddSimpleProductToCartWithNegativeQuantity() { $sku = 'simple'; - $qty = -2; + $quantity = -2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -88,10 +88,10 @@ public function testAddSimpleProductToCartWithNegativeQty() public function testAddProductIfQuantityIsDecimal() { $sku = 'simple_product'; - $qty = 0.2; + $quantity = 0.2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->expectExceptionMessage( "Could not add the product with SKU {$sku} to the shopping cart: The fewest you may purchase is 1" @@ -102,10 +102,10 @@ public function testAddProductIfQuantityIsDecimal() /** * @param string $maskedQuoteId * @param string $sku - * @param float $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, float $qty) : string + private function getQuery(string $maskedQuoteId, string $sku, float $quantity) : string { return <<<QUERY mutation { @@ -115,7 +115,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $qty) : stri cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php index b13277136fadb..3b238f8641637 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php @@ -41,26 +41,26 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ - public function testUpdateCartItemDecimalQty() + public function testUpdateCartItemDecimalQuantity() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $itemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute('test_quote', 'simple_product'); - $qty = 0.5; + $quantity = 0.5; $this->expectExceptionMessage( "Could not update the product with SKU simple_product: The fewest you may purchase is 1" ); - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $query = $this->getQuery($maskedQuoteId, $itemId, $quantity); $this->graphQlMutation($query); } /** * @param string $maskedQuoteId * @param int $itemId - * @param float $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, int $itemId, float $qty): string + private function getQuery(string $maskedQuoteId, int $itemId, float $quantity): string { return <<<QUERY mutation { @@ -69,14 +69,14 @@ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): strin cart_items:[ { cart_item_id: {$itemId} - quantity: {$qty} + quantity: {$quantity} } ] }) { cart { items { id - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php index 48bff73226894..68e99feb5fae2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php @@ -100,7 +100,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() 'label' => null, ], 'telephone' => null, - '__typename' => 'BillingCartAddress', + '__typename' => null, ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); } From 779f39c71e3b801c9a9e8650f2acd05889643daf Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 16:41:23 -0500 Subject: [PATCH 554/585] GraphQL-575: Schema inconsistency of "SelectedShippingMethod" declaration --- .../CatalogGraphQl/etc/schema.graphqls | 178 ------------------ app/code/Magento/GraphQl/etc/schema.graphqls | 178 ++++++++++++++++++ .../SelectedShippingMethod.php | 43 +++-- .../Magento/QuoteGraphQl/etc/schema.graphqls | 6 +- .../GetSelectedShippingMethodTest.php | 38 +++- .../SetOfflineShippingMethodsOnCartTest.php | 66 +++++-- .../Customer/SetShippingMethodsOnCartTest.php | 36 +++- .../Guest/GetSelectedShippingMethodTest.php | 38 +++- .../SetOfflineShippingMethodsOnCartTest.php | 66 +++++-- .../Guest/SetShippingMethodsOnCartTest.php | 36 +++- .../Ups/SetUpsShippingMethodsOnCartTest.php | 35 ++-- 11 files changed, 480 insertions(+), 240 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 08066e5fdfed3..9f102a1c6a150 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -16,179 +16,6 @@ type Query { @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cacheTag: "cat_c", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentity") } -enum CurrencyEnum @doc(description: "The list of available currency codes") { - AFN - ALL - AZN - DZD - AOA - ARS - AMD - AWG - AUD - BSD - BHD - BDT - BBD - BYR - BZD - BMD - BTN - BOB - BAM - BWP - BRL - GBP - BND - BGN - BUK - BIF - KHR - CAD - CVE - CZK - KYD - GQE - CLP - CNY - COP - KMF - CDF - CRC - HRK - CUP - DKK - DJF - DOP - XCD - EGP - SVC - ERN - EEK - ETB - EUR - FKP - FJD - GMD - GEK - GEL - GHS - GIP - GTQ - GNF - GYD - HTG - HNL - HKD - HUF - ISK - INR - IDR - IRR - IQD - ILS - JMD - JPY - JOD - KZT - KES - KWD - KGS - LAK - LVL - LBP - LSL - LRD - LYD - LTL - MOP - MKD - MGA - MWK - MYR - MVR - LSM - MRO - MUR - MXN - MDL - MNT - MAD - MZN - MMK - NAD - NPR - ANG - YTL - NZD - NIC - NGN - KPW - NOK - OMR - PKR - PAB - PGK - PYG - PEN - PHP - PLN - QAR - RHD - RON - RUB - RWF - SHP - STD - SAR - RSD - SCR - SLL - SGD - SKK - SBD - SOS - ZAR - KRW - LKR - SDG - SRD - SZL - SEK - CHF - SYP - TWD - TJS - TZS - THB - TOP - TTD - TND - TMM - USD - UGX - UAH - AED - UYU - UZS - VUV - VEB - VEF - VND - CHE - CHW - XOF - WST - YER - ZMK - ZWD - TRY - AZM - ROL - TRL - XPF -} - type Price @doc(description: "The Price object defines the price of a product as well as any tax-related adjustments.") { amount: Money @doc(description: "The price of a product plus a three-letter currency code") adjustments: [PriceAdjustment] @doc(description: "An array that provides information about tax, weee, or weee_tax adjustments") @@ -214,11 +41,6 @@ enum PriceTypeEnum @doc(description: "This enumeration the price type.") { DYNAMIC } -type Money @doc(description: "A Money object defines a monetary value, including a numeric value and a currency code.") { - value: Float @doc(description: "A number expressing a monetary value") - currency: CurrencyEnum @doc(description: "A three-letter currency code, such as USD or EUR") -} - type ProductPrices @doc(description: "The ProductPrices object contains the regular price of an item, as well as its minimum and maximum prices. Only composite products, which include bundle, configurable, and grouped products, can contain a minimum and maximum price.") { minimalPrice: Price @doc(description: "The lowest possible final price for all the options defined within a composite product. If you are specifying a price range, this would be the from value.") maximalPrice: Price @doc(description: "The highest possible final price for all the options defined within a composite product. If you are specifying a price range, this would be the to value.") diff --git a/app/code/Magento/GraphQl/etc/schema.graphqls b/app/code/Magento/GraphQl/etc/schema.graphqls index 7ea715097cdf3..ab8472aa56cf0 100644 --- a/app/code/Magento/GraphQl/etc/schema.graphqls +++ b/app/code/Magento/GraphQl/etc/schema.graphqls @@ -39,3 +39,181 @@ enum SortEnum @doc(description: "This enumeration indicates whether to return re type ComplexTextValue { html: String! @doc(description: "HTML format") } + +type Money @doc(description: "A Money object defines a monetary value, including a numeric value and a currency code.") { + value: Float @doc(description: "A number expressing a monetary value") + currency: CurrencyEnum @doc(description: "A three-letter currency code, such as USD or EUR") +} + +enum CurrencyEnum @doc(description: "The list of available currency codes") { + AFN + ALL + AZN + DZD + AOA + ARS + AMD + AWG + AUD + BSD + BHD + BDT + BBD + BYR + BZD + BMD + BTN + BOB + BAM + BWP + BRL + GBP + BND + BGN + BUK + BIF + KHR + CAD + CVE + CZK + KYD + GQE + CLP + CNY + COP + KMF + CDF + CRC + HRK + CUP + DKK + DJF + DOP + XCD + EGP + SVC + ERN + EEK + ETB + EUR + FKP + FJD + GMD + GEK + GEL + GHS + GIP + GTQ + GNF + GYD + HTG + HNL + HKD + HUF + ISK + INR + IDR + IRR + IQD + ILS + JMD + JPY + JOD + KZT + KES + KWD + KGS + LAK + LVL + LBP + LSL + LRD + LYD + LTL + MOP + MKD + MGA + MWK + MYR + MVR + LSM + MRO + MUR + MXN + MDL + MNT + MAD + MZN + MMK + NAD + NPR + ANG + YTL + NZD + NIC + NGN + KPW + NOK + OMR + PKR + PAB + PGK + PYG + PEN + PHP + PLN + QAR + RHD + RON + RUB + RWF + SHP + STD + SAR + RSD + SCR + SLL + SGD + SKK + SBD + SOS + ZAR + KRW + LKR + SDG + SRD + SZL + SEK + CHF + SYP + TWD + TJS + TZS + THB + TOP + TTD + TND + TMM + USD + UGX + UAH + AED + UYU + UZS + VUV + VEB + VEF + VND + CHE + CHW + XOF + WST + YER + ZMK + ZWD + TRY + AZM + ROL + TRL + XPF +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index c58affa064c89..6f92611e25f48 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -11,6 +11,8 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\Quote\Model\Quote\Address; +use Magento\Quote\Model\Quote\Address\Rate; /** * @inheritdoc @@ -25,19 +27,38 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value if (!isset($value['model'])) { throw new LocalizedException(__('"model" value should be specified')); } - + /** @var Address $address */ $address = $value['model']; + $rates = $address->getAllShippingRates(); - if ($address->getShippingMethod()) { - list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); - $shippingAmount = $address->getShippingAmount(); - } + if (count($rates) > 0) { + /** @var Rate $rate */ + $rate = current($rates); - return [ - 'carrier_code' => $carrierCode ?? null, - 'method_code' => $methodCode ?? null, - 'label' => $address->getShippingDescription(), - 'amount' => $shippingAmount ?? null, - ]; + $data = [ + 'carrier_code' => $rate->getCarrier(), + 'method_code' => $rate->getMethod(), + 'carrier_title' => $rate->getCarrierTitle(), + 'method_title' => $rate->getMethodTitle(), + 'amount' => [ + 'value' => $address->getShippingAmount(), + 'currency' => $address->getQuote()->getQuoteCurrencyCode(), + ], + 'base_amount' => [ + 'value' => $address->getBaseShippingAmount(), + 'currency' => $address->getQuote()->getBaseCurrencyCode(), + ], + ]; + } else { + $data = [ + 'carrier_code' => null, + 'method_code' => null, + 'carrier_title' => null, + 'method_title' => null, + 'amount' => null, + 'base_amount' => null, + ]; + } + return $data; } } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 6d94685ac4d0f..43682934443cb 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -226,8 +226,10 @@ type CartAddressCountry { type SelectedShippingMethod { carrier_code: String method_code: String - label: String - amount: Float + carrier_title: String + method_title: String + amount: Money + base_amount: Money } type AvailableShippingMethod { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php index ba169d7a5bbc9..5575830ea51cd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php @@ -64,6 +64,28 @@ public function testGetSelectedShippingMethod() self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Flat Rate', $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Fixed', $shippingAddress['selected_shipping_method']['method_title']); + + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); + $amount = $shippingAddress['selected_shipping_method']['amount']; + + self::assertArrayHasKey('value', $amount); + self::assertEquals(10, $amount['value']); + self::assertArrayHasKey('currency', $amount); + self::assertEquals('USD', $amount['currency']); + + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + $baseAmount = $shippingAddress['selected_shipping_method']['base_amount']; + + self::assertArrayHasKey('value', $baseAmount); + self::assertEquals(10, $baseAmount['value']); + self::assertArrayHasKey('currency', $baseAmount); + self::assertEquals('USD', $baseAmount['currency']); } /** @@ -129,8 +151,10 @@ public function testGetGetSelectedShippingMethodIfShippingMethodIsNotSet() self::assertNull($shippingAddress['selected_shipping_method']['carrier_code']); self::assertNull($shippingAddress['selected_shipping_method']['method_code']); - self::assertNull($shippingAddress['selected_shipping_method']['label']); + self::assertNull($shippingAddress['selected_shipping_method']['carrier_title']); + self::assertNull($shippingAddress['selected_shipping_method']['method_title']); self::assertNull($shippingAddress['selected_shipping_method']['amount']); + self::assertNull($shippingAddress['selected_shipping_method']['base_amount']); } /** @@ -172,8 +196,16 @@ private function getQuery(string $maskedQuoteId): string selected_shipping_method { carrier_code method_code - label - amount + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php index 4544691584721..c6c4a18bce4ab 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php @@ -48,12 +48,21 @@ protected function setUp() * * @param string $carrierCode * @param string $methodCode - * @param float $amount - * @param string $label + * @param string $carrierTitle + * @param string $methodTitle + * @param array $amount + * @param array $baseAmount + * @throws \Magento\Framework\Exception\NoSuchEntityException * @dataProvider offlineShippingMethodDataProvider */ - public function testSetOfflineShippingMethod(string $carrierCode, string $methodCode, float $amount, string $label) - { + public function testSetOfflineShippingMethod( + string $carrierCode, + string $methodCode, + string $carrierTitle, + string $methodTitle, + array $amount, + array $baseAmount + ) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery( @@ -77,11 +86,17 @@ public function testSetOfflineShippingMethod(string $carrierCode, string $method self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($carrierTitle, $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); self::assertEquals($amount, $shippingAddress['selected_shipping_method']['amount']); - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals($label, $shippingAddress['selected_shipping_method']['label']); + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + self::assertEquals($baseAmount, $shippingAddress['selected_shipping_method']['base_amount']); } /** @@ -90,9 +105,30 @@ public function testSetOfflineShippingMethod(string $carrierCode, string $method public function offlineShippingMethodDataProvider(): array { return [ - 'flatrate_flatrate' => ['flatrate', 'flatrate', 10, 'Flat Rate - Fixed'], - 'tablerate_bestway' => ['tablerate', 'bestway', 10, 'Best Way - Table Rate'], - 'freeshipping_freeshipping' => ['freeshipping', 'freeshipping', 0, 'Free Shipping - Free'], + 'flatrate_flatrate' => [ + 'flatrate', + 'flatrate', + 'Flat Rate', + 'Fixed', + ['value' => 10, 'currency' => 'USD'], + ['value' => 10, 'currency' => 'USD'], + ], + 'tablerate_bestway' => [ + 'tablerate', + 'bestway', + 'Best Way', + 'Table Rate', + ['value' => 10, 'currency' => 'USD'], + ['value' => 10, 'currency' => 'USD'], + ], + 'freeshipping_freeshipping' => [ + 'freeshipping', + 'freeshipping', + 'Free Shipping', + 'Free', + ['value' => 0, 'currency' => 'USD'], + ['value' => 0, 'currency' => 'USD'], + ], ]; } @@ -122,8 +158,16 @@ private function getQuery( selected_shipping_method { carrier_code method_code - amount - label + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php index a5c91865926a5..9ddedbfc46541 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php @@ -67,10 +67,32 @@ public function testSetShippingMethodOnCartWithSimpleProduct() self::assertArrayHasKey('selected_shipping_method', $shippingAddress); self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($carrierCode, $shippingAddress['selected_shipping_method']['carrier_code']); + self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['carrier_code']); self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Flat Rate', $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Fixed', $shippingAddress['selected_shipping_method']['method_title']); + + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); + $amount = $shippingAddress['selected_shipping_method']['amount']; + + self::assertArrayHasKey('value', $amount); + self::assertEquals(10, $amount['value']); + self::assertArrayHasKey('currency', $amount); + self::assertEquals('USD', $amount['currency']); + + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + $baseAmount = $shippingAddress['selected_shipping_method']['base_amount']; + + self::assertArrayHasKey('value', $baseAmount); + self::assertEquals(10, $baseAmount['value']); + self::assertArrayHasKey('currency', $baseAmount); + self::assertEquals('USD', $baseAmount['currency']); } /** @@ -347,6 +369,16 @@ private function getQuery( selected_shipping_method { carrier_code method_code + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php index bfdecca782319..bd684a950b590 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php @@ -56,6 +56,28 @@ public function testGetSelectedShippingMethod() self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Flat Rate', $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Fixed', $shippingAddress['selected_shipping_method']['method_title']); + + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); + $amount = $shippingAddress['selected_shipping_method']['amount']; + + self::assertArrayHasKey('value', $amount); + self::assertEquals(10, $amount['value']); + self::assertArrayHasKey('currency', $amount); + self::assertEquals('USD', $amount['currency']); + + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + $baseAmount = $shippingAddress['selected_shipping_method']['base_amount']; + + self::assertArrayHasKey('value', $baseAmount); + self::assertEquals(10, $baseAmount['value']); + self::assertArrayHasKey('currency', $baseAmount); + self::assertEquals('USD', $baseAmount['currency']); } /** @@ -100,8 +122,10 @@ public function testGetGetSelectedShippingMethodIfShippingMethodIsNotSet() self::assertNull($shippingAddress['selected_shipping_method']['carrier_code']); self::assertNull($shippingAddress['selected_shipping_method']['method_code']); - self::assertNull($shippingAddress['selected_shipping_method']['label']); + self::assertNull($shippingAddress['selected_shipping_method']['carrier_title']); + self::assertNull($shippingAddress['selected_shipping_method']['method_title']); self::assertNull($shippingAddress['selected_shipping_method']['amount']); + self::assertNull($shippingAddress['selected_shipping_method']['base_amount']); } /** @@ -128,8 +152,16 @@ private function getQuery(string $maskedQuoteId): string selected_shipping_method { carrier_code method_code - label - amount + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php index 2dc4ea360acb9..ff2c5f2e6b528 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php @@ -40,12 +40,21 @@ protected function setUp() * * @param string $carrierCode * @param string $methodCode - * @param float $amount - * @param string $label + * @param string $carrierTitle + * @param string $methodTitle + * @param array $amount + * @param array $baseAmount + * @throws \Magento\Framework\Exception\NoSuchEntityException * @dataProvider offlineShippingMethodDataProvider */ - public function testSetOfflineShippingMethod(string $carrierCode, string $methodCode, float $amount, string $label) - { + public function testSetOfflineShippingMethod( + string $carrierCode, + string $methodCode, + string $carrierTitle, + string $methodTitle, + array $amount, + array $baseAmount + ) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery( @@ -69,11 +78,17 @@ public function testSetOfflineShippingMethod(string $carrierCode, string $method self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($carrierTitle, $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); self::assertEquals($amount, $shippingAddress['selected_shipping_method']['amount']); - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals($label, $shippingAddress['selected_shipping_method']['label']); + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + self::assertEquals($baseAmount, $shippingAddress['selected_shipping_method']['base_amount']); } /** @@ -82,9 +97,30 @@ public function testSetOfflineShippingMethod(string $carrierCode, string $method public function offlineShippingMethodDataProvider(): array { return [ - 'flatrate_flatrate' => ['flatrate', 'flatrate', 10, 'Flat Rate - Fixed'], - 'tablerate_bestway' => ['tablerate', 'bestway', 10, 'Best Way - Table Rate'], - 'freeshipping_freeshipping' => ['freeshipping', 'freeshipping', 0, 'Free Shipping - Free'], + 'flatrate_flatrate' => [ + 'flatrate', + 'flatrate', + 'Flat Rate', + 'Fixed', + ['value' => 10, 'currency' => 'USD'], + ['value' => 10, 'currency' => 'USD'], + ], + 'tablerate_bestway' => [ + 'tablerate', + 'bestway', + 'Best Way', + 'Table Rate', + ['value' => 10, 'currency' => 'USD'], + ['value' => 10, 'currency' => 'USD'], + ], + 'freeshipping_freeshipping' => [ + 'freeshipping', + 'freeshipping', + 'Free Shipping', + 'Free', + ['value' => 0, 'currency' => 'USD'], + ['value' => 0, 'currency' => 'USD'], + ], ]; } @@ -114,8 +150,16 @@ private function getQuery( selected_shipping_method { carrier_code method_code - amount - label + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php index 3cac485f9f6f2..0c2bf1453b547 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php @@ -59,10 +59,32 @@ public function testSetShippingMethodOnCartWithSimpleProduct() self::assertArrayHasKey('selected_shipping_method', $shippingAddress); self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($carrierCode, $shippingAddress['selected_shipping_method']['carrier_code']); + self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['carrier_code']); self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Flat Rate', $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Fixed', $shippingAddress['selected_shipping_method']['method_title']); + + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); + $amount = $shippingAddress['selected_shipping_method']['amount']; + + self::assertArrayHasKey('value', $amount); + self::assertEquals(10, $amount['value']); + self::assertArrayHasKey('currency', $amount); + self::assertEquals('USD', $amount['currency']); + + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + $baseAmount = $shippingAddress['selected_shipping_method']['base_amount']; + + self::assertArrayHasKey('value', $baseAmount); + self::assertEquals(10, $baseAmount['value']); + self::assertArrayHasKey('currency', $baseAmount); + self::assertEquals('USD', $baseAmount['currency']); } /** @@ -358,6 +380,16 @@ private function getQuery( selected_shipping_method { carrier_code method_code + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index ea498ddb31d16..2f6f39d169009 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -48,9 +48,9 @@ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract { /** - * Defines carrier label for "UPS" shipping method + * Defines carrier title for "UPS" shipping method */ - const CARRIER_LABEL = 'United Parcel Service'; + const CARRIER_TITLE = 'United Parcel Service'; /** * Defines carrier code for "UPS" shipping method @@ -87,9 +87,9 @@ protected function setUp() * * @dataProvider dataProviderShippingMethods * @param string $methodCode - * @param string $methodLabel + * @param string $methodTitle */ - public function testSetUpsShippingMethod(string $methodCode, string $methodLabel) + public function testSetUpsShippingMethod(string $methodCode, string $methodTitle) { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); @@ -111,11 +111,11 @@ public function testSetUpsShippingMethod(string $methodCode, string $methodLabel self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -142,9 +142,9 @@ public function dataProviderShippingMethods(): array * * @dataProvider dataProviderShippingMethodsBasedOnCanadaAddress * @param string $methodCode - * @param string $methodLabel + * @param string $methodTitle */ - public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, string $methodLabel) + public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, string $methodTitle) { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); @@ -166,11 +166,11 @@ public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -216,7 +216,8 @@ private function getQuery( selected_shipping_method { carrier_code method_code - label + carrier_title + method_title } } } From 7d27046c88f320fc174145b380bfbdbd54a17a7d Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 20:15:37 -0500 Subject: [PATCH 555/585] GraphQL-575: Schema inconsistency of "SelectedShippingMethod" declaration --- .../Resolver/ShippingAddress/SelectedShippingMethod.php | 5 +++-- .../Quote/Customer/GetSpecifiedBillingAddressTest.php | 2 +- .../GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php | 2 +- .../Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php | 2 -- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index 6f92611e25f48..cd8f20c3f164f 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -32,12 +32,13 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $rates = $address->getAllShippingRates(); if (count($rates) > 0) { + list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); /** @var Rate $rate */ $rate = current($rates); $data = [ - 'carrier_code' => $rate->getCarrier(), - 'method_code' => $rate->getMethod(), + 'carrier_code' => $carrierCode, + 'method_code' => $methodCode, 'carrier_title' => $rate->getCarrierTitle(), 'method_title' => $rate->getMethodTitle(), 'amount' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php index e10d12d73e7a6..1ff5ddbde54ec 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php @@ -110,7 +110,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() 'label' => null, ], 'telephone' => null, - '__typename' => null, + '__typename' => 'BillingCartAddress', 'customer_notes' => null, ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php index 68e99feb5fae2..48bff73226894 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php @@ -100,7 +100,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() 'label' => null, ], 'telephone' => null, - '__typename' => null, + '__typename' => 'BillingCartAddress', ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index 2f6f39d169009..d317c243e84b6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -115,7 +115,6 @@ public function testSetUpsShippingMethod(string $methodCode, string $methodTitle self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -170,7 +169,6 @@ public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** From f6232000ebe7e9e5f7b85b236f5db272d65ea731 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 20:48:34 -0500 Subject: [PATCH 556/585] GraphQL-575: Schema inconsistency of "SelectedShippingMethod" declaration --- .../Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index d317c243e84b6..c50ae0a70380e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -88,6 +88,7 @@ protected function setUp() * @dataProvider dataProviderShippingMethods * @param string $methodCode * @param string $methodTitle + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function testSetUpsShippingMethod(string $methodCode, string $methodTitle) { @@ -142,6 +143,7 @@ public function dataProviderShippingMethods(): array * @dataProvider dataProviderShippingMethodsBasedOnCanadaAddress * @param string $methodCode * @param string $methodTitle + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, string $methodTitle) { From 56f79ede444a84b6ba18b673602d1221d059e156 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 23:21:16 -0500 Subject: [PATCH 557/585] GraphQL-631: Schema inconsistency of "Quantity / Qty" declaration --- setup/performance-toolkit/benchmark.jmx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index c1d21a08f9e2d..0609be4d7d193 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -41820,7 +41820,7 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product quantity In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -42126,7 +42126,7 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product quantity In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> From 74ef0c0b5d168285d375b260ffbbddc87c4d3634 Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Tue, 30 Apr 2019 10:16:10 +0300 Subject: [PATCH 558/585] magento/magento2#22020 static-test-fix --- app/code/Magento/Catalog/Model/Product/Gallery/Processor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php index 21503c1c8a687..54bef2efa5d51 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php @@ -494,7 +494,7 @@ protected function getNotDuplicatedFilename($fileName, $dispretionPath) /** * Retrieve data for update attribute * - * @param \Magento\Catalog\Model\Product $object + * @param \Magento\Catalog\Model\Product $object * @return array * @since 101.0.0 */ From f900e10206da15d28bb52fc56b9a1eb230b438b6 Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Tue, 30 Apr 2019 11:40:10 +0300 Subject: [PATCH 559/585] magento/magento2#22526 static-test-fix --- .../Magento/Backend/Block/Store/Switcher.php | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backend/Block/Store/Switcher.php b/app/code/Magento/Backend/Block/Store/Switcher.php index 709f44a879a3f..9c35cfb5df81d 100644 --- a/app/code/Magento/Backend/Block/Store/Switcher.php +++ b/app/code/Magento/Backend/Block/Store/Switcher.php @@ -86,6 +86,8 @@ class Switcher extends \Magento\Backend\Block\Template protected $_storeFactory; /** + * Switcher constructor. + * * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Store\Model\WebsiteFactory $websiteFactory * @param \Magento\Store\Model\GroupFactory $storeGroupFactory @@ -106,7 +108,7 @@ public function __construct( } /** - * @return void + * @inheritdoc */ protected function _construct() { @@ -130,6 +132,8 @@ protected function _construct() } /** + * Get website collection. + * * @return \Magento\Store\Model\ResourceModel\Website\Collection */ public function getWebsiteCollection() @@ -169,6 +173,8 @@ public function isWebsiteSwitchEnabled() } /** + * Set website variable name. + * * @param string $varName * @return $this */ @@ -179,6 +185,8 @@ public function setWebsiteVarName($varName) } /** + * Get website variable name. + * * @return string */ public function getWebsiteVarName() @@ -191,6 +199,8 @@ public function getWebsiteVarName() } /** + * Check if current website selected. + * * @param \Magento\Store\Model\Website $website * @return bool */ @@ -200,6 +210,8 @@ public function isWebsiteSelected(\Magento\Store\Model\Website $website) } /** + * Return website Id. + * * @return int|null */ public function getWebsiteId() @@ -211,6 +223,8 @@ public function getWebsiteId() } /** + * Return group collection provided website. + * * @param int|\Magento\Store\Model\Website $website * @return \Magento\Store\Model\ResourceModel\Group\Collection */ @@ -247,6 +261,8 @@ public function isStoreGroupSwitchEnabled() } /** + * Sets store group variable name. + * * @param string $varName * @return $this */ @@ -257,6 +273,8 @@ public function setStoreGroupVarName($varName) } /** + * Return store group variable name. + * * @return string */ public function getStoreGroupVarName() @@ -269,6 +287,8 @@ public function getStoreGroupVarName() } /** + * Is provided group selected. + * * @param \Magento\Store\Model\Group $group * @return bool */ @@ -278,6 +298,8 @@ public function isStoreGroupSelected(\Magento\Store\Model\Group $group) } /** + * Return store group Id. + * * @return int|null */ public function getStoreGroupId() @@ -289,6 +311,8 @@ public function getStoreGroupId() } /** + * Return store collection. + * * @param \Magento\Store\Model\Group|int $group * @return \Magento\Store\Model\ResourceModel\Store\Collection */ @@ -328,6 +352,8 @@ public function getStores($group) } /** + * Return store Id. + * * @return int|null */ public function getStoreId() @@ -339,6 +365,8 @@ public function getStoreId() } /** + * Check is provided store selected. + * * @param \Magento\Store\Model\Store $store * @return bool */ @@ -358,6 +386,8 @@ public function isStoreSwitchEnabled() } /** + * Sets store variable name. + * * @param string $varName * @return $this */ @@ -368,6 +398,8 @@ public function setStoreVarName($varName) } /** + * Return store variable name. + * * @return mixed|string */ public function getStoreVarName() @@ -380,6 +412,8 @@ public function getStoreVarName() } /** + * Return switch url. + * * @return string */ public function getSwitchUrl() @@ -399,6 +433,8 @@ public function getSwitchUrl() } /** + * Checks if scope selected. + * * @return bool */ public function hasScopeSelected() @@ -472,6 +508,8 @@ public function getCurrentStoreName() } /** + * Sets store ids. + * * @param array $storeIds * @return $this */ @@ -482,6 +520,8 @@ public function setStoreIds($storeIds) } /** + * Return store ids. + * * @return array */ public function getStoreIds() @@ -490,6 +530,8 @@ public function getStoreIds() } /** + * Check if system is run in the single store mode. + * * @return bool */ public function isShow() @@ -498,6 +540,8 @@ public function isShow() } /** + * Render block. + * * @return string */ protected function _toHtml() From 81daba855c0e741b3659fb109556115638e15f5d Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Fri, 22 Mar 2019 14:53:44 +0200 Subject: [PATCH 560/585] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Model/Cart/AddSimpleProductToCart.php | 18 +++++++++++++++++- app/code/Magento/QuoteGraphQl/etc/di.xml | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index ad730288e5cc2..36a31642e5139 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -15,6 +15,7 @@ use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\Stdlib\ArrayManager; use Magento\Quote\Model\Quote; +use phpDocumentor\Reflection\Types\Mixed_; /** * Add simple product to cart @@ -140,7 +141,9 @@ private function extractCustomizableOptions(array $cartItemData): array $customizableOptionsData = []; foreach ($customizableOptions as $customizableOption) { - $customizableOptionsData[$customizableOption['id']] = $customizableOption['value']; + $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( + $customizableOption['value'] + ); } return $customizableOptionsData; } @@ -161,4 +164,17 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb ], ]); } + + /** + * @param string $value + * @return string|array + */ + private function convertCustomOptions(string $value) + { + if (substr($value, 0, 1) === "[" || + substr($value, strlen($value) - 1, 1) === "]") { + return explode(',', substr($value, 1, -1)); + } + return $value; + } } diff --git a/app/code/Magento/QuoteGraphQl/etc/di.xml b/app/code/Magento/QuoteGraphQl/etc/di.xml index 0697761a2a2a6..32b8b12987ffa 100644 --- a/app/code/Magento/QuoteGraphQl/etc/di.xml +++ b/app/code/Magento/QuoteGraphQl/etc/di.xml @@ -26,7 +26,7 @@ <item name="area" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Text</item> <item name="drop_down" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown</item> <item name="radio" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown</item> - <item name="checkbox" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown</item> + <item name="checkbox" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Multiple</item> <item name="multiple" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Multiple</item> </argument> </arguments> From 742e6a79c733819744c6afa75dd1cde1dac2824c Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Thu, 28 Mar 2019 08:31:35 +0200 Subject: [PATCH 561/585] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Model/Cart/AddSimpleProductToCart.php | 1 - .../CatalogInventory/AddProductToCartTest.php | 83 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index 36a31642e5139..cf65393b08997 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -15,7 +15,6 @@ use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\Stdlib\ArrayManager; use Magento\Quote\Model\Quote; -use phpDocumentor\Reflection\Types\Mixed_; /** * Add simple product to cart diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 6f27693eeb4a7..c2fbfc1418dbf 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -46,6 +46,89 @@ public function testAddProductIfQuantityIsNotAvailable() $this->graphQlMutation($query); } + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @expectedException \Exception + * @expectedExceptionMessage The product's required option(s) weren't entered. Make sure the options are entered and try again. + */ + public function testAddProductWithoutRequiredCustomOPtions() + { + $sku = 'simple_with_custom_options'; + $qty = 1; + + $maskedQuoteId = $this->getMaskedQuoteId(); + $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + */ + public function testAddProductWithRequiredCustomOPtions() + { + $sku = 'simple_with_custom_options'; + $qty = 1; + $productCustomOptions = Bootstrap::getObjectManager() + ->get(\Magento\Catalog\Api\ProductCustomOptionRepositoryInterface::class) + ->getList($sku); + $customizableOptions = ''; + foreach ($productCustomOptions as $option) { + $value = $option->getValues() ? + '[' . key($option->getValues()) . ']' : + 'Test'; + $customizableOptions .= ' { + id: ' . $option->getId() . ' + value: "' . $value . '" + }'; + } + + $maskedQuoteId = $this->getMaskedQuoteId(); + $query = <<<QUERY +mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$maskedQuoteId}" + cartItems: { + data: { + qty: {$qty} + sku: "{$sku}" + } + customizable_options: [ + {$customizableOptions} + ] + } + } + ) +{ + cart { + items { + product { + sku + } + ... on SimpleCartItem { + customizable_options { + id + is_required + sort_order + } + } + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); + + self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); + self::assertEquals( + 1, + $response['addSimpleProductsToCart']['cart']['items'][0]['customizable_options'][0]['is_required'] + ); + } + /** * @magentoApiDataFixture Magento/Catalog/_files/products.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php From 30bc7b764590cb030eb57a4af3011fae77b5ddf4 Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Wed, 3 Apr 2019 09:10:08 +0300 Subject: [PATCH 562/585] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index cf65393b08997..bd81a15307e31 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -170,7 +170,7 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb */ private function convertCustomOptions(string $value) { - if (substr($value, 0, 1) === "[" || + if (substr($value, 0, 1) === "[" && substr($value, strlen($value) - 1, 1) === "]") { return explode(',', substr($value, 1, -1)); } From 733ddf969f840a0a787a459c96c97869c7f58ad1 Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Sat, 27 Apr 2019 12:26:29 +0300 Subject: [PATCH 563/585] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 1 - .../Magento/GraphQl/CatalogInventory/AddProductToCartTest.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index e2d29e93db574..0b6b392c2ed9b 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -325,7 +325,6 @@ type SelectedCustomizableOptionValue { label: String! value: String! price: CartItemSelectedOptionValuePrice! - sort_order: Int! } type CartItemSelectedOptionValuePrice { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index c2fbfc1418dbf..708e034a4626b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -52,7 +52,7 @@ public function testAddProductIfQuantityIsNotAvailable() * @expectedException \Exception * @expectedExceptionMessage The product's required option(s) weren't entered. Make sure the options are entered and try again. */ - public function testAddProductWithoutRequiredCustomOPtions() + public function testAddProductWithoutRequiredCustomOptions() { $sku = 'simple_with_custom_options'; $qty = 1; @@ -66,7 +66,7 @@ public function testAddProductWithoutRequiredCustomOPtions() * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddProductWithRequiredCustomOPtions() + public function testAddProductWithRequiredCustomOptions() { $sku = 'simple_with_custom_options'; $qty = 1; From 1315577e2099637207f02deec48607d81f7cde46 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 11:33:53 -0500 Subject: [PATCH 564/585] GraphQL-474: Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Model/Cart/AddSimpleProductToCart.php | 52 ++++++------- .../Magento/QuoteGraphQl/etc/schema.graphqls | 7 +- ...mpleProductWithCustomOptionsToCartTest.php | 75 +++++++------------ ...tualProductWithCustomOptionsToCartTest.php | 75 +++++++------------ 4 files changed, 84 insertions(+), 125 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index bd81a15307e31..251f17619c2a8 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -13,21 +13,13 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; -use Magento\Framework\Stdlib\ArrayManager; use Magento\Quote\Model\Quote; /** * Add simple product to cart - * - * TODO: should be replaced for different types resolver */ class AddSimpleProductToCart { - /** - * @var ArrayManager - */ - private $arrayManager; - /** * @var DataObjectFactory */ @@ -39,16 +31,13 @@ class AddSimpleProductToCart private $productRepository; /** - * @param ArrayManager $arrayManager * @param DataObjectFactory $dataObjectFactory * @param ProductRepositoryInterface $productRepository */ public function __construct( - ArrayManager $arrayManager, DataObjectFactory $dataObjectFactory, ProductRepositoryInterface $productRepository ) { - $this->arrayManager = $arrayManager; $this->dataObjectFactory = $dataObjectFactory; $this->productRepository = $productRepository; } @@ -67,11 +56,6 @@ public function execute(Quote $cart, array $cartItemData): void { $sku = $this->extractSku($cartItemData); $quantity = $this->extractQuantity($cartItemData); - if ($quantity <= 0) { - throw new GraphQlInputException( - __('Please enter a number greater than 0 in this field.') - ); - } $customizableOptions = $this->extractCustomizableOptions($cartItemData); try { @@ -105,11 +89,10 @@ public function execute(Quote $cart, array $cartItemData): void */ private function extractSku(array $cartItemData): string { - $sku = $this->arrayManager->get('data/sku', $cartItemData); - if (!isset($sku)) { - throw new GraphQlInputException(__('Missing key "sku" in cart item data')); + if (!isset($cartItemData['data']['sku']) || empty($cartItemData['data']['sku'])) { + throw new GraphQlInputException(__('Missed "sku" in cart item data')); } - return (string)$sku; + return (string)$cartItemData['data']['sku']; } /** @@ -121,11 +104,17 @@ private function extractSku(array $cartItemData): string */ private function extractQuantity(array $cartItemData): float { - $quantity = $this->arrayManager->get('data/quantity', $cartItemData); - if (!isset($quantity)) { - throw new GraphQlInputException(__('Missing key "quantity" in cart item data')); + if (!isset($cartItemData['data']['quantity'])) { + throw new GraphQlInputException(__('Missed "qty" in cart item data')); } - return (float)$quantity; + $quantity = (float)$cartItemData['data']['quantity']; + + if ($quantity <= 0) { + throw new GraphQlInputException( + __('Please enter a number greater than 0 in this field.') + ); + } + return $quantity; } /** @@ -136,13 +125,17 @@ private function extractQuantity(array $cartItemData): float */ private function extractCustomizableOptions(array $cartItemData): array { - $customizableOptions = $this->arrayManager->get('customizable_options', $cartItemData, []); + if (!isset($cartItemData['customizable_options']) || empty($cartItemData['customizable_options'])) { + return []; + } $customizableOptionsData = []; - foreach ($customizableOptions as $customizableOption) { - $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( - $customizableOption['value'] - ); + foreach ($cartItemData['customizable_options'] as $customizableOption) { + if (isset($customizableOption['value_string'])) { + $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( + $customizableOption['value_string'] + ); + } } return $customizableOptionsData; } @@ -170,6 +163,7 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb */ private function convertCustomOptions(string $value) { + $value = trim($value); if (substr($value, 0, 1) === "[" && substr($value, strlen($value) - 1, 1) === "]") { return explode(',', substr($value, 1, -1)); diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 0b6b392c2ed9b..c2b92034c3294 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -52,7 +52,7 @@ input CartItemInput { input CustomizableOptionInput { id: Int! - value: String! + value_string: String! } input ApplyCouponToCartInput { @@ -314,8 +314,7 @@ interface CartItemInterface @typeResolver(class: "Magento\\QuoteGraphQl\\Model\\ type SelectedCustomizableOption { id: Int! label: String! - type: String! - is_required: Int! + is_required: Boolean! values: [SelectedCustomizableOptionValue!]! sort_order: Int! } @@ -323,7 +322,7 @@ type SelectedCustomizableOption { type SelectedCustomizableOptionValue { id: Int! label: String! - value: String! + value: String price: CartItemSelectedOptionValuePrice! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index 63546298304b0..d64c51354129d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -50,41 +50,11 @@ public function testAddSimpleProductWithOptions() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); - /* Generate customizable options fragment for GraphQl request */ - $queryCustomizableOptions = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); + $queryCustomizableOptionValues = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); - $query = <<<QUERY -mutation { - addSimpleProductsToCart( - input: { - cart_id: "{$maskedQuoteId}", - cartItems: [ - { - data: { - quantity: $quantity - sku: "$sku" - }, - customizable_options: $queryCustomizableOptions - } - ] - } - ) { - cart { - items { - ... on SimpleCartItem { - customizable_options { - label - values { - value - } - } - } - } - } - } -} -QUERY; + $customizableOptions = "customizable_options: {$queryCustomizableOptionValues}"; + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); $response = $this->graphQlMutation($query); @@ -95,7 +65,7 @@ public function testAddSimpleProductWithOptions() $assignedOptionsCount = count($customOptionsValues); for ($counter = 0; $counter < $assignedOptionsCount; $counter++) { self::assertEquals( - $customOptionsValues[$counter]['value'], + $customOptionsValues[$counter]['value_string'], $customizableOptionsOutput[$counter]['values'][0]['value'] ); } @@ -107,13 +77,31 @@ public function testAddSimpleProductWithOptions() * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_options.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddSimpleProductWithNoRequiredOptionsSet() + public function testAddSimpleProductWithMissedRequiredOptionsSet() { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $sku = 'simple'; $quantity = 1; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $customizableOptions = ''; - $query = <<<QUERY + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); + + self::expectExceptionMessage( + 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' + ); + $this->graphQlMutation($query); + } + + /** + * @param string $maskedQuoteId + * @param string $sku + * @param float $quantity + * @param string $customizableOptions + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, float $quantity, string $customizableOptions): string + { + return <<<QUERY mutation { addSimpleProductsToCart( input: { @@ -124,6 +112,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() quantity: $quantity sku: "$sku" } + {$customizableOptions} } ] } @@ -134,7 +123,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() customizable_options { label values { - value + value } } } @@ -143,12 +132,6 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() } } QUERY; - - self::expectExceptionMessage( - 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' - ); - - $this->graphQlMutation($query); } /** @@ -168,13 +151,13 @@ private function getCustomOptionsValuesForQuery(string $sku): array if ($optionType == 'field' || $optionType == 'area') { $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => 'test' + 'value_string' => 'test' ]; } elseif ($optionType == 'drop_down') { $optionSelectValues = $customOption->getValues(); $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => reset($optionSelectValues)->getOptionTypeId() + 'value_string' => reset($optionSelectValues)->getOptionTypeId() ]; } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index 94ac11ad8e0b1..55542919cc098 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -50,41 +50,11 @@ public function testAddVirtualProductWithOptions() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); - /* Generate customizable options fragment for GraphQl request */ - $queryCustomizableOptions = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); + $queryCustomizableOptionValues = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); - $query = <<<QUERY -mutation { - addVirtualProductsToCart( - input: { - cart_id: "{$maskedQuoteId}", - cartItems: [ - { - data: { - quantity: $quantity - sku: "$sku" - }, - customizable_options: $queryCustomizableOptions - } - ] - } - ) { - cart { - items { - ... on VirtualCartItem { - customizable_options { - label - values { - value - } - } - } - } - } - } -} -QUERY; + $customizableOptions = "customizable_options: {$queryCustomizableOptionValues}"; + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); $response = $this->graphQlMutation($query); @@ -95,7 +65,7 @@ public function testAddVirtualProductWithOptions() $assignedOptionsCount = count($customOptionsValues); for ($counter = 0; $counter < $assignedOptionsCount; $counter++) { self::assertEquals( - $customOptionsValues[$counter]['value'], + $customOptionsValues[$counter]['value_string'], $customizableOptionsOutput[$counter]['values'][0]['value'] ); } @@ -107,13 +77,31 @@ public function testAddVirtualProductWithOptions() * @magentoApiDataFixture Magento/Catalog/_files/product_virtual_with_options.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddVirtualProductWithNoRequiredOptionsSet() + public function testAddSimpleProductWithMissedRequiredOptionsSet() { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $sku = 'virtual'; $quantity = 1; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $customizableOptions = ''; - $query = <<<QUERY + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); + + self::expectExceptionMessage( + 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' + ); + $this->graphQlMutation($query); + } + + /** + * @param string $maskedQuoteId + * @param string $sku + * @param float $quantity + * @param string $customizableOptions + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, float $quantity, string $customizableOptions): string + { + return <<<QUERY mutation { addVirtualProductsToCart( input: { @@ -124,6 +112,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() quantity: $quantity sku: "$sku" } + {$customizableOptions} } ] } @@ -134,7 +123,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() customizable_options { label values { - value + value } } } @@ -143,12 +132,6 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() } } QUERY; - - self::expectExceptionMessage( - 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' - ); - - $this->graphQlMutation($query); } /** @@ -168,13 +151,13 @@ private function getCustomOptionsValuesForQuery(string $sku): array if ($optionType == 'field' || $optionType == 'area') { $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => 'test' + 'value_string' => 'test' ]; } elseif ($optionType == 'drop_down') { $optionSelectValues = $customOption->getValues(); $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => reset($optionSelectValues)->getOptionTypeId() + 'value_string' => reset($optionSelectValues)->getOptionTypeId() ]; } } From b115f1c546d5f09e67c7f369ec8b239c1b0a2984 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 11:53:24 -0500 Subject: [PATCH 565/585] GraphQL-474: Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../CatalogInventory/AddProductToCartTest.php | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 708e034a4626b..6f27693eeb4a7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -46,89 +46,6 @@ public function testAddProductIfQuantityIsNotAvailable() $this->graphQlMutation($query); } - /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - * @expectedException \Exception - * @expectedExceptionMessage The product's required option(s) weren't entered. Make sure the options are entered and try again. - */ - public function testAddProductWithoutRequiredCustomOptions() - { - $sku = 'simple_with_custom_options'; - $qty = 1; - - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); - } - - /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - */ - public function testAddProductWithRequiredCustomOptions() - { - $sku = 'simple_with_custom_options'; - $qty = 1; - $productCustomOptions = Bootstrap::getObjectManager() - ->get(\Magento\Catalog\Api\ProductCustomOptionRepositoryInterface::class) - ->getList($sku); - $customizableOptions = ''; - foreach ($productCustomOptions as $option) { - $value = $option->getValues() ? - '[' . key($option->getValues()) . ']' : - 'Test'; - $customizableOptions .= ' { - id: ' . $option->getId() . ' - value: "' . $value . '" - }'; - } - - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = <<<QUERY -mutation { - addSimpleProductsToCart( - input: { - cart_id: "{$maskedQuoteId}" - cartItems: { - data: { - qty: {$qty} - sku: "{$sku}" - } - customizable_options: [ - {$customizableOptions} - ] - } - } - ) -{ - cart { - items { - product { - sku - } - ... on SimpleCartItem { - customizable_options { - id - is_required - sort_order - } - } - } - } - } -} -QUERY; - $response = $this->graphQlQuery($query); - self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - - self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); - self::assertEquals( - 1, - $response['addSimpleProductsToCart']['cart']['items'][0]['customizable_options'][0]['is_required'] - ); - } - /** * @magentoApiDataFixture Magento/Catalog/_files/products.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php From f393ffdc0f207a92f2df4274137b84ab50799362 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 12:34:21 -0500 Subject: [PATCH 566/585] GraphQL-641: Schema Inconsistency of "cartItems" declaration --- .../Magento/ConfigurableProductGraphQl/etc/schema.graphqls | 2 +- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 4 ++-- .../Magento/GraphQl/CatalogInventory/AddProductToCartTest.php | 2 +- .../ConfigurableProduct/AddConfigurableProductToCartTest.php | 2 +- .../Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php | 2 +- .../Quote/AddSimpleProductWithCustomOptionsToCartTest.php | 4 ++-- .../Quote/AddVirtualProductWithCustomOptionsToCartTest.php | 4 ++-- .../GraphQl/Quote/Customer/AddSimpleProductToCartTest.php | 2 +- .../GraphQl/Quote/Customer/AddVirtualProductToCartTest.php | 2 +- .../Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php | 2 +- .../GraphQl/Quote/Guest/AddSimpleProductToCartTest.php | 2 +- .../GraphQl/Quote/Guest/AddVirtualProductToCartTest.php | 2 +- .../Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php | 2 +- 13 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index d4780c5c0867a..45a4323e7f4bc 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -41,7 +41,7 @@ type ConfigurableProductOptionsValues @doc(description: "ConfigurableProductOpti input AddConfigurableProductsToCartInput { cart_id: String! - cartItems: [ConfigurableProductCartItemInput!]! + cart_items: [ConfigurableProductCartItemInput!]! } type AddConfigurableProductsToCartOutput { diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index e2d29e93db574..5828fd4975d78 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -27,7 +27,7 @@ input createEmptyCartInput { input AddSimpleProductsToCartInput { cart_id: String! - cartItems: [SimpleProductCartItemInput!]! + cart_items: [SimpleProductCartItemInput!]! } input SimpleProductCartItemInput { @@ -37,7 +37,7 @@ input SimpleProductCartItemInput { input AddVirtualProductsToCartInput { cart_id: String! - cartItems: [VirtualProductCartItemInput!]! + cart_items: [VirtualProductCartItemInput!]! } input VirtualProductCartItemInput { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 6f27693eeb4a7..6ed0f6ef7a132 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -112,7 +112,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity) : addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php index 6810f9d44ce91..a6f02e4239f25 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php @@ -93,7 +93,7 @@ private function getQuery(string $maskedQuoteId, string $variantSku, int $quanti addConfigurableProductsToCart( input: { cart_id: "{$maskedQuoteId}" - cartItems: [ + cart_items: [ { variant_sku: "{$variantSku}" data: { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php index e09ee8bc969af..808fd95d331e1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php @@ -79,7 +79,7 @@ private function addSimpleProductToCart(string $maskedCartId, int $qty, string $ addSimpleProductsToCart( input: { cart_id: "{$maskedCartId}" - cartItems: [ + cart_items: [ { data: { qty: $qty diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index 63546298304b0..d254e146f5b12 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -59,7 +59,7 @@ public function testAddSimpleProductWithOptions() addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity @@ -118,7 +118,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index 94ac11ad8e0b1..19bf591e81084 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -59,7 +59,7 @@ public function testAddVirtualProductWithOptions() addVirtualProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity @@ -118,7 +118,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() addVirtualProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index be22d860df122..aca13e53875dd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -139,7 +139,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): mutation { addSimpleProductsToCart(input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index 1269b9d8e7b3d..86573dcde2e35 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -139,7 +139,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): mutation { addVirtualProductsToCart(input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index 92974f2491f75..8ea8fce3a4327 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -212,7 +212,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void addSimpleProductsToCart( input: { cart_id: "{$cartId}" - cartItems: [ + cart_items: [ { data: { quantity: {$qty} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index 8b20320fc2f02..9a943cf4b204e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -112,7 +112,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}" - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index cb429e7b9cb9e..cadbec857c2d6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -113,7 +113,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): addVirtualProductsToCart( input: { cart_id: "{$maskedQuoteId}" - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index bddee2151f5cd..da6ac5f31448a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -172,7 +172,7 @@ private function addProductToCart(string $cartId, float $quantity, string $sku): addSimpleProductsToCart( input: { cart_id: "{$cartId}" - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} From a75fc35f8750b91789a8a4d2b53f19984938a337 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 30 Apr 2019 13:30:29 -0500 Subject: [PATCH 567/585] MQE-1519: Deliver weekly MTF conversion PR - Remove testCaseId MC-14719 because it is failing in the builds. To be revisited later. --- ...pingCartWithDisableMiniCartSidebarTest.xml | 127 ------------------ 1 file changed, 127 deletions(-) delete mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml deleted file mode 100644 index afbc6216ff9ca..0000000000000 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml +++ /dev/null @@ -1,127 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest"> - <annotations> - <stories value="Shopping Cart"/> - <title value="Create Grouped product and verify mini cart action with disabled and enable Mini Cart Sidebar"/> - <description value="Create Grouped product and verify mini cart action with disabled and enable Mini Cart Sidebar"/> - <testCaseId value="MC-14719"/> - <severity value="CRITICAL"/> - <group value="mtf_migrated"/> - </annotations> - - <before> - <magentoCLI stepKey="disableShoppingCartSidebar" command="config:set checkout/sidebar/display 0"/> - <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> - <createData entity="SimpleSubCategory" stepKey="createSubCategory"/> - - <!--Create simple products--> - <createData entity="SimpleProduct2" stepKey="simpleProduct1"> - <field key="price">10.00</field> - </createData> - <createData entity="SimpleProduct2" stepKey="simpleProduct2"> - <field key="price">50.00</field> - </createData> - - <!--Create Bundle product--> - <createData entity="BundleProductPriceViewRange" stepKey="createBundleProduct"> - <requiredEntity createDataKey="createSubCategory"/> - </createData> - <createData entity="DropDownBundleOption" stepKey="createBundleOption1_1"> - <requiredEntity createDataKey="createBundleProduct"/> - <field key="required">True</field> - </createData> - <createData entity="ApiBundleLink" stepKey="linkOptionToProduct"> - <requiredEntity createDataKey="createBundleProduct"/> - <requiredEntity createDataKey="createBundleOption1_1"/> - <requiredEntity createDataKey="simpleProduct1"/> - </createData> - <createData entity="ApiBundleLink" stepKey="linkOptionToProduct2"> - <requiredEntity createDataKey="createBundleProduct"/> - <requiredEntity createDataKey="createBundleOption1_1"/> - <requiredEntity createDataKey="simpleProduct2"/> - </createData> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> - </before> - <after> - <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> - <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> - <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> - <deleteData createDataKey="createSubCategory" stepKey="deleteCategory"/> - <magentoCLI stepKey="disableShoppingCartSidebar" command="config:set checkout/sidebar/display 1"/> - </after> - - <!--Open Product page in StoreFront and assert product and price range --> - <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> - <argument name="product" value="$$createBundleProduct$$"/> - </actionGroup> - <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible"> - <argument name="selector" value="{{StorefrontProductInfoMainSection.priceFrom}}"/> - <argument name="userInput" value="From $10.00"/> - </actionGroup> - <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible1"> - <argument name="selector" value="{{StorefrontProductInfoMainSection.priceTo}}"/> - <argument name="userInput" value="To $50.00"/> - </actionGroup> - - <!-- Add Bundle dynamic product to the cart --> - <actionGroup ref="StorefrontAddBundleProductToTheCartActionGroup" stepKey="addBundleDynamicProductToTheCart"> - <argument name="productName" value="$$simpleProduct2.name$$"/> - <argument name="quantity" value="2"/> - </actionGroup> - - <!-- Select Mini Cart, verify it doen't open --> - <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> - <dontSeeElement selector="{{StorefrontMinicartSection.viewAndEditCart}}" stepKey="dontSeeViewAndEditCart"/> - - <!--Assert Product items in cart --> - <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> - <argument name="productName" value="$$createBundleProduct.name$$"/> - <argument name="productSku" value="$$createBundleProduct.sku$$"/> - <argument name="productPrice" value="$50.00"/> - <argument name="subtotal" value="$100.00" /> - <argument name="qty" value="2"/> - </actionGroup> - - <!-- Assert Grouped product with option is displayed in cart --> - <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionTitle"> - <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> - <argument name="userInput" value="$$createBundleOption1_1.title$$"/> - </actionGroup> - <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionInCart"> - <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> - <argument name="userInput" value="1 x $$simpleProduct2.name$$ $50.00"/> - </actionGroup> - - <!--Assert Shopping Cart Summary--> - <actionGroup ref="AssertStorefrontShoppingCartSummaryWithShippingActionGroup" stepKey="AssertCartSummary" > - <argument name="subtotal" value="$100.00"/> - <argument name="shipping" value="$10.00"/> - <argument name="total" value="$110.00"/> - </actionGroup> - - <!--Enabled Shopping Cart Sidebar --> - <magentoCLI stepKey="enableShoppingCartSidebar" command="config:set checkout/sidebar/display 1"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> - <reloadPage stepKey="reloadThePage"/> - - <!--Click on mini cart--> - <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart1"/> - - <!--Assert mini cart can open and check mini cart items --> - <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProductInMiniCart1"> - <argument name="productName" value="$$createBundleProduct.name$$"/> - <argument name="productPrice" value="$50.00"/> - <argument name="cartSubtotal" value="$100.00" /> - <argument name="qty" value="2"/> - </actionGroup> - </test> -</tests> From c28268ebb89fdfbdd7d7b5ede2698d809e123cc7 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 13:41:52 -0500 Subject: [PATCH 568/585] GraphQL-630: Schema inconsistency of "AvailableShippingMethod" declaration --- .../AvailableShippingMethods.php | 46 ++++++++++++++++++- .../SelectedShippingMethod.php | 20 +++++++- .../Magento/QuoteGraphQl/etc/schema.graphqls | 8 ++-- .../GetAvailableShippingMethodsTest.php | 40 ++++++++++++---- .../Guest/GetAvailableShippingMethodsTest.php | 40 ++++++++++++---- 5 files changed, 131 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php index a9e0ba59d15d9..958934ed18032 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php @@ -7,13 +7,16 @@ namespace Magento\QuoteGraphQl\Model\Resolver\ShippingAddress; +use Magento\Directory\Model\Currency; use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\Data\ShippingMethodInterface; use Magento\Quote\Model\Cart\ShippingMethodConverter; +use Magento\Store\Model\StoreManagerInterface; /** * @inheritdoc @@ -30,16 +33,24 @@ class AvailableShippingMethods implements ResolverInterface */ private $shippingMethodConverter; + /** + * @var StoreManagerInterface + */ + private $storeManager; + /** * @param ExtensibleDataObjectConverter $dataObjectConverter * @param ShippingMethodConverter $shippingMethodConverter + * @param StoreManagerInterface $storeManager */ public function __construct( ExtensibleDataObjectConverter $dataObjectConverter, - ShippingMethodConverter $shippingMethodConverter + ShippingMethodConverter $shippingMethodConverter, + StoreManagerInterface $storeManager ) { $this->dataObjectConverter = $dataObjectConverter; $this->shippingMethodConverter = $shippingMethodConverter; + $this->storeManager = $storeManager; } /** @@ -65,13 +76,44 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $shippingRates = $address->getGroupedAllShippingRates(); foreach ($shippingRates as $carrierRates) { foreach ($carrierRates as $rate) { - $methods[] = $this->dataObjectConverter->toFlatArray( + $methodData = $this->dataObjectConverter->toFlatArray( $this->shippingMethodConverter->modelToDataObject($rate, $cart->getQuoteCurrencyCode()), [], ShippingMethodInterface::class ); + $methods[] = $this->processMoneyTypeData($methodData, $cart->getQuoteCurrencyCode()); } } return $methods; } + + /** + * Process money type data + * + * @param array $data + * @param string $quoteCurrencyCode + * @return array + * @throws NoSuchEntityException + */ + private function processMoneyTypeData(array $data, string $quoteCurrencyCode): array + { + if (isset($data['amount'])) { + $data['amount'] = ['value' => $data['amount'], 'currency' => $quoteCurrencyCode]; + } + + if (isset($data['base_amount'])) { + /** @var Currency $currency */ + $currency = $this->storeManager->getStore()->getBaseCurrency(); + $data['base_amount'] = ['value' => $data['base_amount'], 'currency' => $currency->getCode()]; + } + + if (isset($data['price_excl_tax'])) { + $data['price_excl_tax'] = ['value' => $data['price_excl_tax'], 'currency' => $quoteCurrencyCode]; + } + + if (isset($data['price_incl_tax'])) { + $data['price_incl_tax'] = ['value' => $data['price_incl_tax'], 'currency' => $quoteCurrencyCode]; + } + return $data; + } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index cd8f20c3f164f..e396d2b46494a 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -7,18 +7,34 @@ namespace Magento\QuoteGraphQl\Model\Resolver\ShippingAddress; +use Magento\Directory\Model\Currency; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Model\Quote\Address; use Magento\Quote\Model\Quote\Address\Rate; +use Magento\Store\Model\StoreManagerInterface; /** * @inheritdoc */ class SelectedShippingMethod implements ResolverInterface { + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @param StoreManagerInterface $storeManager + */ + public function __construct( + StoreManagerInterface $storeManager + ) { + $this->storeManager = $storeManager; + } + /** * @inheritdoc */ @@ -35,6 +51,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); /** @var Rate $rate */ $rate = current($rates); + /** @var Currency $currency */ + $currency = $this->storeManager->getStore()->getBaseCurrency(); $data = [ 'carrier_code' => $carrierCode, @@ -47,7 +65,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value ], 'base_amount' => [ 'value' => $address->getBaseShippingAmount(), - 'currency' => $address->getQuote()->getBaseCurrencyCode(), + 'currency' => $currency, ], ]; } else { diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index e2d29e93db574..3324ff644192a 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -243,10 +243,10 @@ type AvailableShippingMethod { method_code: String @doc(description: "Could be null if method is not available") method_title: String @doc(description: "Could be null if method is not available") error_message: String - amount: Float! - base_amount: Float @doc(description: "Could be null if method is not available") - price_excl_tax: Float! - price_incl_tax: Float! + amount: Money! + base_amount: Money @doc(description: "Could be null if method is not available") + price_excl_tax: Money! + price_incl_tax: Money! available: Boolean! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php index 2b647f61c4c63..b01921ae67ed7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php @@ -58,15 +58,27 @@ public function testGetAvailableShippingMethods() self::assertCount(1, $response['cart']['shipping_addresses'][0]['available_shipping_methods']); $expectedAddressData = [ - 'amount' => 10, - 'base_amount' => 10, + 'amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'base_amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], 'carrier_code' => 'flatrate', 'carrier_title' => 'Flat Rate', 'error_message' => '', 'method_code' => 'flatrate', 'method_title' => 'Fixed', - 'price_incl_tax' => 10, - 'price_excl_tax' => 10, + 'price_incl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'price_excl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], ]; self::assertEquals( $expectedAddressData, @@ -158,15 +170,27 @@ private function getQuery(string $maskedQuoteId): string cart (cart_id: "{$maskedQuoteId}") { shipping_addresses { available_shipping_methods { - amount - base_amount + amount { + value + currency + } + base_amount { + value + currency + } carrier_code carrier_title error_message method_code method_title - price_excl_tax - price_incl_tax + price_excl_tax { + value + currency + } + price_incl_tax { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php index a8113657eff6e..8703a690c62e3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php @@ -50,15 +50,27 @@ public function testGetAvailableShippingMethods() self::assertCount(1, $response['cart']['shipping_addresses'][0]['available_shipping_methods']); $expectedAddressData = [ - 'amount' => 10, - 'base_amount' => 10, + 'amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'base_amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], 'carrier_code' => 'flatrate', 'carrier_title' => 'Flat Rate', 'error_message' => '', 'method_code' => 'flatrate', 'method_title' => 'Fixed', - 'price_incl_tax' => 10, - 'price_excl_tax' => 10, + 'price_incl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'price_excl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], ]; self::assertEquals( $expectedAddressData, @@ -126,15 +138,27 @@ private function getQuery(string $maskedQuoteId): string cart (cart_id: "{$maskedQuoteId}") { shipping_addresses { available_shipping_methods { - amount - base_amount + amount { + value + currency + } + base_amount { + value + currency + } carrier_code carrier_title error_message method_code method_title - price_excl_tax - price_incl_tax + price_excl_tax { + value + currency + } + price_incl_tax { + value + currency + } } } } From 05ea6ef10a470a76735219e705825d896bf3c848 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 13:49:39 -0500 Subject: [PATCH 569/585] GraphQL-474: Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index 251f17619c2a8..b491b10730c10 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -132,7 +132,7 @@ private function extractCustomizableOptions(array $cartItemData): array $customizableOptionsData = []; foreach ($cartItemData['customizable_options'] as $customizableOption) { if (isset($customizableOption['value_string'])) { - $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( + $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptionValue( $customizableOption['value_string'] ); } @@ -158,10 +158,12 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb } /** + * Convert custom options vakue + * * @param string $value * @return string|array */ - private function convertCustomOptions(string $value) + private function convertCustomOptionValue(string $value) { $value = trim($value); if (substr($value, 0, 1) === "[" && From 9a01c2f2699bbd0a18dec9460cf41ce2da1dc55f Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 13:57:41 -0500 Subject: [PATCH 570/585] GraphQL-641: Schema Inconsistency of "cartItems" declaration --- .../Model/Resolver/AddSimpleProductsToCart.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php index 82ffd0970d672..cfae0e1267802 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php @@ -52,12 +52,12 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $maskedCartId = $args['input']['cart_id']; - if (!isset($args['input']['cartItems']) || empty($args['input']['cartItems']) - || !is_array($args['input']['cartItems']) + if (!isset($args['input']['cart_items']) || empty($args['input']['cart_items']) + || !is_array($args['input']['cart_items']) ) { - throw new GraphQlInputException(__('Required parameter "cartItems" is missing')); + throw new GraphQlInputException(__('Required parameter "cart_items" is missing')); } - $cartItems = $args['input']['cartItems']; + $cartItems = $args['input']['cart_items']; $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); $this->addProductsToCart->execute($cart, $cartItems); From 5523461133237ccc8011898262a447c8d26ec50a Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@adobe.com> Date: Tue, 30 Apr 2019 15:04:25 -0500 Subject: [PATCH 571/585] magento-engcom/magento2ce#2809: Suppressed static test failures --- app/code/Magento/Catalog/Model/Product/Gallery/Processor.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php index 54bef2efa5d51..e1b788bc3941b 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php @@ -157,6 +157,7 @@ public function addImage( throw new LocalizedException(__("The image doesn't exist.")); } + // phpcs:ignore Magento2.Functions.DiscouragedFunction $pathinfo = pathinfo($file); $imgExtensions = ['jpg', 'jpeg', 'gif', 'png']; if (!isset($pathinfo['extension']) || !in_array(strtolower($pathinfo['extension']), $imgExtensions)) { @@ -452,6 +453,7 @@ protected function getUniqueFileName($file, $forTmp = false) $destinationFile = $forTmp ? $this->mediaDirectory->getAbsolutePath($this->mediaConfig->getTmpMediaPath($file)) : $this->mediaDirectory->getAbsolutePath($this->mediaConfig->getMediaPath($file)); + // phpcs:ignore Magento2.Functions.DiscouragedFunction $destFile = dirname($file) . '/' . \Magento\MediaStorage\Model\File\Uploader::getNewFileName($destinationFile); } From fbed769e09f5918f507b67dfb6fd1cf49ddc6dc1 Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Tue, 30 Apr 2019 15:10:34 -0500 Subject: [PATCH 572/585] MQE-1519: Deliver weekly MTF conversion PR - Added longer wait for actionGroup, causing failures in builds due to load time --- ...ertStorefrontShoppingCartSummaryWithShippingActionGroup.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml index c4c9b9d6814d0..ca9f2afc8fbc9 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml @@ -13,7 +13,8 @@ </arguments> <waitForLoadingMaskToDisappear stepKey="waitForMaskToDisappear" after="assertSubtotal"/> <waitForElementVisible selector="{{CheckoutCartSummarySection.shipping}}" time="60" stepKey="waitForElementToBeVisible" after="waitForMaskToDisappear"/> - <wait time="5" stepKey="waitForShippingDetailsToLoad" after="waitForElementToBeVisible"/> + <!-- Shipping can take a long time to change in builds, can't rely on an explicit wait--> + <wait time="15" stepKey="waitForShippingDetailsToLoad" after="waitForElementToBeVisible"/> <see userInput="{{shipping}}" selector="{{CheckoutCartSummarySection.shipping}}" stepKey="assertShipping" after="waitForShippingDetailsToLoad" /> </actionGroup> </actionGroups> From 302e6ab75c20e8f1d0368b34308c7bba90caa272 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 30 Apr 2019 15:12:46 -0500 Subject: [PATCH 573/585] MQE-1519: Deliver weekly MTF conversion PR - Re-introduce MC-14719 because we think we may have fixed the problem elsewhere in an action group change --- ...pingCartWithDisableMiniCartSidebarTest.xml | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml new file mode 100644 index 0000000000000..afbc6216ff9ca --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddBundleDynamicProductToShoppingCartWithDisableMiniCartSidebarTest"> + <annotations> + <stories value="Shopping Cart"/> + <title value="Create Grouped product and verify mini cart action with disabled and enable Mini Cart Sidebar"/> + <description value="Create Grouped product and verify mini cart action with disabled and enable Mini Cart Sidebar"/> + <testCaseId value="MC-14719"/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <magentoCLI stepKey="disableShoppingCartSidebar" command="config:set checkout/sidebar/display 0"/> + <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> + <createData entity="SimpleSubCategory" stepKey="createSubCategory"/> + + <!--Create simple products--> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">50.00</field> + </createData> + + <!--Create Bundle product--> + <createData entity="BundleProductPriceViewRange" stepKey="createBundleProduct"> + <requiredEntity createDataKey="createSubCategory"/> + </createData> + <createData entity="DropDownBundleOption" stepKey="createBundleOption1_1"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="required">True</field> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> + <deleteData createDataKey="createSubCategory" stepKey="deleteCategory"/> + <magentoCLI stepKey="disableShoppingCartSidebar" command="config:set checkout/sidebar/display 1"/> + </after> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$createBundleProduct$$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.priceFrom}}"/> + <argument name="userInput" value="From $10.00"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seePriceRangeIsVisible1"> + <argument name="selector" value="{{StorefrontProductInfoMainSection.priceTo}}"/> + <argument name="userInput" value="To $50.00"/> + </actionGroup> + + <!-- Add Bundle dynamic product to the cart --> + <actionGroup ref="StorefrontAddBundleProductToTheCartActionGroup" stepKey="addBundleDynamicProductToTheCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + <argument name="quantity" value="2"/> + </actionGroup> + + <!-- Select Mini Cart, verify it doen't open --> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> + <dontSeeElement selector="{{StorefrontMinicartSection.viewAndEditCart}}" stepKey="dontSeeViewAndEditCart"/> + + <!--Assert Product items in cart --> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertSimpleProduct1ItemsInCheckOutCart"> + <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productSku" value="$$createBundleProduct.sku$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="subtotal" value="$100.00" /> + <argument name="qty" value="2"/> + </actionGroup> + + <!-- Assert Grouped product with option is displayed in cart --> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionTitle"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="$$createBundleOption1_1.title$$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeProductOptionInCart"> + <argument name="selector" value="{{CheckoutCartProductSection.productOptionLabel}}"/> + <argument name="userInput" value="1 x $$simpleProduct2.name$$ $50.00"/> + </actionGroup> + + <!--Assert Shopping Cart Summary--> + <actionGroup ref="AssertStorefrontShoppingCartSummaryWithShippingActionGroup" stepKey="AssertCartSummary" > + <argument name="subtotal" value="$100.00"/> + <argument name="shipping" value="$10.00"/> + <argument name="total" value="$110.00"/> + </actionGroup> + + <!--Enabled Shopping Cart Sidebar --> + <magentoCLI stepKey="enableShoppingCartSidebar" command="config:set checkout/sidebar/display 1"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <reloadPage stepKey="reloadThePage"/> + + <!--Click on mini cart--> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart1"/> + + <!--Assert mini cart can open and check mini cart items --> + <actionGroup ref="AssertStorefrontMiniCartItemsActionGroup" stepKey="assertSimpleProductInMiniCart1"> + <argument name="productName" value="$$createBundleProduct.name$$"/> + <argument name="productPrice" value="$50.00"/> + <argument name="cartSubtotal" value="$100.00" /> + <argument name="qty" value="2"/> + </actionGroup> + </test> +</tests> From a253222106d67ad7950c14d029a9de9dd59fc338 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 15:39:47 -0500 Subject: [PATCH 574/585] GraphQL-630: Schema inconsistency of "AvailableShippingMethod" declaration --- .../Resolver/ShippingAddress/SelectedShippingMethod.php | 2 +- .../GraphQl/Quote/Customer/CheckoutEndToEndTest.php | 7 +++++-- .../Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index e396d2b46494a..bf6315086ae8b 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -65,7 +65,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value ], 'base_amount' => [ 'value' => $address->getBaseShippingAmount(), - 'currency' => $currency, + 'currency' => $currency->getCode(), ], ]; } else { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index 92974f2491f75..eddc1f98d7a96 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -309,7 +309,9 @@ private function setShippingAddress(string $cartId): array available_shipping_methods { carrier_code method_code - amount + amount { + value + } } } } @@ -334,7 +336,8 @@ private function setShippingAddress(string $cartId): array self::assertNotEmpty($availableShippingMethod['method_code']); self::assertArrayHasKey('amount', $availableShippingMethod); - self::assertNotEmpty($availableShippingMethod['amount']); + self::assertArrayHasKey('value', $availableShippingMethod['amount']); + self::assertNotEmpty($availableShippingMethod['amount']['value']); return $availableShippingMethod; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index bddee2151f5cd..a95e4404a08ac 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -269,7 +269,9 @@ private function setShippingAddress(string $cartId): array available_shipping_methods { carrier_code method_code - amount + amount { + value + } } } } @@ -294,7 +296,8 @@ private function setShippingAddress(string $cartId): array self::assertNotEmpty($availableShippingMethod['method_code']); self::assertArrayHasKey('amount', $availableShippingMethod); - self::assertNotEmpty($availableShippingMethod['amount']); + self::assertArrayHasKey('value', $availableShippingMethod['amount']); + self::assertNotEmpty($availableShippingMethod['amount']['value']); return $availableShippingMethod; } From ea718482b61e2dff472491bda1a64d2faf75a713 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 15:41:30 -0500 Subject: [PATCH 575/585] GraphQL-630: Schema inconsistency of "AvailableShippingMethod" declaration --- app/code/Magento/QuoteGraphQl/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/composer.json b/app/code/Magento/QuoteGraphQl/composer.json index a3c07f7df2cee..6f4d3969d1018 100644 --- a/app/code/Magento/QuoteGraphQl/composer.json +++ b/app/code/Magento/QuoteGraphQl/composer.json @@ -11,7 +11,8 @@ "magento/module-store": "*", "magento/module-customer": "*", "magento/module-customer-graph-ql": "*", - "magento/module-sales": "*" + "magento/module-sales": "*", + "magento/module-directory": "*" }, "suggest": { "magento/module-graph-ql": "*", From 91d8a9279adab6e067422840af32eec8b7507a50 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 1 May 2019 02:12:06 +0300 Subject: [PATCH 576/585] magento/graphql-ce#646: Incorrect name of Selected Shipping Method --- .../SelectedShippingMethod.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index cd8f20c3f164f..61c535d350092 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -30,17 +30,26 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value /** @var Address $address */ $address = $value['model']; $rates = $address->getAllShippingRates(); + $carrierTitle = null; + $methodTitle = null; if (count($rates) > 0) { list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); + /** @var Rate $rate */ - $rate = current($rates); + foreach ($rates as $rate) { + if ($rate->getCode() == $address->getShippingMethod()) { + $carrierTitle = $rate->getCarrierTitle(); + $methodTitle = $rate->getMethodTitle(); + break; + } + } $data = [ 'carrier_code' => $carrierCode, 'method_code' => $methodCode, - 'carrier_title' => $rate->getCarrierTitle(), - 'method_title' => $rate->getMethodTitle(), + 'carrier_title' => $carrierTitle, + 'method_title' => $methodTitle, 'amount' => [ 'value' => $address->getShippingAmount(), 'currency' => $address->getQuote()->getQuoteCurrencyCode(), @@ -54,8 +63,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $data = [ 'carrier_code' => null, 'method_code' => null, - 'carrier_title' => null, - 'method_title' => null, + 'carrier_title' => $carrierTitle, + 'method_title' => $methodTitle, 'amount' => null, 'base_amount' => null, ]; From 8a65e48c2414f7516b0c6444525dc078c8a9b392 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 1 May 2019 10:29:41 +0300 Subject: [PATCH 577/585] graphQl-640: fixed input type declaration for PaymentMethodAdditionalDataInput and SelectedPaymentMethodAdditionalData --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index e2d29e93db574..800d0582ff6d4 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -134,8 +134,7 @@ input PaymentMethodInput { purchase_order_number: String @doc(description:"Purchase order number") } -input PaymentMethodAdditionalDataInput { -} +input PaymentMethodAdditionalDataInput input SetGuestEmailOnCartInput { cart_id: String! @@ -262,8 +261,7 @@ type SelectedPaymentMethod { purchase_order_number: String @doc(description: "The purchase order number.") } -type SelectedPaymentMethodAdditionalData { -} +type SelectedPaymentMethodAdditionalData type AppliedCoupon { code: String! From 98b1d3ca49f07f85359848e7459189c423069591 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 1 May 2019 11:53:22 +0300 Subject: [PATCH 578/585] magento/graphql-ce#649: GetSpecifiedBillingAddressTest fix misspelling --- .../Quote/Customer/GetSpecifiedBillingAddressTest.php | 10 +++++----- .../Quote/Guest/GetSpecifiedBillingAddressTest.php | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php index 1ff5ddbde54ec..b6dde46871cbb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php @@ -44,7 +44,7 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddress() + public function testGetSpecifiedBillingAddress() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); @@ -83,7 +83,7 @@ public function testGeSpecifiedBillingAddress() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ - public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() + public function testGetSpecifiedBillingAddressIfBillingAddressIsNotSet() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); @@ -121,7 +121,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() * @expectedException \Exception * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ - public function testGeSpecifiedBillingAddressOfNonExistentCart() + public function testGetSpecifiedBillingAddressOfNonExistentCart() { $maskedQuoteId = 'non_existent_masked_id'; $query = $this->getQuery($maskedQuoteId); @@ -137,7 +137,7 @@ public function testGeSpecifiedBillingAddressOfNonExistentCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddressFromAnotherGuestCart() + public function testGetSpecifiedBillingAddressFromAnotherGuestCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); @@ -155,7 +155,7 @@ public function testGeSpecifiedBillingAddressFromAnotherGuestCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddressFromAnotherCustomerCart() + public function testGetSpecifiedBillingAddressFromAnotherCustomerCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php index 48bff73226894..8ddf1641ede8a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php @@ -36,7 +36,7 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddress() + public function testGetSpecifiedBillingAddress() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); @@ -73,7 +73,7 @@ public function testGeSpecifiedBillingAddress() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ - public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() + public function testGetSpecifiedBillingAddressIfBillingAddressIsNotSet() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); From ac76e2ef674fcb4bb9b1b1054cb9c7841762efee Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 1 May 2019 13:10:45 +0300 Subject: [PATCH 579/585] magento/graphql-ce#602: [Test Coverage] Get Specified shipping address --- .../GetSpecifiedShippingAddressTest.php | 219 ++++++++++++++++++ .../Guest/GetSpecifiedShippingAddressTest.php | 170 ++++++++++++++ 2 files changed, 389 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php new file mode 100644 index 0000000000000..766dd102b749c --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php @@ -0,0 +1,219 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for get specified shipping address + */ +class GetSpecifiedShippingAddressTest extends GraphQlAbstract +{ + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddress() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => 'John', + 'lastname' => 'Smith', + 'company' => 'CompanyName', + 'street' => [ + 'Green str, 67' + ], + 'city' => 'CityM', + 'region' => [ + 'code' => 'AL', + 'label' => 'Alabama', + ], + 'postcode' => '75477', + 'country' => [ + 'code' => 'US', + 'label' => 'US', + ], + 'telephone' => '3468676', + '__typename' => 'ShippingCartAddress', + 'customer_notes' => null, + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testGetSpecifiedShippingAddressIfShippingAddressIsNotSet() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => null, + 'lastname' => null, + 'company' => null, + 'street' => [ + '' + ], + 'city' => null, + 'region' => [ + 'code' => null, + 'label' => null, + ], + 'postcode' => null, + 'country' => [ + 'code' => null, + 'label' => null, + ], + 'telephone' => null, + '__typename' => 'ShippingCartAddress', + 'customer_notes' => null, + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" + */ + public function testGetSpecifiedShippingAddressOfNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddressFromAnotherGuestCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery($this->getQuery($maskedQuoteId), [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddressFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery( + $this->getQuery($maskedQuoteId), + [], + '', + $this->getHeaderMap('customer2@search.example.com') + ); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id: "$maskedQuoteId") { + shipping_addresses { + firstname + lastname + company + street + city + region + { + code + label + } + postcode + country + { + code + label + } + telephone + __typename + customer_notes + } + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php new file mode 100644 index 0000000000000..3b96a873bdb81 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php @@ -0,0 +1,170 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for get specified shipping address + */ +class GetSpecifiedShippingAddressTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddress() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => 'John', + 'lastname' => 'Smith', + 'company' => 'CompanyName', + 'street' => [ + 'Green str, 67' + ], + 'city' => 'CityM', + 'region' => [ + 'code' => 'AL', + 'label' => 'Alabama', + ], + 'postcode' => '75477', + 'country' => [ + 'code' => 'US', + 'label' => 'US', + ], + 'telephone' => '3468676', + '__typename' => 'ShippingCartAddress', + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testGetSpecifiedShippingAddressIfShippingAddressIsNotSet() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => null, + 'lastname' => null, + 'company' => null, + 'street' => [ + '' + ], + 'city' => null, + 'region' => [ + 'code' => null, + 'label' => null, + ], + 'postcode' => null, + 'country' => [ + 'code' => null, + 'label' => null, + ], + 'telephone' => null, + '__typename' => 'ShippingCartAddress', + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" + */ + public function testGetShippingAddressOfNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetShippingAddressFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id: "$maskedQuoteId") { + shipping_addresses { + firstname + lastname + company + street + city + region + { + code + label + } + postcode + country + { + code + label + } + telephone + __typename + } + } +} +QUERY; + } +} From 6bd7e484775716d475f9a86913af64112745bb34 Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Wed, 1 May 2019 16:01:53 +0300 Subject: [PATCH 580/585] Added Test coverage for "Get Selected payment method" --- .../Customer/GetSelectedPaymentMethodTest.php | 143 ++++++++++++++++++ .../Guest/GetSelectedPaymentMethodTest.php | 105 +++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php new file mode 100644 index 0000000000000..d876d74de661b --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php @@ -0,0 +1,143 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for getting selected payment method from cart + */ +class GetSelectedPaymentMethodTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testGetSelectedPaymentMethod() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + $this->assertArrayHasKey('cart', $response); + $this->assertArrayHasKey('selected_payment_method', $response['cart']); + $this->assertArrayHasKey('code', $response['cart']['selected_payment_method']); + $this->assertEquals('checkmo', $response['cart']['selected_payment_method']['code']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + */ + public function testGetSelectedPaymentMethodFromNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + 'Could not find a cart with ID "non_existent_masked_id"' + ); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testGetSelectedPaymentMethodFromGuestCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testGetSelectedPaymentMethodFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" + ); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer3@search.example.com')); + } + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id:"$maskedQuoteId") { + selected_payment_method { + code + } + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + * @throws \Magento\Framework\Exception\AuthenticationException + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php new file mode 100644 index 0000000000000..ef04da88ea67a --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php @@ -0,0 +1,105 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for getting selected payment method from cart + */ +class GetSelectedPaymentMethodTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + * + */ + public function testGetSelectedPaymentMethod() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('cart', $response); + $this->assertArrayHasKey('selected_payment_method', $response['cart']); + $this->assertArrayHasKey('code', $response['cart']['selected_payment_method']); + $this->assertEquals('checkmo', $response['cart']['selected_payment_method']['code']); + } + + /** + * @expectedException \Exception + */ + public function testGetSelectedPaymentMethodFromNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + 'Could not find a cart with ID "non_existent_masked_id"' + ); + + $this->graphQlQuery($query); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testGetSelectedPaymentMethodFromCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" + ); + + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id:"$maskedQuoteId") { + selected_payment_method { + code + } + } +} +QUERY; + } +} From 8a9422b86c43c90d261dfe366c6bd6306ea616c1 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Wed, 1 May 2019 10:20:30 -0500 Subject: [PATCH 581/585] MQE-1519: Deliver weekly MTF conversion PR - Increase wait from 15 to 30 for shipping on cart page --- ...sertStorefrontShoppingCartSummaryWithShippingActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml index ca9f2afc8fbc9..5eb3de3a1af82 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml @@ -14,7 +14,7 @@ <waitForLoadingMaskToDisappear stepKey="waitForMaskToDisappear" after="assertSubtotal"/> <waitForElementVisible selector="{{CheckoutCartSummarySection.shipping}}" time="60" stepKey="waitForElementToBeVisible" after="waitForMaskToDisappear"/> <!-- Shipping can take a long time to change in builds, can't rely on an explicit wait--> - <wait time="15" stepKey="waitForShippingDetailsToLoad" after="waitForElementToBeVisible"/> + <wait time="30" stepKey="waitForShippingDetailsToLoad" after="waitForElementToBeVisible"/> <see userInput="{{shipping}}" selector="{{CheckoutCartSummarySection.shipping}}" stepKey="assertShipping" after="waitForShippingDetailsToLoad" /> </actionGroup> </actionGroups> From 30b049d6be5475d651b0400c9f07b2a1a2961485 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 13:15:09 -0500 Subject: [PATCH 582/585] GraphQL-602: [Test Coverage] Get Specified shipping address --- .../GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php | 2 +- .../GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php index 766dd102b749c..de3c384e65783 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php @@ -137,7 +137,7 @@ public function testGetSpecifiedShippingAddressOfNonExistentCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php */ - public function testGetSpecifiedShippingAddressFromAnotherGuestCart() + public function testGetSpecifiedShippingAddressFromGuestCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php index 3b96a873bdb81..f71915bab650f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php @@ -117,13 +117,14 @@ public function testGetShippingAddressOfNonExistentCart() } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php */ - public function testGetShippingAddressFromAnotherCustomerCart() + public function testGetShippingAddressFromCustomerCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); From 64e76c4888f8baae719791ed2787b9f0948562b4 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 13:29:31 -0500 Subject: [PATCH 583/585] GraphQL-646: Incorrect name of Selected Shipping Method --- .../Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index c50ae0a70380e..7de689a6ad0f5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -116,6 +116,7 @@ public function testSetUpsShippingMethod(string $methodCode, string $methodTitle self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -171,6 +172,7 @@ public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** From 0959569c5b159b670bc9d46d48da8e52f6741a8b Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 15:14:05 -0500 Subject: [PATCH 584/585] GraphQL-640: Input type declaration in GraphQL SDL cannot be empty --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 800d0582ff6d4..e87a5f4fc1d49 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -130,12 +130,9 @@ input SetPaymentMethodOnCartInput { input PaymentMethodInput { code: String! @doc(description:"Payment method code") - additional_data: PaymentMethodAdditionalDataInput @doc(description:"Additional payment data") purchase_order_number: String @doc(description:"Purchase order number") } -input PaymentMethodAdditionalDataInput - input SetGuestEmailOnCartInput { cart_id: String! email: String! @@ -257,12 +254,9 @@ type AvailablePaymentMethod { type SelectedPaymentMethod { code: String! @doc(description: "The payment method code") title: String! @doc(description: "The payment method title.") - additional_data: SelectedPaymentMethodAdditionalData @doc(description: "Additional payment data") purchase_order_number: String @doc(description: "The purchase order number.") } -type SelectedPaymentMethodAdditionalData - type AppliedCoupon { code: String! } From 9359cca6c7ced8511117e4e88bcafb6c942c5644 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 19:56:25 -0500 Subject: [PATCH 585/585] GraphQL-641: Schema Inconsistency of "cartItems" declaration --- setup/performance-toolkit/benchmark.jmx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 0609be4d7d193..a8a7e419373b8 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -41347,7 +41347,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41567,7 +41567,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41739,7 +41739,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42045,7 +42045,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42303,7 +42303,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42609,7 +42609,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42867,7 +42867,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43094,7 +43094,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43959,7 +43959,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -44019,7 +44019,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp>