diff --git a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less
index f2b9c9274bbcf..1be46c8239ee2 100644
--- a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less
+++ b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less
@@ -398,6 +398,17 @@
&.orders-recent {
&:extend(.abs-account-table-margin-mobile all);
&:extend(.abs-no-border-top all);
+ .table-order-items {
+ &.table {
+ tbody {
+ > tr {
+ > td.col {
+ padding-left: 0;
+ }
+ }
+ }
+ }
+ }
}
}
diff --git a/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less
index 4d990a82cb7e4..1f1ea93d0b54a 100644
--- a/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less
+++ b/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less
@@ -453,7 +453,7 @@
}
}
-.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
.logo {
margin-bottom: 13px;
margin-top: 4px;
diff --git a/app/etc/di.xml b/app/etc/di.xml
index 19543375aad58..d0b45ea16c855 100755
--- a/app/etc/di.xml
+++ b/app/etc/di.xml
@@ -38,7 +38,7 @@
-
+
@@ -1757,4 +1757,11 @@
+
+
+ Magento\Framework\Lock\Backend\Cache
+ 10000
+ 20
+
+
diff --git a/composer.json b/composer.json
index 9ef896c7e72cc..50b22238e0d01 100644
--- a/composer.json
+++ b/composer.json
@@ -181,6 +181,8 @@
"magento/module-media-storage": "*",
"magento/module-message-queue": "*",
"magento/module-msrp": "*",
+ "magento/module-msrp-configurable-product": "*",
+ "magento/module-msrp-grouped-product": "*",
"magento/module-multishipping": "*",
"magento/module-mysql-mq": "*",
"magento/module-new-relic-reporting": "*",
diff --git a/composer.lock b/composer.lock
index 84e89277a95db..a7131f4a16eec 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": "3cdccc93cc990b4212377b1d01a8c4ef",
+ "content-hash": "60007664938710edf52eadddd7551867",
"packages": [
{
"name": "braintree/braintree_php",
@@ -257,16 +257,16 @@
},
{
"name": "composer/composer",
- "version": "1.8.3",
+ "version": "1.8.4",
"source": {
"type": "git",
"url": "https://github.com/composer/composer.git",
- "reference": "a6a3b44581398b7135c7baa0557b7c5b10808b47"
+ "reference": "bc364c2480c17941e2135cfc568fa41794392534"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/composer/zipball/a6a3b44581398b7135c7baa0557b7c5b10808b47",
- "reference": "a6a3b44581398b7135c7baa0557b7c5b10808b47",
+ "url": "https://api.github.com/repos/composer/composer/zipball/bc364c2480c17941e2135cfc568fa41794392534",
+ "reference": "bc364c2480c17941e2135cfc568fa41794392534",
"shasum": ""
},
"require": {
@@ -333,7 +333,7 @@
"dependency",
"package"
],
- "time": "2019-01-30T07:31:34+00:00"
+ "time": "2019-02-11T09:52:10+00:00"
},
{
"name": "composer/semver",
@@ -1912,7 +1912,7 @@
},
{
"name": "symfony/css-selector",
- "version": "v4.2.3",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
@@ -2028,16 +2028,16 @@
},
{
"name": "symfony/filesystem",
- "version": "v4.2.3",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "7c16ebc2629827d4ec915a52ac809768d060a4ee"
+ "reference": "e16b9e471703b2c60b95f14d31c1239f68f11601"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/7c16ebc2629827d4ec915a52ac809768d060a4ee",
- "reference": "7c16ebc2629827d4ec915a52ac809768d060a4ee",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/e16b9e471703b2c60b95f14d31c1239f68f11601",
+ "reference": "e16b9e471703b2c60b95f14d31c1239f68f11601",
"shasum": ""
},
"require": {
@@ -2074,20 +2074,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2019-01-16T20:35:37+00:00"
+ "time": "2019-02-07T11:40:08+00:00"
},
{
"name": "symfony/finder",
- "version": "v4.2.3",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "ef71816cbb264988bb57fe6a73f610888b9aa70c"
+ "reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/ef71816cbb264988bb57fe6a73f610888b9aa70c",
- "reference": "ef71816cbb264988bb57fe6a73f610888b9aa70c",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/267b7002c1b70ea80db0833c3afe05f0fbde580a",
+ "reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a",
"shasum": ""
},
"require": {
@@ -2123,7 +2123,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2019-01-16T20:35:37+00:00"
+ "time": "2019-02-23T15:42:05+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -2753,16 +2753,16 @@
},
{
"name": "zendframework/zend-db",
- "version": "2.9.3",
+ "version": "2.10.0",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-db.git",
- "reference": "5b4f2c42f94c9f7f4b2f456a0ebe459fab12b3d9"
+ "reference": "77022f06f6ffd384fa86d22ab8d8bbdb925a1e8e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/zendframework/zend-db/zipball/5b4f2c42f94c9f7f4b2f456a0ebe459fab12b3d9",
- "reference": "5b4f2c42f94c9f7f4b2f456a0ebe459fab12b3d9",
+ "url": "https://api.github.com/repos/zendframework/zend-db/zipball/77022f06f6ffd384fa86d22ab8d8bbdb925a1e8e",
+ "reference": "77022f06f6ffd384fa86d22ab8d8bbdb925a1e8e",
"shasum": ""
},
"require": {
@@ -2773,7 +2773,7 @@
"phpunit/phpunit": "^5.7.25 || ^6.4.4",
"zendframework/zend-coding-standard": "~1.0.0",
"zendframework/zend-eventmanager": "^2.6.2 || ^3.0",
- "zendframework/zend-hydrator": "^1.1 || ^2.1",
+ "zendframework/zend-hydrator": "^1.1 || ^2.1 || ^3.0",
"zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3"
},
"suggest": {
@@ -2807,7 +2807,7 @@
"db",
"zf"
],
- "time": "2018-04-09T13:21:36+00:00"
+ "time": "2019-02-25T11:37:45+00:00"
},
{
"name": "zendframework/zend-di",
@@ -4377,16 +4377,16 @@
},
{
"name": "zendframework/zend-uri",
- "version": "2.6.1",
+ "version": "2.7.0",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-uri.git",
- "reference": "3b6463645c6766f78ce537c70cb4fdabee1e725f"
+ "reference": "b2785cd38fe379a784645449db86f21b7739b1ee"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/zendframework/zend-uri/zipball/3b6463645c6766f78ce537c70cb4fdabee1e725f",
- "reference": "3b6463645c6766f78ce537c70cb4fdabee1e725f",
+ "url": "https://api.github.com/repos/zendframework/zend-uri/zipball/b2785cd38fe379a784645449db86f21b7739b1ee",
+ "reference": "b2785cd38fe379a784645449db86f21b7739b1ee",
"shasum": ""
},
"require": {
@@ -4401,8 +4401,8 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.6.x-dev",
- "dev-develop": "2.7.x-dev"
+ "dev-master": "2.7.x-dev",
+ "dev-develop": "2.8.x-dev"
}
},
"autoload": {
@@ -4420,7 +4420,7 @@
"uri",
"zf"
],
- "time": "2018-04-30T13:40:08+00:00"
+ "time": "2019-02-27T21:39:04+00:00"
},
{
"name": "zendframework/zend-validator",
@@ -4889,16 +4889,16 @@
},
{
"name": "codeception/phpunit-wrapper",
- "version": "6.5.1",
+ "version": "6.6.1",
"source": {
"type": "git",
"url": "https://github.com/Codeception/phpunit-wrapper.git",
- "reference": "d78f9eb9c4300a5924cc27dee03e8c1a96fcf5f3"
+ "reference": "d0da25a98bcebeb15d97c2ad3b2de6166b6e7a0c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/d78f9eb9c4300a5924cc27dee03e8c1a96fcf5f3",
- "reference": "d78f9eb9c4300a5924cc27dee03e8c1a96fcf5f3",
+ "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/d0da25a98bcebeb15d97c2ad3b2de6166b6e7a0c",
+ "reference": "d0da25a98bcebeb15d97c2ad3b2de6166b6e7a0c",
"shasum": ""
},
"require": {
@@ -4912,7 +4912,7 @@
},
"require-dev": {
"codeception/specify": "*",
- "vlucas/phpdotenv": "^2.4"
+ "vlucas/phpdotenv": "^3.0"
},
"type": "library",
"autoload": {
@@ -4931,24 +4931,24 @@
}
],
"description": "PHPUnit classes used by Codeception",
- "time": "2019-01-13T10:34:55+00:00"
+ "time": "2019-02-26T20:47:39+00:00"
},
{
"name": "codeception/stub",
- "version": "2.0.4",
+ "version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/Codeception/Stub.git",
- "reference": "f50bc271f392a2836ff80690ce0c058efe1ae03e"
+ "reference": "853657f988942f7afb69becf3fd0059f192c705a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Codeception/Stub/zipball/f50bc271f392a2836ff80690ce0c058efe1ae03e",
- "reference": "f50bc271f392a2836ff80690ce0c058efe1ae03e",
+ "url": "https://api.github.com/repos/Codeception/Stub/zipball/853657f988942f7afb69becf3fd0059f192c705a",
+ "reference": "853657f988942f7afb69becf3fd0059f192c705a",
"shasum": ""
},
"require": {
- "phpunit/phpunit": ">=4.8 <8.0"
+ "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.0.3"
},
"type": "library",
"autoload": {
@@ -4961,7 +4961,7 @@
"MIT"
],
"description": "Flexible Stub wrapper for PHPUnit's Mock Builder",
- "time": "2018-07-26T11:55:37+00:00"
+ "time": "2019-03-02T15:35:10+00:00"
},
{
"name": "consolidation/annotated-command",
@@ -5061,16 +5061,16 @@
},
{
"name": "consolidation/config",
- "version": "1.1.1",
+ "version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/consolidation/config.git",
- "reference": "925231dfff32f05b787e1fddb265e789b939cf4c"
+ "reference": "cac1279bae7efb5c7fb2ca4c3ba4b8eb741a96c1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/consolidation/config/zipball/925231dfff32f05b787e1fddb265e789b939cf4c",
- "reference": "925231dfff32f05b787e1fddb265e789b939cf4c",
+ "url": "https://api.github.com/repos/consolidation/config/zipball/cac1279bae7efb5c7fb2ca4c3ba4b8eb741a96c1",
+ "reference": "cac1279bae7efb5c7fb2ca4c3ba4b8eb741a96c1",
"shasum": ""
},
"require": {
@@ -5079,9 +5079,9 @@
"php": ">=5.4.0"
},
"require-dev": {
- "g1a/composer-test-scenarios": "^1",
+ "g1a/composer-test-scenarios": "^3",
+ "php-coveralls/php-coveralls": "^1",
"phpunit/phpunit": "^5",
- "satooshi/php-coveralls": "^1.0",
"squizlabs/php_codesniffer": "2.*",
"symfony/console": "^2.5|^3|^4",
"symfony/yaml": "^2.8.11|^3|^4"
@@ -5091,6 +5091,33 @@
},
"type": "library",
"extra": {
+ "scenarios": {
+ "symfony4": {
+ "require-dev": {
+ "symfony/console": "^4.0"
+ },
+ "config": {
+ "platform": {
+ "php": "7.1.3"
+ }
+ }
+ },
+ "symfony2": {
+ "require-dev": {
+ "symfony/console": "^2.8",
+ "symfony/event-dispatcher": "^2.8",
+ "phpunit/phpunit": "^4.8.36"
+ },
+ "remove": [
+ "php-coveralls/php-coveralls"
+ ],
+ "config": {
+ "platform": {
+ "php": "5.4.8"
+ }
+ }
+ }
+ },
"branch-alias": {
"dev-master": "1.x-dev"
}
@@ -5111,7 +5138,7 @@
}
],
"description": "Provide configuration services for a commandline tool.",
- "time": "2018-10-24T17:55:35+00:00"
+ "time": "2019-03-03T19:37:04+00:00"
},
{
"name": "consolidation/log",
@@ -5261,16 +5288,16 @@
},
{
"name": "consolidation/robo",
- "version": "1.4.4",
+ "version": "1.4.6",
"source": {
"type": "git",
"url": "https://github.com/consolidation/Robo.git",
- "reference": "8bec6a6ea54a7d03d56552a4250c49dec3b3083d"
+ "reference": "d4805a1abbc730e9a6d64ede2eba56f91a2b4eb3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/consolidation/Robo/zipball/8bec6a6ea54a7d03d56552a4250c49dec3b3083d",
- "reference": "8bec6a6ea54a7d03d56552a4250c49dec3b3083d",
+ "url": "https://api.github.com/repos/consolidation/Robo/zipball/d4805a1abbc730e9a6d64ede2eba56f91a2b4eb3",
+ "reference": "d4805a1abbc730e9a6d64ede2eba56f91a2b4eb3",
"shasum": ""
},
"require": {
@@ -5365,7 +5392,7 @@
}
],
"description": "Modern task runner",
- "time": "2019-02-08T20:59:23+00:00"
+ "time": "2019-02-17T05:32:27+00:00"
},
{
"name": "consolidation/self-update",
@@ -8559,16 +8586,16 @@
},
{
"name": "symfony/browser-kit",
- "version": "v4.2.3",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
- "reference": "ee4462581eb54bf34b746e4a5d522a4f21620160"
+ "reference": "61d85c5af2fc058014c7c89504c3944e73a086f0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/browser-kit/zipball/ee4462581eb54bf34b746e4a5d522a4f21620160",
- "reference": "ee4462581eb54bf34b746e4a5d522a4f21620160",
+ "url": "https://api.github.com/repos/symfony/browser-kit/zipball/61d85c5af2fc058014c7c89504c3944e73a086f0",
+ "reference": "61d85c5af2fc058014c7c89504c3944e73a086f0",
"shasum": ""
},
"require": {
@@ -8612,20 +8639,20 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
- "time": "2019-01-16T21:31:25+00:00"
+ "time": "2019-02-23T15:17:42+00:00"
},
{
"name": "symfony/config",
- "version": "v4.2.3",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "25a2e7abe0d97e70282537292e3df45cf6da7b98"
+ "reference": "7f70d79c7a24a94f8e98abb988049403a53d7b31"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/25a2e7abe0d97e70282537292e3df45cf6da7b98",
- "reference": "25a2e7abe0d97e70282537292e3df45cf6da7b98",
+ "url": "https://api.github.com/repos/symfony/config/zipball/7f70d79c7a24a94f8e98abb988049403a53d7b31",
+ "reference": "7f70d79c7a24a94f8e98abb988049403a53d7b31",
"shasum": ""
},
"require": {
@@ -8675,7 +8702,7 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
- "time": "2019-01-30T11:44:30+00:00"
+ "time": "2019-02-23T15:17:42+00:00"
},
{
"name": "symfony/contracts",
@@ -8747,16 +8774,16 @@
},
{
"name": "symfony/dependency-injection",
- "version": "v4.2.3",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "72c14cbc0c27706b9b4c33b9cd7a280972ff4806"
+ "reference": "cdadb3765df7c89ac93628743913b92bb91f1704"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/72c14cbc0c27706b9b4c33b9cd7a280972ff4806",
- "reference": "72c14cbc0c27706b9b4c33b9cd7a280972ff4806",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/cdadb3765df7c89ac93628743913b92bb91f1704",
+ "reference": "cdadb3765df7c89ac93628743913b92bb91f1704",
"shasum": ""
},
"require": {
@@ -8816,20 +8843,20 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
- "time": "2019-01-30T17:51:38+00:00"
+ "time": "2019-02-23T15:17:42+00:00"
},
{
"name": "symfony/dom-crawler",
- "version": "v4.2.3",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
- "reference": "d8476760b04cdf7b499c8718aa437c20a9155103"
+ "reference": "53c97769814c80a84a8403efcf3ae7ae966d53bb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/d8476760b04cdf7b499c8718aa437c20a9155103",
- "reference": "d8476760b04cdf7b499c8718aa437c20a9155103",
+ "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/53c97769814c80a84a8403efcf3ae7ae966d53bb",
+ "reference": "53c97769814c80a84a8403efcf3ae7ae966d53bb",
"shasum": ""
},
"require": {
@@ -8873,20 +8900,20 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
- "time": "2019-01-16T20:35:37+00:00"
+ "time": "2019-02-23T15:17:42+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v4.2.3",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "8d2318b73e0a1bc75baa699d00ebe2ae8b595a39"
+ "reference": "850a667d6254ccf6c61d853407b16f21c4579c77"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8d2318b73e0a1bc75baa699d00ebe2ae8b595a39",
- "reference": "8d2318b73e0a1bc75baa699d00ebe2ae8b595a39",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/850a667d6254ccf6c61d853407b16f21c4579c77",
+ "reference": "850a667d6254ccf6c61d853407b16f21c4579c77",
"shasum": ""
},
"require": {
@@ -8927,20 +8954,20 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
- "time": "2019-01-29T09:49:29+00:00"
+ "time": "2019-02-26T08:03:39+00:00"
},
{
"name": "symfony/options-resolver",
- "version": "v4.2.3",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
- "reference": "831b272963a8aa5a0613a1a7f013322d8161bbbb"
+ "reference": "3896e5a7d06fd15fa4947694c8dcdd371ff147d1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/831b272963a8aa5a0613a1a7f013322d8161bbbb",
- "reference": "831b272963a8aa5a0613a1a7f013322d8161bbbb",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/3896e5a7d06fd15fa4947694c8dcdd371ff147d1",
+ "reference": "3896e5a7d06fd15fa4947694c8dcdd371ff147d1",
"shasum": ""
},
"require": {
@@ -8981,7 +9008,7 @@
"configuration",
"options"
],
- "time": "2019-01-16T21:31:25+00:00"
+ "time": "2019-02-23T15:17:42+00:00"
},
{
"name": "symfony/polyfill-php70",
@@ -9099,7 +9126,7 @@
},
{
"name": "symfony/stopwatch",
- "version": "v4.2.3",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
@@ -9149,16 +9176,16 @@
},
{
"name": "symfony/yaml",
- "version": "v3.4.22",
+ "version": "v3.4.23",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "ba11776e9e6c15ad5759a07bffb15899bac75c2d"
+ "reference": "57f1ce82c997f5a8701b89ef970e36bb657fd09c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/ba11776e9e6c15ad5759a07bffb15899bac75c2d",
- "reference": "ba11776e9e6c15ad5759a07bffb15899bac75c2d",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/57f1ce82c997f5a8701b89ef970e36bb657fd09c",
+ "reference": "57f1ce82c997f5a8701b89ef970e36bb657fd09c",
"shasum": ""
},
"require": {
@@ -9204,7 +9231,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
- "time": "2019-01-16T10:59:17+00:00"
+ "time": "2019-02-23T15:06:07+00:00"
},
{
"name": "theseer/fdomdocument",
diff --git a/dev/tests/acceptance/tests/_data/catalog_import_products.csv b/dev/tests/acceptance/tests/_data/catalog_import_products.csv
new file mode 100644
index 0000000000000..7732f15d4ce3a
--- /dev/null
+++ b/dev/tests/acceptance/tests/_data/catalog_import_products.csv
@@ -0,0 +1,4 @@
+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_label,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,related_position,crosssell_skus,crosssell_position,upsell_skus,upsell_position,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,bundle_shipment_type,configurable_variations,configurable_variation_labels,associated_skus
+SimpleProductForTest1,,Default,simple,"Default","base,second_website",SimpleProductAfterImport1,,,1.0000,1,"Taxable Goods","Catalog, Search",250.0000,,,,simple-product-for-test-1,,,,,,,,,,,,"3/4/19, 5:53 AM","3/4/19, 4:47 PM",,,"Block after Info Column",,,,,,,,,,,"Use config",,,100.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,,,,,,,,,,,,,,,,,,,
+SimpleProductForTest2,,Default,simple,"Default",base,SimpleProductAfterImport2,,,1.0000,1,"Taxable Goods","Catalog, Search",300.0000,,,,simple-product-for-test-2,,,,,,,,,,,,"3/4/19, 5:53 AM","3/4/19, 4:47 PM",,,"Block after Info Column",,,,,,,,,,,"Use config",,,100.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,,,,,,,,,,,,,,,,,,,
+SimpleProductForTest3,,Default,simple,"Default","base,second_website",SimpleProductAfterImport3,,,1.0000,1,"Taxable Goods","Catalog, Search",350.0000,,,,simple-product-for-test-3,,,,,,,,,,,,"3/4/19, 5:53 AM","3/4/19, 4:47 PM",,,"Block after Info Column",,,,,,,,,,,"Use config",,,100.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,,,,,,,,,,,,,,,,,,,
\ No newline at end of file
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryProductsVariantsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryProductsVariantsTest.php
index 1419aff867d2d..f62be7328481c 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryProductsVariantsTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryProductsVariantsTest.php
@@ -18,14 +18,11 @@
class CategoryProductsVariantsTest extends GraphQlAbstract
{
/**
- *
* @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function testGetSimpleProductsFromCategory()
{
- $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/360');
-
$query
= <<objectManager->create(
- \Magento\Integration\Api\CustomerTokenServiceInterface::class
- );
- $customerToken = $customerTokenService->createCustomerAccessToken('customer@example.com', 'password');
- $headerMap = ['Authorization' => 'Bearer ' . $customerToken];
- $response = $this->graphQlQuery($query, [], '', $headerMap);
+ $response = $this->graphQlQuery($query);
$responseDataObject = new DataObject($response);
//Some sort of smoke testing
self::assertEquals(
@@ -111,39 +104,37 @@ public function testCategoriesTree()
}
/**
- * @magentoApiDataFixture Magento/Customer/_files/customer.php
* @magentoApiDataFixture Magento/Catalog/_files/categories.php
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function testGetCategoryById()
{
- $rootCategoryId = 13;
+ $categoryId = 13;
$query = <<objectManager->create(
- \Magento\Integration\Api\CustomerTokenServiceInterface::class
- );
- $customerToken = $customerTokenService->createCustomerAccessToken('customer@example.com', 'password');
- $headerMap = ['Authorization' => 'Bearer ' . $customerToken];
- $response = $this->graphQlQuery($query, [], '', $headerMap);
- $responseDataObject = new DataObject($response);
- //Some sort of smoke testing
- self::assertEquals(
- 'Category 1.2',
- $responseDataObject->getData('category/name')
- );
- self::assertEquals(
- 13,
- $responseDataObject->getData('category/id')
- );
+ $response = $this->graphQlQuery($query);
+ self::assertEquals('Category 1.2', $response['category']['name']);
+ self::assertEquals(13, $response['category']['id']);
+ }
+
+ public function testNonExistentCategoryWithProductCount()
+ {
+ $query = <<expectException(ResponseContainsErrorsException::class);
+ $this->expectExceptionMessage('GraphQL response contains errors: Category doesn\'t exist');
+ $this->graphQlQuery($query);
}
/**
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php
index a7c83aba89f0a..e517b22ad09de 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php
@@ -137,6 +137,26 @@ public function testQueryAllFieldsSimpleProduct()
sort_order
}
}
+ ... on CustomizableCheckboxOption {
+ checkbox_option: value {
+ option_type_id
+ sku
+ price
+ price_type
+ title
+ sort_order
+ }
+ }
+ ... on CustomizableMultipleOption {
+ multiple_option: value {
+ option_type_id
+ sku
+ price
+ price_type
+ title
+ sort_order
+ }
+ }
...on CustomizableFileOption {
product_sku
file_option: value {
@@ -736,7 +756,7 @@ private function assertOptions($product, $actualResponse)
$values = $option->getValues();
/** @var \Magento\Catalog\Model\Product\Option\Value $value */
$value = current($values);
- $findValueKeyName = $option->getType() === 'radio' ? 'radio_option' : 'drop_down_option';
+ $findValueKeyName = $option->getType() . '_option';
if ($value->getTitle() === $optionsArray[$findValueKeyName][0]['title']) {
$match = true;
}
@@ -756,7 +776,7 @@ private function assertOptions($product, $actualResponse)
];
if (!empty($option->getValues())) {
- $valueKeyName = $option->getType() === 'radio' ? 'radio_option' : 'drop_down_option';
+ $valueKeyName = $option->getType() . '_option';
$value = current($optionsArray[$valueKeyName]);
/** @var \Magento\Catalog\Model\Product\Option\Value $productValue */
$productValue = current($option->getValues());
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php
new file mode 100644
index 0000000000000..17c2af8dc59d0
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php
@@ -0,0 +1,124 @@
+quoteResource = $objectManager->get(QuoteResource::class);
+ $this->quoteFactory = $objectManager->get(QuoteFactory::class);
+ $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Catalog/_files/products.php
+ * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage The requested qty is not available
+ */
+ public function testAddProductIfQuantityIsNotAvailable()
+ {
+ $sku = 'simple';
+ $qty = 200;
+
+ $maskedQuoteId = $this->getMaskedQuoteId();
+ $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty);
+ $this->graphQlQuery($query);
+ self::fail('Should be "The requested qty is not available" error message.');
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Catalog/_files/products.php
+ * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php
+ * @magentoConfigFixture default cataloginventory/item_options/max_sale_qty 5
+ * @expectedException \Exception
+ * @expectedExceptionMessage The most you may purchase is 5.
+ */
+ public function testAddMoreProductsThatAllowed()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/167');
+
+ $sku = 'custom-design-simple-product';
+ $qty = 7;
+
+ $maskedQuoteId = $this->getMaskedQuoteId();
+ $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty);
+ $this->graphQlQuery($query);
+ self::fail('Should be "The most you may purchase is 5." error message.');
+ }
+
+ /**
+ * @return string
+ */
+ public function getMaskedQuoteId() : string
+ {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id');
+
+ return $this->quoteIdToMaskedId->execute((int)$quote->getId());
+ }
+
+ /**
+ * @param string $maskedQuoteId
+ * @param string $sku
+ * @param int $qty
+ * @return string
+ */
+ public function getAddSimpleProductQuery(string $maskedQuoteId, string $sku, int $qty) : string
+ {
+ return <<markTestIncomplete('https://github.com/magento/graphql-ce/issues/361');
-
$productSku = 'configurable';
$query
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php
index f4e96e49a58e6..84c111bd25fd4 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php
@@ -77,7 +77,6 @@ public function testChangePasswordIfUserIsNotAuthorizedTest()
*/
public function testChangeWeakPassword()
{
- $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/190');
$customerEmail = 'customer@example.com';
$oldCustomerPassword = 'password';
$newCustomerPassword = 'weakpass';
@@ -94,7 +93,7 @@ public function testChangeWeakPassword()
/**
* @magentoApiDataFixture Magento/Customer/_files/customer.php
* @expectedException \Exception
- * @expectedExceptionMessage The password doesn't match this account. Verify the password and try again.
+ * @expectedExceptionMessage Invalid login or password.
*/
public function testChangePasswordIfPasswordIsInvalid()
{
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php
index ba0232020298f..1153b9662b41a 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php
@@ -132,7 +132,7 @@ public function testDeleteDefaultBillingCustomerAddress()
* @magentoApiDataFixture Magento/Customer/_files/customer.php
*
* @expectedException \Exception
- * @expectedExceptionMessage Address id 9999 does not exist.
+ * @expectedExceptionMessage Could not find a address with ID "9999"
*/
public function testDeleteNonExistCustomerAddress()
{
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php
index c11c1385f7412..df45e1de771d9 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php
@@ -47,33 +47,57 @@ public function testUpdateCustomer()
$currentEmail = 'customer@example.com';
$currentPassword = 'password';
+ $newPrefix = 'Dr';
$newFirstname = 'Richard';
+ $newMiddlename = 'Riley';
$newLastname = 'Rowe';
+ $newSuffix = 'III';
+ $newDob = '3/11/1972';
+ $newTaxVat = 'GQL1234567';
+ $newGender = 2;
$newEmail = 'customer_updated@example.com';
$query = <<graphQlQuery($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword));
+ $this->assertEquals($newPrefix, $response['updateCustomer']['customer']['prefix']);
$this->assertEquals($newFirstname, $response['updateCustomer']['customer']['firstname']);
+ $this->assertEquals($newMiddlename, $response['updateCustomer']['customer']['middlename']);
$this->assertEquals($newLastname, $response['updateCustomer']['customer']['lastname']);
+ $this->assertEquals($newSuffix, $response['updateCustomer']['customer']['suffix']);
+ $this->assertEquals($newDob, $response['updateCustomer']['customer']['dob']);
+ $this->assertEquals($newTaxVat, $response['updateCustomer']['customer']['taxvat']);
$this->assertEquals($newEmail, $response['updateCustomer']['customer']['email']);
+ $this->assertEquals($newGender, $response['updateCustomer']['customer']['gender']);
}
/**
@@ -185,7 +209,7 @@ public function testUpdateEmailIfPasswordIsMissed()
/**
* @magentoApiDataFixture Magento/Customer/_files/customer.php
* @expectedException \Exception
- * @expectedExceptionMessage The password doesn't match this account. Verify the password and try again.
+ * @expectedExceptionMessage Invalid login or password.
*/
public function testUpdateEmailIfPasswordIsInvalid()
{
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Directory/CurrencyTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Directory/CurrencyTest.php
index 1ff0b53dda0bb..ad5d71cb08605 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Directory/CurrencyTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Directory/CurrencyTest.php
@@ -21,8 +21,8 @@ public function testGetCurrency()
currency {
base_currency_code
base_currency_symbol
- default_display_currecy_code
- default_display_currecy_symbol
+ default_display_currency_code
+ default_display_currency_symbol
available_currency_codes
exchange_rates {
currency_to
@@ -36,8 +36,8 @@ public function testGetCurrency()
$this->assertArrayHasKey('currency', $result);
$this->assertArrayHasKey('base_currency_code', $result['currency']);
$this->assertArrayHasKey('base_currency_symbol', $result['currency']);
- $this->assertArrayHasKey('default_display_currecy_code', $result['currency']);
- $this->assertArrayHasKey('default_display_currecy_symbol', $result['currency']);
+ $this->assertArrayHasKey('default_display_currency_code', $result['currency']);
+ $this->assertArrayHasKey('default_display_currency_symbol', $result['currency']);
$this->assertArrayHasKey('available_currency_codes', $result['currency']);
$this->assertArrayHasKey('exchange_rates', $result['currency']);
}
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/OfflineShipping/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/OfflineShipping/SetOfflineShippingMethodsOnCartTest.php
new file mode 100644
index 0000000000000..80acbbdb64230
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/OfflineShipping/SetOfflineShippingMethodsOnCartTest.php
@@ -0,0 +1,210 @@
+quoteResource = $objectManager->get(QuoteResource::class);
+ $this->quoteFactory = $objectManager->get(QuoteFactory::class);
+ $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class);
+ $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ * @magentoApiDataFixture Magento/OfflineShipping/_files/enable_offline_shipping_methods.php
+ * @magentoApiDataFixture Magento/OfflineShipping/_files/tablerates_weight.php
+ *
+ * @param string $carrierCode
+ * @param string $methodCode
+ * @param float $amount
+ * @param string $label
+ * @dataProvider offlineShippingMethodDataProvider
+ */
+ public function testSetOfflineShippingMethod(string $carrierCode, string $methodCode, float $amount, string $label)
+ {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load(
+ $quote,
+ 'test_order_1',
+ 'reserved_order_id'
+ );
+ $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId());
+ $shippingAddressId = (int)$quote->getShippingAddress()->getId();
+
+ $query = $this->getQuery(
+ $maskedQuoteId,
+ $shippingAddressId,
+ $carrierCode,
+ $methodCode
+ );
+
+ $response = $this->sendRequestWithToken($query);
+
+ $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses'];
+ self::assertEquals($addressesInformation[0]['selected_shipping_method']['carrier_code'], $carrierCode);
+ self::assertEquals($addressesInformation[0]['selected_shipping_method']['method_code'], $methodCode);
+ self::assertEquals($addressesInformation[0]['selected_shipping_method']['amount'], $amount);
+ self::assertEquals($addressesInformation[0]['selected_shipping_method']['label'], $label);
+ }
+
+ /**
+ * @return array
+ */
+ public function offlineShippingMethodDataProvider()
+ {
+ 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'],
+ ];
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ * @magentoApiDataFixture Magento/OfflineShipping/_files/enable_offline_shipping_methods.php
+ */
+ public function testSetShippingMethodTwiceInOneRequest()
+ {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load(
+ $quote,
+ 'test_order_1',
+ 'reserved_order_id'
+ );
+ $shippingAddress = $quote->getShippingAddress();
+ $shippingAddressId = $shippingAddress->getId();
+ $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId());
+
+ $query = <<sendRequestWithToken($query);
+ }
+
+ /**
+ * Generates query for setting the specified shipping method on cart
+ *
+ * @param int $shippingAddressId
+ * @param string $maskedQuoteId
+ * @param string $carrierCode
+ * @param string $methodCode
+ * @return string
+ */
+ private function getQuery(
+ string $maskedQuoteId,
+ int $shippingAddressId,
+ string $carrierCode,
+ string $methodCode
+ ): string {
+ return <<customerTokenService->createCustomerAccessToken('customer@example.com', 'password');
+ $headerMap = ['Authorization' => 'Bearer ' . $customerToken];
+
+ return $this->graphQlQuery($query, [], '', $headerMap);
+ }
+}
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 d5bdb942e9b2c..d9ab8db62a195 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php
@@ -9,7 +9,7 @@
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\TestCase\GraphQlAbstract;
-use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\QuoteFactory;
use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface;
use Magento\Quote\Model\ResourceModel\Quote as QuoteResource;
@@ -21,9 +21,9 @@ class AddSimpleProductToCartTest extends GraphQlAbstract
private $quoteResource;
/**
- * @var Quote
+ * @var QuoteFactory
*/
- private $quote;
+ private $quoteFactory;
/**
* @var QuoteIdToMaskedQuoteIdInterface
@@ -37,27 +37,102 @@ protected function setUp()
{
$objectManager = Bootstrap::getObjectManager();
$this->quoteResource = $objectManager->get(QuoteResource::class);
- $this->quote = $objectManager->create(Quote::class);
+ $this->quoteFactory = $objectManager->get(QuoteFactory::class);
$this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class);
}
+ /**
+ * @magentoApiDataFixture Magento/Catalog/_files/products.php
+ * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php
+ */
+ public function testAddSimpleProductToCart()
+ {
+ $sku = 'simple';
+ $qty = 2;
+ $maskedQuoteId = $this->getMaskedQuoteId();
+
+ $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty);
+ $response = $this->graphQlQuery($query);
+ 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/Catalog/_files/products.php
* @magentoApiDataFixture Magento/Checkout/_files/active_quote.php
* @expectedException \Exception
- * @expectedExceptionMessage The requested qty is not available
+ * @expectedExceptionMessage Please enter a number greater than 0 in this field.
*/
- public function testAddProductIfQuantityIsNotAvailable()
+ public function testAddSimpleProductToCartWithNegativeQty()
{
$sku = 'simple';
- $qty = 200;
-
- $this->quoteResource->load(
- $this->quote,
- 'test_order_1',
- 'reserved_order_id'
- );
- $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId());
+ $qty = -2;
+ $maskedQuoteId = $this->getMaskedQuoteId();
+
+ $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty);
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @return string
+ */
+ public function getMaskedQuoteId() : string
+ {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id');
+
+ return $this->quoteIdToMaskedId->execute((int)$quote->getId());
+ }
+
+ /**
+ * @param string $maskedQuoteId
+ * @param string $sku
+ * @param int $qty
+ * @return string
+ */
+ public function getAddSimpleProductQuery(string $maskedQuoteId, string $sku, int $qty): string
+ {
+ return <<getMaskedQuoteIdByReversedQuoteId('test_order_item_with_items');
+ $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId('test_order_item_with_items');
+ $query = $this->getQuery($maskedQuoteId);
+ $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+
+ self::assertArrayHasKey('cart', $response);
+ self::assertEquals('checkmo', $response['cart']['available_payment_methods'][0]['code']);
+ self::assertEquals('Check / Money order', $response['cart']['available_payment_methods'][0]['title']);
+ self::assertGreaterThan(
+ 0,
+ count($response['cart']['available_payment_methods']),
+ 'There are no available payment methods for customer cart!'
+ );
+ }
- $query = <<getMaskedQuoteIdByReservedOrderId(
+ 'test_order_with_virtual_product_without_address'
+ );
+ $query = $this->getQuery($guestQuoteMaskedId);
+
+ $this->expectExceptionMessage(
+ "The current user cannot perform operations on cart \"$guestQuoteMaskedId\""
+ );
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/three_customers.php
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php
+ */
+ public function testGetPaymentMethodsFromAnotherCustomerCart()
+ {
+ $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId('test_order_item_with_items');
+ $query = $this->getQuery($maskedQuoteId);
+
+ $this->expectExceptionMessage(
+ "The current user cannot perform operations on cart \"$maskedQuoteId\""
+ );
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer3@search.example.com'));
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php
+ * @magentoApiDataFixture Magento/Payment/_files/disable_all_active_payment_methods.php
+ */
+ public function testGetPaymentMethodsIfPaymentsAreNotSet()
+ {
+ $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId('test_order_item_with_items');
+ $query = $this->getQuery($maskedQuoteId);
+ $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+
+ self::assertEquals(0, count($response['cart']['available_payment_methods']));
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id"
+ */
+ public function testGetPaymentMethodsOfNonExistentCart()
+ {
+ $maskedQuoteId = 'non_existent_masked_id';
+ $query = $this->getQuery($maskedQuoteId);
+
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @param string $maskedQuoteId
+ * @return string
+ */
+ private function getQuery(
+ string $maskedQuoteId
+ ): string {
+ return <<graphQlQuery($query, [], '', $this->getHeaderMap());
-
- self::assertArrayHasKey('cart', $response);
- self::assertEquals('checkmo', $response['cart']['available_payment_methods'][0]['code']);
- self::assertEquals('Check / Money order', $response['cart']['available_payment_methods'][0]['title']);
}
/**
@@ -88,13 +160,13 @@ private function getHeaderMap(string $username = 'customer@example.com', string
}
/**
- * @param string $reversedQuoteId
+ * @param string $reservedOrderId
* @return string
*/
- private function getMaskedQuoteIdByReversedQuoteId(string $reversedQuoteId): string
+ private function getMaskedQuoteIdByReservedOrderId(string $reservedOrderId): string
{
$quote = $this->quoteFactory->create();
- $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id');
+ $this->quoteResource->load($quote, $reservedOrderId, 'reserved_order_id');
return $this->quoteIdToMaskedId->execute((int)$quote->getId());
}
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 fe9b7b3c49a7c..4b1509eef354e 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
@@ -72,8 +72,8 @@ public function testGetCart()
}
/**
- * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
*/
public function testGetGuestCart()
{
@@ -114,6 +114,26 @@ public function testGetNonExistentCart()
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
}
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage Current user does not have an active cart.
+ */
+ public function testGetInactiveCart()
+ {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id');
+ $quote->setCustomerId(1);
+ $quote->setIsActive(false);
+ $this->quoteResource->save($quote);
+ $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId());
+
+ $query = $this->getCartQuery($maskedQuoteId);
+
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
/**
* @param string $maskedQuoteId
* @return string
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 a351a2188a664..e80a2127ad420 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
@@ -81,14 +81,13 @@ public function testRemoveItemFromCart()
public function testRemoveItemFromNonExistentCart()
{
$query = $this->prepareMutationQuery('non_existent_masked_id', 1);
-
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
}
/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
*/
- public function testRemoveNotExistentItem()
+ public function testRemoveNonExistentItem()
{
$quote = $this->quoteFactory->create();
$this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id');
@@ -130,7 +129,7 @@ public function testRemoveItemIfItemIsNotBelongToCart()
}
/**
- * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php
*/
public function testRemoveItemFromGuestCart()
@@ -183,6 +182,50 @@ public function testRemoveItemFromAnotherCustomerCart()
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
}
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @param string $input
+ * @param string $message
+ * @dataProvider dataProviderUpdateWithMissedRequiredParameters
+ */
+ public function testUpdateWithMissedItemRequiredParameters(string $input, string $message)
+ {
+ $query = <<expectExceptionMessage($message);
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @return array
+ */
+ public function dataProviderUpdateWithMissedRequiredParameters(): array
+ {
+ return [
+ 'missed_cart_id' => [
+ 'cart_item_id: 1',
+ 'Required parameter "cart_id" is missing.'
+ ],
+ 'missed_cart_item_id' => [
+ 'cart_id: "test"',
+ 'Required parameter "cart_item_id" is missing.'
+ ],
+ ];
+ }
+
/**
* @param string $maskedQuoteId
* @param int $itemId
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 96f32d781267b..55a32f7cdf653 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
@@ -90,6 +90,7 @@ public function testSetNewBillingAddress()
code
label
}
+ address_type
}
}
}
@@ -147,6 +148,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter()
code
label
}
+ address_type
}
shipping_addresses {
firstname
@@ -160,6 +162,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter()
code
label
}
+ address_type
}
}
}
@@ -174,7 +177,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter()
self::assertArrayHasKey('shipping_addresses', $cartResponse);
$shippingAddressResponse = current($cartResponse['shipping_addresses']);
$this->assertNewAddressFields($billingAddressResponse);
- $this->assertNewAddressFields($shippingAddressResponse);
+ $this->assertNewAddressFields($shippingAddressResponse, 'SHIPPING');
}
/**
@@ -373,7 +376,7 @@ public function testSetBillingAddressToAnotherCustomerCart()
* @magentoApiDataFixture Magento/Customer/_files/customer_address.php
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @expectedException \Exception
- * @expectedExceptionMessage The current user cannot use address with ID "1"
+ * @expectedExceptionMessage Current customer does not have permission to address with ID "1"
*/
public function testSetBillingAddressIfCustomerIsNotOwnerOfAddress()
{
@@ -400,12 +403,66 @@ public function testSetBillingAddressIfCustomerIsNotOwnerOfAddress()
$this->graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com'));
}
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id"
+ */
+ public function testSetBillingAddressOnNonExistentCart()
+ {
+ $maskedQuoteId = 'non_existent_masked_id';
+ $query = <<graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @dataProvider dataProviderSetWithoutRequiredParameters
+ * @param string $input
+ * @param string $message
+ * @throws \Exception
+ */
+ public function testSetBillingAddressWithoutRequiredParameters(string $input, string $message)
+ {
+ $maskedQuoteId = $this->assignQuoteToCustomer();
+ $input = str_replace('cart_id_value', $maskedQuoteId, $input);
+
+ $query = <<expectExceptionMessage($message);
+ $this->graphQlQuery($query);
+ }
+
/**
* Verify the all the whitelisted fields for a New Address Object
*
- * @param array $billingAddressResponse
+ * @param array $addressResponse
+ * @param string $addressType
*/
- private function assertNewAddressFields(array $billingAddressResponse): void
+ private function assertNewAddressFields(array $addressResponse, string $addressType = 'BILLING'): void
{
$assertionMap = [
['response_field' => 'firstname', 'expected_value' => 'test firstname'],
@@ -416,9 +473,10 @@ private function assertNewAddressFields(array $billingAddressResponse): void
['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]
];
- $this->assertResponseFields($billingAddressResponse, $assertionMap);
+ $this->assertResponseFields($addressResponse, $assertionMap);
}
/**
@@ -481,4 +539,22 @@ private function assignQuoteToCustomer(
$this->quoteResource->save($quote);
return $this->quoteIdToMaskedId->execute((int)$quote->getId());
}
+
+ /**
+ * @return array
+ */
+ public function dataProviderSetWithoutRequiredParameters()
+ {
+ return [
+ 'missed_billing_address' => [
+ 'cart_id: "cart_id_value"',
+ 'Field SetBillingAddressOnCartInput.billing_address of required type BillingAddressInput!'
+ . ' was not provided.',
+ ],
+ 'missed_cart_id' => [
+ 'billing_address: {}',
+ 'Required parameter "cart_id" is missing'
+ ]
+ ];
+ }
}
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 bbc77b6c39740..51c48f5041dd9 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
@@ -151,6 +151,91 @@ public function testSetPaymentMethodToAnotherCustomerCart()
$this->graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com'));
}
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id"
+ */
+ public function testPaymentMethodOnNonExistentCart()
+ {
+ $maskedQuoteId = 'non_existent_masked_id';
+ $query = <<graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ * @param string $input
+ * @param string $message
+ * @dataProvider dataProviderSetPaymentMethodWithoutRequiredParameters
+ */
+ public function testSetPaymentMethodWithoutRequiredParameters(string $input, string $message)
+ {
+ $query = <<expectExceptionMessage($message);
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+ /**
+ * @return array
+ */
+ public function dataProviderSetPaymentMethodWithoutRequiredParameters(): array
+ {
+ return [
+ 'missed_cart_id' => [
+ 'payment_method: {code: "' . Checkmo::PAYMENT_METHOD_CHECKMO_CODE . '"}',
+ 'Required parameter "cart_id" is missing.'
+ ],
+ 'missed_payment_method' => [
+ 'cart_id: "test"',
+ 'Required parameter "code" for "payment_method" is missing.'
+ ],
+ 'missed_payment_method_code' => [
+ 'cart_id: "test", payment_method: {code: ""}',
+ 'Required parameter "code" for "payment_method" is missing.'
+ ],
+ ];
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_payment_saved.php
+ */
+ public function testReSetPayment()
+ {
+ /** @var \Magento\Quote\Model\Quote $quote */
+ $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1_with_payment');
+ $methodCode = Checkmo::PAYMENT_METHOD_CHECKMO_CODE;
+ $query = $this->prepareMutationQuery($maskedQuoteId, $methodCode);
+ $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']);
+ }
+
/**
* @param string $maskedQuoteId
* @param string $methodCode
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php
similarity index 77%
rename from dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingAddressOnCartTest.php
rename to dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php
index 1f9aca2f12013..ae184b8930c07 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingAddressOnCartTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php
@@ -5,17 +5,14 @@
*/
declare(strict_types=1);
-namespace Magento\GraphQl\Quote;
+namespace Magento\GraphQl\Quote\Customer;
-use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Integration\Api\CustomerTokenServiceInterface;
-use Magento\Multishipping\Helper\Data;
use Magento\Quote\Model\QuoteFactory;
use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface;
use Magento\Quote\Model\ResourceModel\Quote as QuoteResource;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\TestCase\GraphQlAbstract;
-use Magento\TestFramework\ObjectManager;
/**
* Test for set shipping addresses on cart mutation
@@ -52,11 +49,12 @@ protected function setUp()
}
/**
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
*/
- public function testSetNewShippingAddressByGuest()
+ public function testSetNewShippingAddress()
{
- $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address');
+ $maskedQuoteId = $this->assignQuoteToCustomer();
$query = <<graphQlQuery($query);
+ $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap());
self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']);
$cartResponse = $response['setShippingAddressesOnCart']['cart'];
@@ -109,13 +108,14 @@ public function testSetNewShippingAddressByGuest()
}
/**
- * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
* @expectedException \Exception
- * @expectedExceptionMessage The current customer isn't authorized.
+ * @expectedExceptionMessage The Cart includes virtual product(s) only, so a shipping address is not used.
*/
- public function testSetShippingAddressFromAddressBookByGuest()
+ public function testSetNewShippingAddressOnQuoteWithVirtualProducts()
{
- $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address');
+ $maskedQuoteId = $this->assignQuoteToCustomer('test_order_with_virtual_product_without_address');
$query = <<graphQlQuery($query);
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
}
/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php
*/
- public function testSetNewShippingAddressByRegisteredCustomer()
+ public function testSetShippingAddressFromAddressBook()
{
$maskedQuoteId = $this->assignQuoteToCustomer();
@@ -155,18 +167,7 @@ public function testSetNewShippingAddressByRegisteredCustomer()
cart_id: "$maskedQuoteId"
shipping_addresses: [
{
- address: {
- firstname: "test firstname"
- lastname: "test lastname"
- company: "test company"
- street: ["test street 1", "test street 2"]
- city: "test city"
- region: "test region"
- postcode: "887766"
- country_code: "US"
- telephone: "88776655"
- save_in_address_book: false
- }
+ customer_address_id: 1
}
]
}
@@ -180,10 +181,6 @@ public function testSetNewShippingAddressByRegisteredCustomer()
city
postcode
telephone
- country {
- label
- code
- }
}
}
}
@@ -195,15 +192,16 @@ public function testSetNewShippingAddressByRegisteredCustomer()
$cartResponse = $response['setShippingAddressesOnCart']['cart'];
self::assertArrayHasKey('shipping_addresses', $cartResponse);
$shippingAddressResponse = current($cartResponse['shipping_addresses']);
- $this->assertNewShippingAddressFields($shippingAddressResponse);
+ $this->assertSavedShippingAddressFields($shippingAddressResponse);
}
/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoApiDataFixture Magento/Customer/_files/customer.php
- * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage Could not find a address with ID "100"
*/
- public function testSetShippingAddressFromAddressBookByRegisteredCustomer()
+ public function testSetNonExistentShippingAddressFromAddressBook()
{
$maskedQuoteId = $this->assignQuoteToCustomer();
@@ -214,41 +212,28 @@ public function testSetShippingAddressFromAddressBookByRegisteredCustomer()
cart_id: "$maskedQuoteId"
shipping_addresses: [
{
- customer_address_id: 1
+ customer_address_id: 100
}
]
}
) {
cart {
shipping_addresses {
- firstname
- lastname
- company
- street
city
- postcode
- telephone
}
}
}
}
QUERY;
- $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap());
-
- self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']);
- $cartResponse = $response['setShippingAddressesOnCart']['cart'];
- self::assertArrayHasKey('shipping_addresses', $cartResponse);
- $shippingAddressResponse = current($cartResponse['shipping_addresses']);
- $this->assertSavedShippingAddressFields($shippingAddressResponse);
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
}
/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoApiDataFixture Magento/Customer/_files/customer.php
- * @expectedException \Exception
- * @expectedExceptionMessage Could not find a address with ID "100"
+ * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php
*/
- public function testSetNotExistedShippingAddressFromAddressBook()
+ public function testSetNewShippingAddressAndFromAddressBookAtSameTime()
{
$maskedQuoteId = $this->assignQuoteToCustomer();
@@ -259,7 +244,19 @@ public function testSetNotExistedShippingAddressFromAddressBook()
cart_id: "$maskedQuoteId"
shipping_addresses: [
{
- customer_address_id: 100
+ customer_address_id: 1,
+ address: {
+ firstname: "test firstname"
+ lastname: "test lastname"
+ company: "test company"
+ street: ["test street 1", "test street 2"]
+ city: "test city"
+ region: "test region"
+ postcode: "887766"
+ country_code: "US"
+ telephone: "88776655"
+ save_in_address_book: false
+ }
}
]
}
@@ -272,17 +269,22 @@ public function testSetNotExistedShippingAddressFromAddressBook()
}
}
QUERY;
+ self::expectExceptionMessage(
+ 'The shipping address cannot contain "customer_address_id" and "address" at the same time.'
+ );
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
}
/**
+ * @magentoApiDataFixture Magento/Customer/_files/three_customers.php
+ * @magentoApiDataFixture Magento/Customer/_files/customer_address.php
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @expectedException \Exception
- * @expectedExceptionMessage The shipping address must contain either "customer_address_id" or "address".
+ * @expectedExceptionMessage Current customer does not have permission to address with ID "1"
*/
- public function testSetShippingAddressWithoutAddresses()
+ public function testSetShippingAddressIfCustomerIsNotOwnerOfAddress()
{
- $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address');
+ $maskedQuoteId = $this->assignQuoteToCustomer('test_order_with_simple_product_without_address', 2);
$query = <<graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com'));
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/three_customers.php
+ * @magentoApiDataFixture Magento/Customer/_files/customer_address.php
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @expectedException \Exception
+ */
+ public function testSetShippingAddressToAnotherCustomerCart()
+ {
+ $maskedQuoteId = $this->assignQuoteToCustomer('test_order_with_simple_product_without_address', 1);
+
+ $query = <<graphQlQuery($query);
+ $this->expectExceptionMessage(
+ "The current user cannot perform operations on cart \"$maskedQuoteId\""
+ );
+
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com'));
}
/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoApiDataFixture Magento/Customer/_files/customer.php
- * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php
+ * @dataProvider dataProviderUpdateWithMissedRequiredParameters
+ * @param string $input
+ * @param string $message
+ * @throws \Exception
*/
- public function testSetNewShippingAddressAndFromAddressBookAtSameTime()
+ public function testSetNewShippingAddressWithMissedRequiredParameters(string $input, string $message)
{
$maskedQuoteId = $this->assignQuoteToCustomer();
@@ -318,22 +363,10 @@ public function testSetNewShippingAddressAndFromAddressBookAtSameTime()
mutation {
setShippingAddressesOnCart(
input: {
- cart_id: "$maskedQuoteId"
+ cart_id: "{$maskedQuoteId}"
shipping_addresses: [
{
- customer_address_id: 1,
- address: {
- firstname: "test firstname"
- lastname: "test lastname"
- company: "test company"
- street: ["test street 1", "test street 2"]
- city: "test city"
- region: "test region"
- postcode: "887766"
- country_code: "US"
- telephone: "88776655"
- save_in_address_book: false
- }
+ {$input}
}
]
}
@@ -346,20 +379,36 @@ public function testSetNewShippingAddressAndFromAddressBookAtSameTime()
}
}
QUERY;
- self::expectExceptionMessage(
- 'The shipping address cannot contain "customer_address_id" and "address" at the same time.'
- );
+ $this->expectExceptionMessage($message);
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
}
/**
+ * @return array
+ */
+ public function dataProviderUpdateWithMissedRequiredParameters()
+ {
+ return [
+ 'shipping_addresses' => [
+ '',
+ 'The shipping address must contain either "customer_address_id" or "address".',
+ ],
+ 'missed_city' => [
+ 'address: { save_in_address_book: false }',
+ 'Field CartAddressInput.city of required type String! was not provided'
+ ]
+ ];
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @expectedException \Exception
* @expectedExceptionMessage You cannot specify multiple shipping addresses.
*/
public function testSetMultipleNewShippingAddresses()
{
- $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address');
+ $maskedQuoteId = $this->assignQuoteToCustomer();
$query = <<get(\Magento\Config\Model\ResourceModel\Config::class);
- $config->saveConfig(
- Data::XML_PATH_CHECKOUT_MULTIPLE_AVAILABLE,
- null,
- ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
- 0
- );
- /** @var \Magento\Framework\App\Config\ReinitableConfigInterface $config */
- $config = ObjectManager::getInstance()->get(\Magento\Framework\App\Config\ReinitableConfigInterface::class);
- $config->reinit();
-
- $this->graphQlQuery($query);
- }
-
- /**
- * @magentoApiDataFixture Magento/Customer/_files/three_customers.php
- * @magentoApiDataFixture Magento/Customer/_files/customer_address.php
- * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
- * @expectedException \Exception
- * @expectedExceptionMessage The current user cannot use address with ID "1"
- */
- public function testSetShippingAddressIfCustomerIsNotOwnerOfAddress()
- {
- $maskedQuoteId = $this->assignQuoteToCustomer('test_order_with_simple_product_without_address', 2);
-
- $query = <<graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com'));
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
}
/**
@@ -472,6 +474,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']
];
$this->assertResponseFields($shippingAddressResponse, $assertionMap);
@@ -509,18 +512,6 @@ private function getHeaderMap(string $username = 'customer@example.com', string
return $headerMap;
}
- /**
- * @param string $reversedQuoteId
- * @return string
- */
- private function getMaskedQuoteIdByReversedQuoteId(string $reversedQuoteId): string
- {
- $quote = $this->quoteFactory->create();
- $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id');
-
- return $this->quoteIdToMaskedId->execute((int)$quote->getId());
- }
-
/**
* @param string $reversedQuoteId
* @param int $customerId
@@ -536,22 +527,4 @@ private function assignQuoteToCustomer(
$this->quoteResource->save($quote);
return $this->quoteIdToMaskedId->execute((int)$quote->getId());
}
-
- public function tearDown()
- {
- /** @var \Magento\Config\Model\ResourceModel\Config $config */
- $config = ObjectManager::getInstance()->get(\Magento\Config\Model\ResourceModel\Config::class);
-
- //default state of multishipping config
- $config->saveConfig(
- Data::XML_PATH_CHECKOUT_MULTIPLE_AVAILABLE,
- 1,
- ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
- 0
- );
-
- /** @var \Magento\Framework\App\Config\ReinitableConfigInterface $config */
- $config = ObjectManager::getInstance()->get(\Magento\Framework\App\Config\ReinitableConfigInterface::class);
- $config->reinit();
- }
}
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
new file mode 100644
index 0000000000000..736ea69440753
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php
@@ -0,0 +1,206 @@
+quoteResource = $objectManager->get(QuoteResource::class);
+ $this->quoteFactory = $objectManager->get(QuoteFactory::class);
+ $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class);
+ $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class);
+ }
+
+ public function testShippingMethodWithVirtualProduct()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testShippingMethodWithSimpleProduct()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testShippingMethodWithSimpleProductWithoutAddress()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testSetShippingMethodWithMissedRequiredParameters()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testSetNonExistentShippingMethod()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testSetShippingMethodIfAddressIsNotBelongToCart()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testSetShippingMethodToNonExistentCart()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testSetShippingMethodToGuestCart()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testSetShippingMethodToAnotherCustomerCart()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testSetShippingMethodToNonExistentCartAddress()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testSetShippingMethodToGuestCartAddress()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testSetShippingMethodToAnotherCustomerCartAddress()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ public function testSetMultipleShippingMethods()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423');
+ }
+
+ /**
+ * @param string $maskedQuoteId
+ * @param string $shippingMethodCode
+ * @param string $shippingCarrierCode
+ * @param string $shippingAddressId
+ * @return string
+ * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
+ */
+ private function prepareMutationQuery(
+ string $maskedQuoteId,
+ string $shippingMethodCode,
+ string $shippingCarrierCode,
+ string $shippingAddressId
+ ) : string {
+ return <<quoteFactory->create();
+ $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id');
+
+ return $this->quoteIdToMaskedId->execute((int)$quote->getId());
+ }
+
+ /**
+ * @param string $reversedQuoteId
+ * @param int $customerId
+ * @return string
+ * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
+ */
+ private function assignQuoteToCustomer(
+ string $reversedQuoteId,
+ int $customerId
+ ): string {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id');
+ $quote->setCustomerId($customerId);
+ $this->quoteResource->save($quote);
+ return $this->quoteIdToMaskedId->execute((int)$quote->getId());
+ }
+
+ /**
+ * @param string $username
+ * @param string $password
+ * @return array
+ * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
+ */
+ 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/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php
new file mode 100644
index 0000000000000..74e7aa8b5d0a4
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php
@@ -0,0 +1,334 @@
+quoteResource = $objectManager->get(QuoteResource::class);
+ $this->quoteFactory = $objectManager->get(QuoteFactory::class);
+ $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class);
+ $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class);
+ $this->productRepository = $objectManager->get(ProductRepositoryInterface::class);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ */
+ public function testUpdateCartItemQty()
+ {
+ $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;
+
+ $query = $this->getQuery($maskedQuoteId, $itemId, $qty);
+ $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+
+ $this->assertArrayHasKey('updateCartItems', $response);
+ $this->assertArrayHasKey('cart', $response['updateCartItems']);
+
+ $responseCart = $response['updateCartItems']['cart'];
+ $item = current($responseCart['items']);
+
+ $this->assertEquals($itemId, $item['id']);
+ $this->assertEquals($qty, $item['qty']);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ */
+ public function testRemoveCartItemIfQuantityIsZero()
+ {
+ $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 = 0;
+
+ $query = $this->getQuery($maskedQuoteId, $itemId, $qty);
+ $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+
+ $this->assertArrayHasKey('updateCartItems', $response);
+ $this->assertArrayHasKey('cart', $response['updateCartItems']);
+
+ $responseCart = $response['updateCartItems']['cart'];
+ $this->assertCount(0, $responseCart['items']);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id"
+ */
+ public function testUpdateItemInNonExistentCart()
+ {
+ $query = $this->getQuery('non_existent_masked_id', 1, 2);
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ */
+ public function testUpdateNonExistentItem()
+ {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id');
+ $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId());
+ $notExistentItemId = 999;
+
+ $this->expectExceptionMessage("Could not find cart item with id: {$notExistentItemId}.");
+
+ $query = $this->getQuery($maskedQuoteId, $notExistentItemId, 2);
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php
+ */
+ public function testUpdateItemIfItemIsNotBelongToCart()
+ {
+ $firstQuote = $this->quoteFactory->create();
+ $this->quoteResource->load($firstQuote, 'test_order_1', 'reserved_order_id');
+ $firstQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$firstQuote->getId());
+
+ $secondQuote = $this->quoteFactory->create();
+ $this->quoteResource->load(
+ $secondQuote,
+ 'test_order_with_virtual_product_without_address',
+ 'reserved_order_id'
+ );
+ $secondQuote->setCustomerId(1);
+ $this->quoteResource->save($secondQuote);
+ $secondQuoteItemId = (int)$secondQuote
+ ->getItemByProduct($this->productRepository->get('virtual-product'))
+ ->getId();
+
+ $this->expectExceptionMessage("Could not find cart item with id: {$secondQuoteItemId}.");
+
+ $query = $this->getQuery($firstQuoteMaskedId, $secondQuoteItemId, 2);
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php
+ */
+ public function testUpdateItemInGuestCart()
+ {
+ $guestQuote = $this->quoteFactory->create();
+ $this->quoteResource->load(
+ $guestQuote,
+ 'test_order_with_virtual_product_without_address',
+ 'reserved_order_id'
+ );
+ $guestQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$guestQuote->getId());
+ $guestQuoteItemId = (int)$guestQuote
+ ->getItemByProduct($this->productRepository->get('virtual-product'))
+ ->getId();
+
+ $this->expectExceptionMessage(
+ "The current user cannot perform operations on cart \"$guestQuoteMaskedId\""
+ );
+
+ $query = $this->getQuery($guestQuoteMaskedId, $guestQuoteItemId, 2);
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/three_customers.php
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php
+ */
+ public function testUpdateItemInAnotherCustomerCart()
+ {
+ $anotherCustomerQuote = $this->quoteFactory->create();
+ $this->quoteResource->load(
+ $anotherCustomerQuote,
+ 'test_order_with_virtual_product_without_address',
+ 'reserved_order_id'
+ );
+ $anotherCustomerQuote->setCustomerId(2);
+ $this->quoteResource->save($anotherCustomerQuote);
+
+ $anotherCustomerQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$anotherCustomerQuote->getId());
+ $anotherCustomerQuoteItemId = (int)$anotherCustomerQuote
+ ->getItemByProduct($this->productRepository->get('virtual-product'))
+ ->getId();
+
+ $this->expectExceptionMessage(
+ "The current user cannot perform operations on cart \"$anotherCustomerQuoteMaskedId\""
+ );
+
+ $query = $this->getQuery($anotherCustomerQuoteMaskedId, $anotherCustomerQuoteItemId, 2);
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage Required parameter "cart_id" is missing.
+ */
+ public function testUpdateWithMissedCartItemId()
+ {
+ $query = <<graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @param string $input
+ * @param string $message
+ * @dataProvider dataProviderUpdateWithMissedRequiredParameters
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ */
+ public function testUpdateWithMissedItemRequiredParameters(string $input, string $message)
+ {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id');
+ $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId());
+
+ $query = <<expectExceptionMessage($message);
+ $this->graphQlQuery($query, [], '', $this->getHeaderMap());
+ }
+
+ /**
+ * @return array
+ */
+ public function dataProviderUpdateWithMissedRequiredParameters(): array
+ {
+ return [
+ 'missed_cart_items' => [
+ '',
+ 'Required parameter "cart_items" is missing.'
+ ],
+ 'missed_cart_item_id' => [
+ 'cart_items: [{ quantity: 2 }]',
+ 'Required parameter "cart_item_id" for "cart_items" is missing.'
+ ],
+ 'missed_cart_item_qty' => [
+ 'cart_items: [{ cart_item_id: 1 }]',
+ 'Required parameter "quantity" for "cart_items" is missing.'
+ ],
+ ];
+ }
+
+ /**
+ * @param string $maskedQuoteId
+ * @param int $itemId
+ * @param float $qty
+ * @return string
+ */
+ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): string
+ {
+ return <<customerTokenService->createCustomerAccessToken($username, $password);
+ $headerMap = ['Authorization' => 'Bearer ' . $customerToken];
+ return $headerMap;
+ }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailablePaymentMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailablePaymentMethodsTest.php
index a5a08aaf39fb1..c4dd9af490c99 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailablePaymentMethodsTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailablePaymentMethodsTest.php
@@ -49,18 +49,8 @@ protected function setUp()
*/
public function testGetCartWithPaymentMethods()
{
- $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address');
-
- $query = <<getMaskedQuoteIdByReservedOrderId('test_order_with_simple_product_without_address');
+ $query = $this->getQuery($maskedQuoteId);
$response = $this->graphQlQuery($query);
self::assertArrayHasKey('cart', $response);
@@ -73,16 +63,78 @@ public function testGetCartWithPaymentMethods()
'No Payment Information Required',
$response['cart']['available_payment_methods'][1]['title']
);
+ self::assertGreaterThan(
+ 0,
+ count($response['cart']['available_payment_methods']),
+ 'There are no available payment methods for guest cart!'
+ );
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ */
+ public function testGetPaymentMethodsFromCustomerCart()
+ {
+ $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId('test_order_1');
+ $query = $this->getQuery($maskedQuoteId);
+
+ $this->expectExceptionMessage(
+ "The current user cannot perform operations on cart \"$maskedQuoteId\""
+ );
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @magentoApiDataFixture Magento/Payment/_files/disable_all_active_payment_methods.php
+ */
+ public function testGetPaymentMethodsIfPaymentsAreNotSet()
+ {
+ $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId('test_order_with_simple_product_without_address');
+ $query = $this->getQuery($maskedQuoteId);
+ $response = $this->graphQlQuery($query);
+
+ self::assertEquals(0, count($response['cart']['available_payment_methods']));
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id"
+ */
+ public function testGetPaymentMethodsOfNonExistentCart()
+ {
+ $maskedQuoteId = 'non_existent_masked_id';
+ $query = $this->getQuery($maskedQuoteId);
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @param string $maskedQuoteId
+ * @return string
+ */
+ private function getQuery(
+ string $maskedQuoteId
+ ): string {
+ return <<quoteFactory->create();
- $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id');
+ $this->quoteResource->load($quote, $reservedOrderId, 'reserved_order_id');
return $this->quoteIdToMaskedId->execute((int)$quote->getId());
}
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 b1d5e475c793e..916d5951b0ff2 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
@@ -97,6 +97,24 @@ public function testGetNonExistentCart()
$this->graphQlQuery($query);
}
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage Current user does not have an active cart.
+ */
+ public function testGetInactiveCart()
+ {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id');
+ $quote->setIsActive(false);
+ $this->quoteResource->save($quote);
+ $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId());
+
+ $query = $this->getCartQuery($maskedQuoteId);
+
+ $this->graphQlQuery($query);
+ }
+
/**
* @param string $maskedQuoteId
* @return string
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 a6b8f05fc0834..a306b29e51197 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
@@ -73,14 +73,13 @@ public function testRemoveItemFromCart()
public function testRemoveItemFromNonExistentCart()
{
$query = $this->prepareMutationQuery('non_existent_masked_id', 1);
-
$this->graphQlQuery($query);
}
/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
*/
- public function testRemoveNotExistentItem()
+ public function testRemoveNonExistentItem()
{
$quote = $this->quoteFactory->create();
$this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id');
@@ -139,6 +138,49 @@ public function testRemoveItemFromCustomerCart()
$this->graphQlQuery($query);
}
+ /**
+ * @param string $input
+ * @param string $message
+ * @dataProvider dataProviderUpdateWithMissedRequiredParameters
+ */
+ public function testUpdateWithMissedItemRequiredParameters(string $input, string $message)
+ {
+ $query = <<expectExceptionMessage($message);
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @return array
+ */
+ public function dataProviderUpdateWithMissedRequiredParameters(): array
+ {
+ return [
+ 'missed_cart_id' => [
+ 'cart_item_id: 1',
+ 'Required parameter "cart_id" is missing.'
+ ],
+ 'missed_cart_item_id' => [
+ 'cart_id: "test"',
+ 'Required parameter "cart_item_id" is missing.'
+ ],
+ ];
+ }
+
/**
* @param string $maskedQuoteId
* @param int $itemId
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 24fc8353d2552..a2f092b9e0e1d 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
@@ -82,6 +82,7 @@ public function testSetNewBillingAddress()
code
label
}
+ address_type
}
}
}
@@ -138,6 +139,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter()
code
label
}
+ address_type
}
shipping_addresses {
firstname
@@ -151,6 +153,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter()
code
label
}
+ address_type
}
}
}
@@ -165,13 +168,13 @@ public function testSetNewBillingAddressWithUseForShippingParameter()
self::assertArrayHasKey('shipping_addresses', $cartResponse);
$shippingAddressResponse = current($cartResponse['shipping_addresses']);
$this->assertNewAddressFields($billingAddressResponse);
- $this->assertNewAddressFields($shippingAddressResponse);
+ $this->assertNewAddressFields($shippingAddressResponse, 'SHIPPING');
}
/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
*/
- public function testSettBillingAddressToCustomerCart()
+ public function testSetBillingAddressToCustomerCart()
{
$maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1');
@@ -241,12 +244,64 @@ public function testSetBillingAddressFromAddressBook()
$this->graphQlQuery($query);
}
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id"
+ */
+ public function testSetBillingAddressOnNonExistentCart()
+ {
+ $maskedQuoteId = 'non_existent_masked_id';
+ $query = <<graphQlQuery($query);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @dataProvider dataProviderSetWithoutRequiredParameters
+ * @param string $input
+ * @param string $message
+ * @throws \Exception
+ */
+ public function testSetBillingAddressWithoutRequiredParameters(string $input, string $message)
+ {
+ $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address');
+ $input = str_replace('cart_id_value', $maskedQuoteId, $input);
+
+ $query = <<expectExceptionMessage($message);
+ $this->graphQlQuery($query);
+ }
+
/**
* Verify the all the whitelisted fields for a New Address Object
*
- * @param array $billingAddressResponse
+ * @param array $addressResponse
+ * @param string $addressType
*/
- private function assertNewAddressFields(array $billingAddressResponse): void
+ private function assertNewAddressFields(array $addressResponse, string $addressType = 'BILLING'): void
{
$assertionMap = [
['response_field' => 'firstname', 'expected_value' => 'test firstname'],
@@ -257,9 +312,10 @@ private function assertNewAddressFields(array $billingAddressResponse): void
['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]
];
- $this->assertResponseFields($billingAddressResponse, $assertionMap);
+ $this->assertResponseFields($addressResponse, $assertionMap);
}
/**
@@ -273,4 +329,22 @@ private function getMaskedQuoteIdByReversedQuoteId(string $reversedQuoteId): str
return $this->quoteIdToMaskedId->execute((int)$quote->getId());
}
+
+ /**
+ * @return array
+ */
+ public function dataProviderSetWithoutRequiredParameters()
+ {
+ return [
+ 'missed_billing_address' => [
+ 'cart_id: "cart_id_value"',
+ 'Field SetBillingAddressOnCartInput.billing_address of required type BillingAddressInput!'
+ . ' was not provided.',
+ ],
+ 'missed_cart_id' => [
+ 'billing_address: {}',
+ 'Required parameter "cart_id" is missing'
+ ]
+ ];
+ }
}
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 7484b2af7569d..017b85ba17b93 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
@@ -126,6 +126,90 @@ public function testSetPaymentMethodToCustomerCart()
$this->graphQlQuery($query);
}
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ * @param string $input
+ * @param string $message
+ * @dataProvider dataProviderSetPaymentMethodWithoutRequiredParameters
+ */
+ public function testSetPaymentMethodWithoutRequiredParameters(string $input, string $message)
+ {
+ $query = <<expectExceptionMessage($message);
+ $this->graphQlQuery($query);
+ }
+ /**
+ * @return array
+ */
+ public function dataProviderSetPaymentMethodWithoutRequiredParameters(): array
+ {
+ return [
+ 'missed_cart_id' => [
+ 'payment_method: {code: "' . Checkmo::PAYMENT_METHOD_CHECKMO_CODE . '"}',
+ 'Required parameter "cart_id" is missing.'
+ ],
+ 'missed_payment_method' => [
+ 'cart_id: "test"',
+ 'Required parameter "code" for "payment_method" is missing.'
+ ],
+ 'missed_payment_method_code' => [
+ 'cart_id: "test", payment_method: {code: ""}',
+ 'Required parameter "code" for "payment_method" is missing.'
+ ],
+ ];
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id"
+ */
+ public function testSetPaymentOnNonExistentCart()
+ {
+ $maskedQuoteId = 'non_existent_masked_id';
+ $query = <<graphQlQuery($query);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_payment_saved.php
+ */
+ public function testReSetPayment()
+ {
+ /** @var \Magento\Quote\Model\Quote $quote */
+ $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1_with_payment');
+ $this->unAssignCustomerFromQuote('test_order_1_with_payment');
+ $methodCode = Checkmo::PAYMENT_METHOD_CHECKMO_CODE;
+ $query = $this->prepareMutationQuery($maskedQuoteId, $methodCode);
+ $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']);
+ }
+
/**
* @param string $maskedQuoteId
* @param string $methodCode
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
new file mode 100644
index 0000000000000..33aeb2b902a8f
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php
@@ -0,0 +1,374 @@
+quoteResource = $objectManager->get(QuoteResource::class);
+ $this->quoteFactory = $objectManager->get(QuoteFactory::class);
+ $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ */
+ public function testSetNewShippingAddress()
+ {
+ $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address');
+
+ $query = <<graphQlQuery($query);
+
+ self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']);
+ $cartResponse = $response['setShippingAddressesOnCart']['cart'];
+ self::assertArrayHasKey('shipping_addresses', $cartResponse);
+ $shippingAddressResponse = current($cartResponse['shipping_addresses']);
+ $this->assertNewShippingAddressFields($shippingAddressResponse);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage The Cart includes virtual product(s) only, so a shipping address is not used.
+ */
+ public function testSetNewShippingAddressOnQuoteWithVirtualProducts()
+ {
+ $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_virtual_product_without_address');
+
+ $query = <<graphQlQuery($query);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage The current customer isn't authorized.
+ */
+ public function testSetShippingAddressFromAddressBook()
+ {
+ $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address');
+
+ $query = <<graphQlQuery($query);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @expectedException \Exception
+ */
+ public function testSetShippingAddressToCustomerCart()
+ {
+ $maskedQuoteId = $this->assignQuoteToCustomer('test_order_with_simple_product_without_address', 1);
+
+ $query = <<expectExceptionMessage(
+ "The current user cannot perform operations on cart \"$maskedQuoteId\""
+ );
+
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @dataProvider dataProviderUpdateWithMissedRequiredParameters
+ * @param string $input
+ * @param string $message
+ * @throws \Exception
+ */
+ public function testSetNewShippingAddressWithMissedRequiredParameters(string $input, string $message)
+ {
+ $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address');
+
+ $query = <<expectExceptionMessage($message);
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @return array
+ */
+ public function dataProviderUpdateWithMissedRequiredParameters()
+ {
+ return [
+ 'shipping_addresses' => [
+ '',
+ 'The shipping address must contain either "customer_address_id" or "address".',
+ ],
+ 'missed_city' => [
+ 'address: { save_in_address_book: false }',
+ 'Field CartAddressInput.city of required type String! was not provided'
+ ]
+ ];
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @expectedException \Exception
+ * @expectedExceptionMessage You cannot specify multiple shipping addresses.
+ */
+ public function testSetMultipleNewShippingAddresses()
+ {
+ $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address');
+
+ $query = <<graphQlQuery($query);
+ }
+
+ /**
+ * Verify the all the whitelisted fields for a New Address Object
+ *
+ * @param array $shippingAddressResponse
+ */
+ private function assertNewShippingAddressFields(array $shippingAddressResponse): void
+ {
+ $assertionMap = [
+ ['response_field' => 'firstname', 'expected_value' => 'test firstname'],
+ ['response_field' => 'lastname', 'expected_value' => 'test lastname'],
+ ['response_field' => 'company', 'expected_value' => 'test company'],
+ ['response_field' => 'street', 'expected_value' => [0 => 'test street 1', 1 => 'test street 2']],
+ ['response_field' => 'city', 'expected_value' => 'test city'],
+ ['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']
+ ];
+
+ $this->assertResponseFields($shippingAddressResponse, $assertionMap);
+ }
+
+ /**
+ * @param string $reversedQuoteId
+ * @return string
+ */
+ private function getMaskedQuoteIdByReversedQuoteId(string $reversedQuoteId): string
+ {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id');
+
+ return $this->quoteIdToMaskedId->execute((int)$quote->getId());
+ }
+
+ /**
+ * @param string $reversedQuoteId
+ * @param int $customerId
+ * @return string
+ */
+ private function assignQuoteToCustomer(
+ string $reversedQuoteId = 'test_order_with_simple_product_without_address',
+ int $customerId = 1
+ ): string {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id');
+ $quote->setCustomerId($customerId);
+ $this->quoteResource->save($quote);
+ return $this->quoteIdToMaskedId->execute((int)$quote->getId());
+ }
+}
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
new file mode 100644
index 0000000000000..f159cb6f6151e
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php
@@ -0,0 +1,167 @@
+quoteResource = $objectManager->get(QuoteResource::class);
+ $this->quoteFactory = $objectManager->get(QuoteFactory::class);
+ $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class);
+ }
+
+ public function testShippingMethodWithVirtualProduct()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testShippingMethodWithSimpleProduct()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testShippingMethodWithSimpleProductWithoutAddress()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testSetShippingMethodWithMissedRequiredParameters()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testSetNonExistentShippingMethod()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testSetShippingMethodIfAddressIsNotBelongToCart()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testSetShippingMethodToNonExistentCart()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testSetShippingMethodToGuestCart()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testSetShippingMethodToAnotherCustomerCart()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testSetShippingMethodToNonExistentCartAddress()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testSetShippingMethodToGuestCartAddress()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testSetShippingMethodToAnotherCustomerCartAddress()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ public function testSetMultipleShippingMethods()
+ {
+ $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422');
+ }
+
+ /**
+ * @param string $maskedQuoteId
+ * @param string $shippingMethodCode
+ * @param string $shippingCarrierCode
+ * @param string $shippingAddressId
+ * @return string
+ * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
+ */
+ private function prepareMutationQuery(
+ string $maskedQuoteId,
+ string $shippingMethodCode,
+ string $shippingCarrierCode,
+ string $shippingAddressId
+ ) : string {
+ return <<quoteFactory->create();
+ $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id');
+
+ return $this->quoteIdToMaskedId->execute((int)$quote->getId());
+ }
+}
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
new file mode 100644
index 0000000000000..fca7a4287620b
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php
@@ -0,0 +1,273 @@
+quoteResource = $objectManager->get(QuoteResource::class);
+ $this->quoteFactory = $objectManager->get(QuoteFactory::class);
+ $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class);
+ $this->productRepository = $objectManager->get(ProductRepositoryInterface::class);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ */
+ public function testUpdateCartItemQty()
+ {
+ $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;
+
+ $query = $this->getQuery($maskedQuoteId, $itemId, $qty);
+ $response = $this->graphQlQuery($query);
+
+ $this->assertArrayHasKey('updateCartItems', $response);
+ $this->assertArrayHasKey('cart', $response['updateCartItems']);
+
+ $responseCart = $response['updateCartItems']['cart'];
+ $item = current($responseCart['items']);
+
+ $this->assertEquals($itemId, $item['id']);
+ $this->assertEquals($qty, $item['qty']);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ */
+ public function testRemoveCartItemIfQuantityIsZero()
+ {
+ $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 = 0;
+
+ $query = $this->getQuery($maskedQuoteId, $itemId, $qty);
+ $response = $this->graphQlQuery($query);
+
+ $this->assertArrayHasKey('updateCartItems', $response);
+ $this->assertArrayHasKey('cart', $response['updateCartItems']);
+
+ $responseCart = $response['updateCartItems']['cart'];
+ $this->assertCount(0, $responseCart['items']);
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id"
+ */
+ public function testUpdateItemInNonExistentCart()
+ {
+ $query = $this->getQuery('non_existent_masked_id', 1, 2);
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ */
+ public function testUpdateNonExistentItem()
+ {
+ $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());
+ $notExistentItemId = 999;
+
+ $this->expectExceptionMessage("Could not find cart item with id: {$notExistentItemId}.");
+
+ $query = $this->getQuery($maskedQuoteId, $notExistentItemId, 2);
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php
+ */
+ public function testUpdateItemIfItemIsNotBelongToCart()
+ {
+ $firstQuote = $this->quoteFactory->create();
+ $this->quoteResource->load($firstQuote, 'test_order_with_simple_product_without_address', 'reserved_order_id');
+ $firstQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$firstQuote->getId());
+
+ $secondQuote = $this->quoteFactory->create();
+ $this->quoteResource->load(
+ $secondQuote,
+ 'test_order_with_virtual_product_without_address',
+ 'reserved_order_id'
+ );
+ $secondQuoteItemId = (int)$secondQuote
+ ->getItemByProduct($this->productRepository->get('virtual-product'))
+ ->getId();
+
+ $this->expectExceptionMessage("Could not find cart item with id: {$secondQuoteItemId}.");
+
+ $query = $this->getQuery($firstQuoteMaskedId, $secondQuoteItemId, 2);
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ */
+ public function testUpdateItemFromCustomerCart()
+ {
+ $customerQuote = $this->quoteFactory->create();
+ $this->quoteResource->load($customerQuote, 'test_order_1', 'reserved_order_id');
+ $customerQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$customerQuote->getId());
+ $customerQuoteItemId = (int)$customerQuote->getItemByProduct($this->productRepository->get('simple'))->getId();
+
+ $this->expectExceptionMessage("The current user cannot perform operations on cart \"$customerQuoteMaskedId\"");
+
+ $query = $this->getQuery($customerQuoteMaskedId, $customerQuoteItemId, 2);
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Required parameter "cart_id" is missing.
+ */
+ public function testUpdateWithMissedCartItemId()
+ {
+ $query = <<graphQlQuery($query);
+ }
+
+ /**
+ * @param string $input
+ * @param string $message
+ * @dataProvider dataProviderUpdateWithMissedRequiredParameters
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+ */
+ public function testUpdateWithMissedItemRequiredParameters(string $input, string $message)
+ {
+ $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());
+
+ $query = <<expectExceptionMessage($message);
+ $this->graphQlQuery($query);
+ }
+
+ /**
+ * @return array
+ */
+ public function dataProviderUpdateWithMissedRequiredParameters(): array
+ {
+ return [
+ 'missed_cart_items' => [
+ '',
+ 'Required parameter "cart_items" is missing.'
+ ],
+ 'missed_cart_item_id' => [
+ 'cart_items: [{ quantity: 2 }]',
+ 'Required parameter "cart_item_id" for "cart_items" is missing.'
+ ],
+ 'missed_cart_item_qty' => [
+ 'cart_items: [{ cart_item_id: 1 }]',
+ 'Required parameter "quantity" for "cart_items" is missing.'
+ ],
+ ];
+ }
+
+ /**
+ * @param string $maskedQuoteId
+ * @param int $itemId
+ * @param float $qty
+ * @return string
+ */
+ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): string
+ {
+ return <<quoteResource = $objectManager->get(QuoteResource::class);
+ $this->quoteFactory = $objectManager->get(QuoteFactory::class);
+ $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class);
+ $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+ * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php
+ */
+ public function testSetUpsShippingMethod()
+ {
+ $quote = $this->quoteFactory->create();
+ $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id');
+ $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId());
+ $shippingAddressId = (int)$quote->getShippingAddress()->getId();
+
+ $query = $this->getAddUpsShippingMethodQuery(
+ $maskedQuoteId,
+ $shippingAddressId,
+ self::CARRIER_CODE,
+ self::CARRIER_METHOD_CODE_GROUND
+ );
+
+ $response = $this->sendRequestWithToken($query);
+ $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses'];
+ $expectedResult = [
+ 'carrier_code' => self::CARRIER_CODE,
+ 'method_code' => self::CARRIER_METHOD_CODE_GROUND,
+ 'label' => 'United Parcel Service - Ground',
+ ];
+ self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult);
+ }
+
+ /**
+ * Generates query for setting the specified shipping method on cart
+ *
+ * @param int $shippingAddressId
+ * @param string $maskedQuoteId
+ * @param string $carrierCode
+ * @param string $methodCode
+ * @return string
+ */
+ private function getAddUpsShippingMethodQuery(
+ string $maskedQuoteId,
+ int $shippingAddressId,
+ string $carrierCode,
+ string $methodCode
+ ): string {
+ return <<customerTokenService->createCustomerAccessToken('customer@example.com', 'password');
+ $headerMap = ['Authorization' => 'Bearer ' . $customerToken];
+
+ return $this->graphQlQuery($query, [], '', $headerMap);
+ }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php
index c70b1631e85cd..370121a1dad78 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php
@@ -31,7 +31,7 @@ protected function setUp()
}
/**
- * Tests if target_path(canonical_url) is resolved for Product entity
+ * Tests if target_path(relative_url) is resolved for Product entity
*
* @magentoApiDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php
*/
@@ -60,7 +60,7 @@ public function testProductUrlResolver()
urlResolver(url:"{$urlPath}")
{
id
- canonical_url
+ relative_url
type
}
}
@@ -68,12 +68,12 @@ public function testProductUrlResolver()
$response = $this->graphQlQuery($query);
$this->assertArrayHasKey('urlResolver', $response);
$this->assertEquals($product->getEntityId(), $response['urlResolver']['id']);
- $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']);
+ $this->assertEquals($targetPath, $response['urlResolver']['relative_url']);
$this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']);
}
/**
- * Tests the use case where canonical_url is provided as resolver input in the Query
+ * Tests the use case where relative_url is provided as resolver input in the Query
*
* @magentoApiDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php
*/
@@ -104,7 +104,7 @@ public function testProductUrlWithCanonicalUrlInput()
urlResolver(url:"{$canonicalPath}")
{
id
- canonical_url
+ relative_url
type
}
}
@@ -112,7 +112,7 @@ public function testProductUrlWithCanonicalUrlInput()
$response = $this->graphQlQuery($query);
$this->assertArrayHasKey('urlResolver', $response);
$this->assertEquals($product->getEntityId(), $response['urlResolver']['id']);
- $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']);
+ $this->assertEquals($targetPath, $response['urlResolver']['relative_url']);
$this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']);
}
@@ -147,7 +147,7 @@ public function testCategoryUrlResolver()
urlResolver(url:"{$urlPath2}")
{
id
- canonical_url
+ relative_url
type
}
}
@@ -155,7 +155,7 @@ public function testCategoryUrlResolver()
$response = $this->graphQlQuery($query);
$this->assertArrayHasKey('urlResolver', $response);
$this->assertEquals($categoryId, $response['urlResolver']['id']);
- $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']);
+ $this->assertEquals($targetPath, $response['urlResolver']['relative_url']);
$this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']);
}
@@ -183,14 +183,14 @@ public function testCMSPageUrlResolver()
urlResolver(url:"{$requestPath}")
{
id
- canonical_url
+ relative_url
type
}
}
QUERY;
$response = $this->graphQlQuery($query);
$this->assertEquals($cmsPageId, $response['urlResolver']['id']);
- $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']);
+ $this->assertEquals($targetPath, $response['urlResolver']['relative_url']);
$this->assertEquals(strtoupper(str_replace('-', '_', $expectedEntityType)), $response['urlResolver']['type']);
}
@@ -226,7 +226,7 @@ public function testProductUrlRewriteResolver()
urlResolver(url:"{$urlPath}")
{
id
- canonical_url
+ relative_url
type
}
}
@@ -234,7 +234,7 @@ public function testProductUrlRewriteResolver()
$response = $this->graphQlQuery($query);
$this->assertArrayHasKey('urlResolver', $response);
$this->assertEquals($product->getEntityId(), $response['urlResolver']['id']);
- $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']);
+ $this->assertEquals($targetPath, $response['urlResolver']['relative_url']);
$this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']);
}
@@ -266,7 +266,7 @@ public function testInvalidUrlResolverInput()
urlResolver(url:"{$urlPath}")
{
id
- canonical_url
+ relative_url
type
}
}
@@ -307,7 +307,7 @@ public function testCategoryUrlWithLeadingSlash()
urlResolver(url:"/{$urlPath}")
{
id
- canonical_url
+ relative_url
type
}
}
@@ -315,7 +315,7 @@ public function testCategoryUrlWithLeadingSlash()
$response = $this->graphQlQuery($query);
$this->assertArrayHasKey('urlResolver', $response);
$this->assertEquals($categoryId, $response['urlResolver']['id']);
- $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']);
+ $this->assertEquals($targetPath, $response['urlResolver']['relative_url']);
$this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']);
}
@@ -344,7 +344,7 @@ public function testResolveSlash()
urlResolver(url:"/")
{
id
- canonical_url
+ relative_url
type
}
}
@@ -352,7 +352,7 @@ public function testResolveSlash()
$response = $this->graphQlQuery($query);
$this->assertArrayHasKey('urlResolver', $response);
$this->assertEquals($homePageId, $response['urlResolver']['id']);
- $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']);
+ $this->assertEquals($targetPath, $response['urlResolver']['relative_url']);
$this->assertEquals('CMS_PAGE', $response['urlResolver']['type']);
}
}
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Wishlist/WishlistTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Wishlist/WishlistTest.php
index d570fc09b7714..4aac5d9445934 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Wishlist/WishlistTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Wishlist/WishlistTest.php
@@ -93,6 +93,36 @@ public function testGetCustomerWishlist(): void
$this->assertEquals($wishlistItemProduct->getName(), $response['wishlist']['items'][0]['product']['name']);
}
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage The current user cannot perform operations on wishlist
+ */
+ public function testGetGuestWishlist()
+ {
+ $query =
+ <<graphQlQuery($query);
+ }
+
/**
* @param string $email
* @param string $password
diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/ConditionsElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/ConditionsElement.php
index 6dbf2b1aa6a12..03492f7ae1a9e 100644
--- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/ConditionsElement.php
+++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/ConditionsElement.php
@@ -195,6 +195,13 @@ class ConditionsElement extends SimpleElement
*/
protected $exception;
+ /**
+ * Condition option text selector.
+ *
+ * @var string
+ */
+ private $conditionOptionTextSelector = '//option[normalize-space(text())="%s"]';
+
/**
* @inheritdoc
*/
@@ -265,7 +272,7 @@ protected function addSingleCondition($condition, ElementInterface $context)
$this->addCondition($condition['type'], $context);
$createdCondition = $context->find($this->created, Locator::SELECTOR_XPATH);
$this->waitForCondition($createdCondition);
- $this->fillCondition($condition['rules'], $createdCondition);
+ $this->fillCondition($condition['rules'], $createdCondition, $condition['type']);
}
/**
@@ -282,10 +289,16 @@ protected function addCondition($type, ElementInterface $context)
$count = 0;
do {
- $newCondition->find($this->addNew, Locator::SELECTOR_XPATH)->click();
-
try {
- $newCondition->find($this->typeNew, Locator::SELECTOR_XPATH, 'select')->setValue($type);
+ $specificType = $newCondition->find(
+ sprintf($this->conditionOptionTextSelector, $type),
+ Locator::SELECTOR_XPATH
+ )->isPresent();
+ $newCondition->find($this->addNew, Locator::SELECTOR_XPATH)->click();
+ $condition = $specificType
+ ? $newCondition->find($this->typeNew, Locator::SELECTOR_XPATH, 'selectcondition')
+ : $newCondition->find($this->typeNew, Locator::SELECTOR_XPATH, 'select');
+ $condition->setValue($type);
$isSetType = true;
} catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
$isSetType = false;
@@ -306,13 +319,14 @@ protected function addCondition($type, ElementInterface $context)
*
* @param array $rules
* @param ElementInterface $element
+ * @param string|null $type
* @return void
* @throws \Exception
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
- protected function fillCondition(array $rules, ElementInterface $element)
+ protected function fillCondition(array $rules, ElementInterface $element, $type = null)
{
$this->resetKeyParam();
foreach ($rules as $rule) {
@@ -333,7 +347,7 @@ protected function fillCondition(array $rules, ElementInterface $element)
if ($this->fillGrid($rule, $param)) {
$isSet = true;
- } elseif ($this->fillSelect($rule, $param)) {
+ } elseif ($this->fillSelect($rule, $param, $type)) {
$isSet = true;
} elseif ($this->fillText($rule, $param)) {
$isSet = true;
@@ -390,11 +404,15 @@ protected function fillGrid($rule, ElementInterface $param)
*
* @param string $rule
* @param ElementInterface $param
+ * @param string|null $type
* @return bool
*/
- protected function fillSelect($rule, ElementInterface $param)
+ protected function fillSelect($rule, ElementInterface $param, $type = null)
{
- $value = $param->find('select', Locator::SELECTOR_TAG_NAME, 'select');
+ //Avoid confusion between regions like: "Baja California" and "California".
+ $value = strpos($type, 'State/Province') === false
+ ? $param->find('select', Locator::SELECTOR_TAG_NAME, 'select')
+ : $param->find('select', Locator::SELECTOR_TAG_NAME, 'selectstate');
if ($value->isVisible()) {
$value->setValue($rule);
$this->click();
diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/SelectconditionElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/SelectconditionElement.php
new file mode 100644
index 0000000000000..15a799eac5188
--- /dev/null
+++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/SelectconditionElement.php
@@ -0,0 +1,20 @@
+stepFactory = $stepFactory;
$this->fixtureFactory = $fixtureFactory;
$this->adminExportIndex = $adminExportIndex;
$this->catalogProductIndex = $catalogProductIndexPage;
+ $this->cron = $cron;
}
/**
@@ -130,8 +140,12 @@ public function test(
if ($website) {
$website->persist();
$this->setupCurrencyForCustomWebsite($website, $currencyCustomWebsite);
+ $this->cron->run();
+ $this->cron->run();
}
$products = $this->prepareProducts($products, $website);
+ $this->cron->run();
+ $this->cron->run();
$this->adminExportIndex->open();
$this->adminExportIndex->getExportedGrid()->deleteAllExportedFiles();
$exportData = $this->fixtureFactory->createByCode(
diff --git a/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.xml b/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.xml
index d069499da4aab..07646c2aceda8 100644
--- a/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.xml
+++ b/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.xml
@@ -50,7 +50,6 @@
- MC-13864 Consumer always read config from memory
price_scope_website
csv_with_advanced_pricing
diff --git a/dev/tests/functional/tests/app/Magento/Analytics/Test/TestCase/AdvancedReportingButtonTest.xml b/dev/tests/functional/tests/app/Magento/Analytics/Test/TestCase/AdvancedReportingButtonTest.xml
index a975d19ef8879..89c9d9168921f 100644
--- a/dev/tests/functional/tests/app/Magento/Analytics/Test/TestCase/AdvancedReportingButtonTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Analytics/Test/TestCase/AdvancedReportingButtonTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
https://advancedreporting.rjmetrics.com/report
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/Dashboard.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/Dashboard.xml
index adae65a1d06d6..799f9e30fd972 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/Dashboard.xml
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/Dashboard.xml
@@ -17,5 +17,6 @@
+
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/ValidateOrderOfProductTypeTest.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/ValidateOrderOfProductTypeTest.xml
index 7077f367795ed..cb32742a0ce6b 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/ValidateOrderOfProductTypeTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/ValidateOrderOfProductTypeTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
Bundle Product
diff --git a/dev/tests/functional/tests/app/Magento/BundleImportExport/Test/TestCase/ExportProductsTest.xml b/dev/tests/functional/tests/app/Magento/BundleImportExport/Test/TestCase/ExportProductsTest.xml
index 3ad8cff31eaf8..bfbe233b9dc1b 100644
--- a/dev/tests/functional/tests/app/Magento/BundleImportExport/Test/TestCase/ExportProductsTest.xml
+++ b/dev/tests/functional/tests/app/Magento/BundleImportExport/Test/TestCase/ExportProductsTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
default
- bundleProduct
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ValidateOrderOfProductTypeTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ValidateOrderOfProductTypeTest.xml
index 0d1a34ab52f97..ec776128fdfe3 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ValidateOrderOfProductTypeTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ValidateOrderOfProductTypeTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
Simple Product
Virtual Product
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteUsedInConfigurableProductAttributeTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteUsedInConfigurableProductAttributeTest.xml
index df396c22312b1..e46174de8818f 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteUsedInConfigurableProductAttributeTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteUsedInConfigurableProductAttributeTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
one_variation
diff --git a/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ExportProductsTest.php b/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ExportProductsTest.php
index e55558482c1f3..b5cd056fb99ad 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ExportProductsTest.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ExportProductsTest.php
@@ -104,6 +104,8 @@ public function test(
$exportData->persist();
$this->adminExportIndex->getExportForm()->fill($exportData);
$this->adminExportIndex->getFilterExport()->clickContinue();
+ $this->cron->run();
+ $this->cron->run();
$this->assertExportProduct->processAssert($export, $exportedFields, $products);
}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ExportProductsTest.xml b/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ExportProductsTest.xml
index b94f21371496a..be22eab8ac717 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ExportProductsTest.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ExportProductsTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
default
- catalogProductSimple
@@ -27,6 +28,7 @@
+ mftf_migrated:yes
default
- catalogProductSimple
@@ -43,6 +45,7 @@
+ mftf_migrated:yes
default
- catalogProductSimple
@@ -58,7 +61,7 @@
- >MC-13864 Consumer always read config from memory
+ mftf_migrated:yes
default
- catalogProductSimple
diff --git a/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ImportProductsTest.xml b/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ImportProductsTest.xml
index edb0aad954fbb..77e5e2b91d93f 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ImportProductsTest.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogImportExport/Test/TestCase/ImportProductsTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
- Products
- Add/Update
@@ -38,6 +39,7 @@
+ mftf_migrated:yes
Products
Replace
Stop on Error
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/CreateSearchTermEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/CreateSearchTermEntityTest.xml
index 0437e0a5e999b..8c465544a3283 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/CreateSearchTermEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/CreateSearchTermEntityTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
catalogProductSimple::sku
Main Website/Main Website Store/Default Store View
http://example.com/
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/DeleteSearchTermEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/DeleteSearchTermEntityTest.xml
index a9cc0dfd34f9f..8fdd7ef715521 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/DeleteSearchTermEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/DeleteSearchTermEntityTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
default
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/MassDeleteSearchTermEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/MassDeleteSearchTermEntityTest.xml
index 3bf4e521c4a04..3ef2b65c0224b 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/MassDeleteSearchTermEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/MassDeleteSearchTermEntityTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
catalogSearchQuery::default,catalogSearchQuery::default,catalogSearchQuery::default
diff --git a/dev/tests/functional/tests/app/Magento/CatalogUrlRewrite/Test/TestCase/CreateDuplicateUrlCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogUrlRewrite/Test/TestCase/CreateDuplicateUrlCategoryEntityTest.xml
index 398054f1f0ed3..8b15da5ecd2ef 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogUrlRewrite/Test/TestCase/CreateDuplicateUrlCategoryEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogUrlRewrite/Test/TestCase/CreateDuplicateUrlCategoryEntityTest.xml
@@ -14,7 +14,7 @@
Yes
Subcategory%isolation%
subcategory-%isolation%
- test_type:acceptance_test, test_type:extended_acceptance_test, severity:S1
+ test_type:acceptance_test, test_type:extended_acceptance_test, severity:S1, mftf_migrated:yes
diff --git a/dev/tests/functional/tests/app/Magento/CatalogUrlRewrite/Test/TestCase/CreateDuplicateUrlProductEntity.xml b/dev/tests/functional/tests/app/Magento/CatalogUrlRewrite/Test/TestCase/CreateDuplicateUrlProductEntity.xml
index 1116821f756a9..8110ed1ed00b1 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogUrlRewrite/Test/TestCase/CreateDuplicateUrlProductEntity.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogUrlRewrite/Test/TestCase/CreateDuplicateUrlProductEntity.xml
@@ -8,7 +8,7 @@
- test_type:acceptance_test, test_type:extended_acceptance_test, severity:S1
+ test_type:acceptance_test, test_type:extended_acceptance_test, severity:S1, mftf_migrated:yes
simple-product-%isolation%
Simple Product %isolation%
simple_sku_%isolation%
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 8b2460718097c..b4c97a11b9145 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
@@ -9,7 +9,7 @@
https://github.com/magento-engcom/msi/issues/1624
- test_type:extended_acceptance_test, severity:S0
+ test_type:extended_acceptance_test, severity:S0, mftf_migrated:yes
catalogProductSimple::default
simple_order_qty_2
true
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.xml
index e0ea721a51f1b..5caa3ba9b924e 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.xml
@@ -8,7 +8,7 @@
- severity:S0
+ severity:S0,mftf_migrated:yes
default
100
3
@@ -20,7 +20,7 @@
- severity:S0
+ severity:S0,mftf_migrated:yes
with_two_custom_option
50
11
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableImportExport/Test/TestCase/ExportProductsTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableImportExport/Test/TestCase/ExportProductsTest.xml
index 93240586ec92c..0a2ce7ab7f183 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableImportExport/Test/TestCase/ExportProductsTest.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableImportExport/Test/TestCase/ExportProductsTest.xml
@@ -30,6 +30,7 @@
+ mftf_migrated:yes
default
- configurableProduct
@@ -45,7 +46,7 @@
- >MC-13864 Consumer always read config from memory
+ mftf_migrated:yes
default
- configurableProduct
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml
index e1b6fcf47e562..f831173ba0ae0 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
configurable-product-%isolation%
two_new_options
configurable_two_options
@@ -32,6 +33,7 @@
+ mftf_migrated:yes
configurable-product-%isolation%
two_options
configurable_two_options
@@ -97,6 +99,7 @@
+ mftf_migrated:yes
configurable-product-%isolation%
two_options_with_fixed_price
Configurable Product %isolation%
@@ -113,7 +116,7 @@
- test_type:acceptance_test, test_type:extended_acceptance_test
+ test_type:acceptance_test, test_type:extended_acceptance_test, mftf_migrated:yes
two_searchable_options
Configurable Product %isolation%
configurable_sku_%isolation%
@@ -129,6 +132,7 @@
+ mftf_migrated:yes
two_new_options_with_empty_sku
Configurable Product %isolation%
configurable_sku_%isolation%
@@ -137,6 +141,7 @@
+ mftf_migrated:yes
two_new_options_with_parent_sku
Configurable Product %isolation%
existing_sku
@@ -145,6 +150,7 @@
+ mftf_migrated:yes
configurable-product-%isolation%
two_options_with_assigned_product_special_price
configurable_two_new_options_with_special_price
@@ -156,6 +162,7 @@
+ mftf_migrated:yes
configurable-product-%isolation%
two_options_with_assigned_product_tier_price
configurable_two_new_options_with_special_price
@@ -170,7 +177,7 @@
- test_type:acceptance_test, test_type:extended_acceptance_test
+ test_type:acceptance_test, test_type:extended_acceptance_test, mftf_migrated:yes
with_out_of_stock_item
Configurable Product %isolation%
configurable_sku_%isolation%
@@ -189,7 +196,7 @@
- test_type:acceptance_test, test_type:extended_acceptance_test
+ test_type:acceptance_test, test_type:extended_acceptance_test, mftf_migrated:yes
with_disabled_item
Configurable Product %isolation%
configurable_sku_%isolation%
@@ -207,7 +214,7 @@
- test_type:acceptance_test, test_type:extended_acceptance_test
+ test_type:acceptance_test, test_type:extended_acceptance_test, mftf_migrated:yes
with_one_disabled_item_and_one_out_of_stock_item
Configurable Product %isolation%
configurable_sku_%isolation%
@@ -225,6 +232,7 @@
+ mftf_migrated:yes
color_and_size_with_images
Configurable Product %isolation%
configurable_sku_%isolation%
@@ -238,6 +246,7 @@
+ mftf_migrated:yes
configurable-product-%isolation%
three_new_options_with_out_of_stock_product
Configurable Product %isolation%
@@ -254,6 +263,7 @@
+ mftf_migrated:yes
configurable-product-%isolation%
three_new_options_with_out_of_stock_product
Configurable Product %isolation%
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/ValidateOrderOfProductTypeTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/ValidateOrderOfProductTypeTest.xml
index a62bcf92ebf39..5af854cae5434 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/ValidateOrderOfProductTypeTest.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/ValidateOrderOfProductTypeTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
Configurable Product
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest.xml
index 5bb96dc13c739..ff87a1df60fe8 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
save
Main Website
General
@@ -35,7 +36,7 @@
- test_type:extended_acceptance_test
+ test_type:extended_acceptance_test, mftf_migrated:yes
save
Main Website
General
@@ -55,6 +56,7 @@
+ mftf_migrated:yes
save
Main Website
Retailer
@@ -64,6 +66,7 @@
+ mftf_migrated:yes
save
Main Website
General
@@ -83,6 +86,7 @@
+ mftf_migrated:yes
saveAndContinue
Main Website
General
@@ -105,6 +109,7 @@
+ mftf_migrated:yes
save
Main Website
General
@@ -116,6 +121,7 @@
+ mftf_migrated:yes
Main Website
General
John%isolation%
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.xml
index 24f68f686fdc1..095746cfdef57 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.xml
@@ -25,6 +25,7 @@
+ mftf_migrated:yes
default
-
Prefix%isolation%_
@@ -75,6 +76,7 @@
+ mftf_migrated:yes
default
-
Yes
@@ -95,6 +97,7 @@
+ mftf_migrated:yes
johndoe_unique_TX
-
No
@@ -114,6 +117,7 @@
+ mftf_migrated:yes
johndoe_with_multiple_addresses
-
1
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/VerifyDisabledCustomerGroupFieldTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/VerifyDisabledCustomerGroupFieldTest.xml
index 70a912a3b5ffe..e88e5161e474e 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/VerifyDisabledCustomerGroupFieldTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/VerifyDisabledCustomerGroupFieldTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
NOT_LOGGED_IN
- customer_group_code
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/ValidateOrderOfProductTypeTest.xml b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/ValidateOrderOfProductTypeTest.xml
index ccb74e1f79dc9..e807ec9134277 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/ValidateOrderOfProductTypeTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/ValidateOrderOfProductTypeTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
Downloadable Product
diff --git a/dev/tests/functional/tests/app/Magento/GroupedImportExport/Test/TestCase/ExportProductsTest.xml b/dev/tests/functional/tests/app/Magento/GroupedImportExport/Test/TestCase/ExportProductsTest.xml
index cffcdbf45a6dc..a110dc6a89f8c 100644
--- a/dev/tests/functional/tests/app/Magento/GroupedImportExport/Test/TestCase/ExportProductsTest.xml
+++ b/dev/tests/functional/tests/app/Magento/GroupedImportExport/Test/TestCase/ExportProductsTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
default
- groupedProduct
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/ValidateOrderOfProductTypeTest.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/ValidateOrderOfProductTypeTest.xml
index 5a5cfdd9adc4c..ac57cdeb92053 100644
--- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/ValidateOrderOfProductTypeTest.xml
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/ValidateOrderOfProductTypeTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
Grouped Product
diff --git a/dev/tests/functional/tests/app/Magento/PageCache/Test/TestCase/FlushStaticFilesCacheButtonVisibilityTest.xml b/dev/tests/functional/tests/app/Magento/PageCache/Test/TestCase/FlushStaticFilesCacheButtonVisibilityTest.xml
index cbdce59057195..bc529729f1217 100644
--- a/dev/tests/functional/tests/app/Magento/PageCache/Test/TestCase/FlushStaticFilesCacheButtonVisibilityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/PageCache/Test/TestCase/FlushStaticFilesCacheButtonVisibilityTest.xml
@@ -8,7 +8,7 @@
- severity:S3
+ severity:S3, mftf_migrated:yes
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCustomOrderStatusEntityTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCustomOrderStatusEntityTest.xml
index 38ce04fa56d81..e05d0fea6b129 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCustomOrderStatusEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCustomOrderStatusEntityTest.xml
@@ -8,17 +8,20 @@
+ mftf_migrated:yes
order_status%isolation%
orderLabel%isolation%
+ mftf_migrated:yes
pending
orderLabel%isolation%
+ mftf_migrated:yes
order_status%isolation%
Suspected Fraud
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml
index 586ad2acee203..4995c1feb048e 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml
@@ -75,7 +75,6 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit - %isolation%
Fixed amount discount for whole cart
60
- No
No
Coupon code+Fixed amount discount for whole cart
simple_for_salesrule_1
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateWebsiteEntityTest.xml b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateWebsiteEntityTest.xml
index 5a547f69280e1..e35ef853d1b68 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateWebsiteEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateWebsiteEntityTest.xml
@@ -8,7 +8,7 @@
- severity:S1
+ severity:S1, mftf_migrated:yes
website_%isolation%
code_%isolation%
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/DeleteStoreEntityTest.xml b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/DeleteStoreEntityTest.xml
index 306a9fd2024a4..cd37c555fdb1d 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/DeleteStoreEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/DeleteStoreEntityTest.xml
@@ -8,7 +8,7 @@
- severity:S2
+ severity:S2, mftf_migrated:yes
custom
Yes
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/DeleteStoreGroupEntityTest.xml b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/DeleteStoreGroupEntityTest.xml
index 66ae1d8179af5..865530862853a 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/DeleteStoreGroupEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/DeleteStoreGroupEntityTest.xml
@@ -8,7 +8,7 @@
- severity:S3
+ severity:S3, mftf_migrated:yes
custom
Yes
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/UpdateWebsiteEntityTest.xml b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/UpdateWebsiteEntityTest.xml
index ac857ad035f44..5db0e7f8baad4 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/UpdateWebsiteEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/UpdateWebsiteEntityTest.xml
@@ -8,7 +8,7 @@
- severity:S2
+ severity:S2, mftf_migrated:yes
custom_website
website_upd%isolation%
code_upd%isolation%
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CategoryUrlRewriteTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CategoryUrlRewriteTest.xml
index 730eb285d6d0c..1f888c3a2a8b9 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CategoryUrlRewriteTest.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CategoryUrlRewriteTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
custom
default
catalogProductSimple::default
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.xml
index 1917ec928bfaf..0cf2fd9c0d4e1 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.xml
@@ -8,7 +8,7 @@
- test_type:acceptance_test, test_type:extended_acceptance_test
+ test_type:acceptance_test, test_type:extended_acceptance_test, mftf_migrated:yes
For Product
product_with_category
Main Website/Main Website Store/Default Store View
@@ -19,6 +19,7 @@
+ mftf_migrated:yes
For Product
default
Main Website/Main Website Store/Default Store View
@@ -28,6 +29,7 @@
+ mftf_migrated:yes
For Product
default
Main Website/Main Website Store/Default Store View
@@ -38,6 +40,7 @@
+ mftf_migrated:yes
For Product
default
Main Website/Main Website Store/Default Store View
@@ -48,6 +51,7 @@
+ mftf_migrated:yes
For Product
product_with_category
Main Website/Main Website Store/Default Store View
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml
index 98e3f9e38382d..8e737f193cf94 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
simple-product-%isolation%
Simple Product %isolation%
simple_sku_%isolation%
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCustomUrlRewriteEntityTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCustomUrlRewriteEntityTest.xml
index 90f5edec2f46b..8e0e8ebde99fb 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCustomUrlRewriteEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCustomUrlRewriteEntityTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
default
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.xml
index 4a88ad01b5a75..b2be1a205212e 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
Main Website/Main Website Store/Default Store View
default_subcategory
default
@@ -20,6 +21,7 @@
+ mftf_migrated:yes
Main Website/Main Website Store/Default Store View
default_subcategory
default
@@ -32,6 +34,7 @@
+ mftf_migrated:yes
Main Website/Main Website Store/Default Store View
default_subcategory
default
@@ -44,6 +47,7 @@
+ mftf_migrated:yes
Main Website/Main Website Store/Default Store View
default_subcategory
default
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCustomUrlRewriteEntityTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCustomUrlRewriteEntityTest.xml
index 3671cd767ece9..2405216c12203 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCustomUrlRewriteEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCustomUrlRewriteEntityTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
default
Main Website/Main Website Store/Default Store View
wishlist/%isolation%
@@ -19,7 +20,7 @@
- test_type:extended_acceptance_test
+ test_type:extended_acceptance_test, mftf_migrated:yes
custom_rewrite_wishlist
Main Website/Main Website Store/Default Store View
wishlist/%isolation%
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest.xml
index 60de554d594d2..8f12930aa417b 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest.xml
@@ -8,6 +8,7 @@
+ mftf_migrated:yes
product/%catalogProductSimple::product_100_dollar%
Main Website/Main Website Store/Default Store View
test_%isolation%.html
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserRoleRestrictedAccess.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserRoleRestrictedAccess.php
index f7c56ae1b9653..ecfbc8d353888 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserRoleRestrictedAccess.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserRoleRestrictedAccess.php
@@ -10,6 +10,7 @@
use Magento\Mtf\Client\BrowserInterface;
use Magento\Mtf\Constraint\AbstractConstraint;
use Magento\User\Test\Fixture\User;
+use Magento\User\Test\TestStep\LoginUserOnBackendWithErrorStep;
/**
* Asserts that user has only related permissions.
@@ -18,6 +19,8 @@ class AssertUserRoleRestrictedAccess extends AbstractConstraint
{
const DENIED_ACCESS = 'Sorry, you need permissions to view this content.';
+ protected $loginStep = 'Magento\User\Test\TestStep\LoginUserOnBackendStep';
+
/**
* Asserts that user has only related permissions.
*
@@ -36,7 +39,7 @@ public function processAssert(
$denyUrl
) {
$this->objectManager->create(
- \Magento\User\Test\TestStep\LoginUserOnBackendStep::class,
+ $this->loginStep,
['user' => $user]
)->run();
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserRoleRestrictedAccessWithError.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserRoleRestrictedAccessWithError.php
new file mode 100644
index 0000000000000..b001893abb4c4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserRoleRestrictedAccessWithError.php
@@ -0,0 +1,17 @@
+objectManager->create(
- \Magento\User\Test\TestStep\LoginUserOnBackendStep::class,
+ $this->loginStep,
['user' => $user]
)->run();
\PHPUnit\Framework\Assert::assertTrue(
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessLoginWithError.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessLoginWithError.php
new file mode 100644
index 0000000000000..9fed1f4df8573
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessLoginWithError.php
@@ -0,0 +1,20 @@
+
-
+
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.php b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.php
index cc1d0fc980fbf..58450abc71633 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.php
@@ -121,6 +121,11 @@ public function testUpdateAdminUserRolesEntity(
*/
public function tearDown()
{
+ sleep(3);
+ $modalMessage = $this->dashboard->getModalMessage();
+ if ($modalMessage->isVisible()) {
+ $modalMessage->acceptAlert();
+ }
$this->dashboard->getAdminPanelHeader()->logOut();
}
}
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.xml b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.xml
index 224ccbce10f96..db6a13d0f3551 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.xml
@@ -29,8 +29,8 @@
-
-
+
+
custom_admin_with_default_role
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestStep/CloseErrorAlertStep.php b/dev/tests/functional/tests/app/Magento/User/Test/TestStep/CloseErrorAlertStep.php
new file mode 100644
index 0000000000000..51d48058c8ae5
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestStep/CloseErrorAlertStep.php
@@ -0,0 +1,57 @@
+dashboard = $dashboard;
+ $this->browser = $browser;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function run()
+ {
+ $modalMessage = $this->dashboard->getModalMessage();
+ try {
+ $this->browser->waitUntil(
+ function () use ($modalMessage) {
+ return $modalMessage->isVisible() ? true : null;
+ }
+ );
+ $modalMessage->acceptAlert();
+ } catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
+ //There is no modal to accept.
+ }
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LoginUserOnBackendStep.php b/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LoginUserOnBackendStep.php
index 4f7e6deed7a85..c244e27d42899 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LoginUserOnBackendStep.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LoginUserOnBackendStep.php
@@ -50,7 +50,7 @@ class LoginUserOnBackendStep implements TestStepInterface
*
* @var BrowserInterface
*/
- private $browser;
+ protected $browser;
/**
* Array of error messages on admin login form.
@@ -108,8 +108,6 @@ public function run()
}
}
}
-
- $this->dashboard->getSystemMessageDialog()->closePopup();
}
/**
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LoginUserOnBackendWithErrorStep.php b/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LoginUserOnBackendWithErrorStep.php
new file mode 100644
index 0000000000000..094f90d0a5d70
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LoginUserOnBackendWithErrorStep.php
@@ -0,0 +1,53 @@
+closeErrorAlertStep = $closeErrorAlertStep;
+ }
+
+ /**
+ * Run step flow.
+ *
+ * @return void
+ */
+ public function run()
+ {
+ parent::run();
+ $this->closeErrorAlertStep->run();
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LogoutUserOnBackendStep.php b/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LogoutUserOnBackendStep.php
index 70a4080a0b4d5..7f366312bba24 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LogoutUserOnBackendStep.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LogoutUserOnBackendStep.php
@@ -48,7 +48,6 @@ public function __construct(AdminAuthLogin $adminAuth, Dashboard $dashboard)
public function run()
{
$this->adminAuth->open();
- $this->dashboard->getSystemMessageDialog()->closePopup();
$this->dashboard->getAdminPanelHeader()->logOut();
}
}
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LogoutUserOnBackendWithErrorStep.php b/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LogoutUserOnBackendWithErrorStep.php
new file mode 100644
index 0000000000000..ce49e86afc065
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestStep/LogoutUserOnBackendWithErrorStep.php
@@ -0,0 +1,40 @@
+closeErrorAlertStep = $closeErrorAlertStep;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function run()
+ {
+ $this->adminAuth->open();
+ $this->closeErrorAlertStep->run();
+ $this->dashboard->getAdminPanelHeader()->logOut();
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/User/Test/etc/di.xml
new file mode 100644
index 0000000000000..1298bd56a8fb0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/User/Test/etc/di.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ \Magento\User\Test\TestStep\LogoutUserOnBackendWithErrorStep
+
+
+
diff --git a/dev/tests/integration/framework/Magento/TestFramework/MessageQueue/PublisherConsumerController.php b/dev/tests/integration/framework/Magento/TestFramework/MessageQueue/PublisherConsumerController.php
index 9ca351aa1cf98..32240e68ae73e 100644
--- a/dev/tests/integration/framework/Magento/TestFramework/MessageQueue/PublisherConsumerController.php
+++ b/dev/tests/integration/framework/Magento/TestFramework/MessageQueue/PublisherConsumerController.php
@@ -95,17 +95,9 @@ public function initialize()
$this->amqpHelper->deleteConnection($connectionName);
}
$this->amqpHelper->clearQueue("async.operations.all");
- foreach ($this->consumers as $consumer) {
- foreach ($this->getConsumerProcessIds($consumer) as $consumerProcessId) {
- exec("kill {$consumerProcessId}");
- }
- }
- foreach ($this->consumers as $consumer) {
- if (!$this->getConsumerProcessIds($consumer)) {
- exec("{$this->getConsumerStartCommand($consumer, true)} > /dev/null &");
- }
- sleep(5);
- }
+
+ $this->stopConsumers();
+ $this->startConsumers();
if (file_exists($this->logFilePath)) {
// try to remove before failing the test
@@ -230,4 +222,19 @@ public function getPublisher()
{
return $this->publisher;
}
+
+ /**
+ * Start consumers
+ *
+ * @return void
+ */
+ public function startConsumers(): void
+ {
+ foreach ($this->consumers as $consumer) {
+ if (!$this->getConsumerProcessIds($consumer)) {
+ exec("{$this->getConsumerStartCommand($consumer, true)} > /dev/null &");
+ }
+ sleep(5);
+ }
+ }
}
diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/MassactionTest.php b/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/MassactionTest.php
index 8aeee9cf12494..e11c5ce5d9cf3 100644
--- a/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/MassactionTest.php
+++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/MassactionTest.php
@@ -87,41 +87,6 @@ public function testMassactionDefaultValues()
$this->assertFalse($blockEmpty->isAvailable());
}
- public function testGetJavaScript()
- {
- $this->loadLayout();
-
- $javascript = $this->_block->getJavaScript();
-
- $expectedItemFirst = '#"option_id1":{"label":"Option One",' .
- '"url":"http:\\\/\\\/localhost\\\/index\.php\\\/(?:key\\\/([\w\d]+)\\\/)?",' .
- '"complete":"Test","id":"option_id1"}#';
- $this->assertRegExp($expectedItemFirst, $javascript);
-
- $expectedItemSecond = '#"option_id2":{"label":"Option Two",' .
- '"url":"http:\\\/\\\/localhost\\\/index\.php\\\/(?:key\\\/([\w\d]+)\\\/)?",' .
- '"confirm":"Are you sure\?","id":"option_id2"}#';
- $this->assertRegExp($expectedItemSecond, $javascript);
- }
-
- public function testGetJavaScriptWithAddedItem()
- {
- $this->loadLayout();
-
- $input = [
- 'id' => 'option_id3',
- 'label' => 'Option Three',
- 'url' => '*/*/option3',
- 'block_name' => 'admin.test.grid.massaction.option3',
- ];
- $expected = '#"option_id3":{"id":"option_id3","label":"Option Three",' .
- '"url":"http:\\\/\\\/localhost\\\/index\.php\\\/(?:key\\\/([\w\d]+)\\\/)?",' .
- '"block_name":"admin.test.grid.massaction.option3"}#';
-
- $this->_block->addItem($input['id'], $input);
- $this->assertRegExp($expected, $this->_block->getJavaScript());
- }
-
/**
* @param string $mageMode
* @param int $expectedCount
@@ -213,21 +178,4 @@ public function getItemsDataProvider()
]
];
}
-
- public function testGridContainsMassactionColumn()
- {
- $this->loadLayout();
- $this->_layout->getBlock('admin.test.grid')->toHtml();
-
- $gridMassactionColumn = $this->_layout->getBlock('admin.test.grid')
- ->getColumnSet()
- ->getChildBlock('massaction');
-
- $this->assertNotNull($gridMassactionColumn, 'Massaction column does not exist in the grid column set');
- $this->assertInstanceOf(
- \Magento\Backend\Block\Widget\Grid\Column::class,
- $gridMassactionColumn,
- 'Massaction column is not an instance of \Magento\Backend\Block\Widget\Column'
- );
- }
}
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..89f1e5e5d53d6 100644
--- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php
+++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php
@@ -21,6 +21,8 @@ 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);
diff --git a/dev/tests/integration/testsuite/Magento/Braintree/Controller/Paypal/ReviewTest.php b/dev/tests/integration/testsuite/Magento/Braintree/Controller/Paypal/ReviewTest.php
new file mode 100644
index 0000000000000..fc79048f15f45
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Braintree/Controller/Paypal/ReviewTest.php
@@ -0,0 +1,43 @@
+controller = $this->_objectManager->create(Review::class);
+ }
+
+ /**
+ * Test controller implements correct interfaces
+ *
+ */
+ public function testInterfaceImplementation()
+ {
+ $this->assertInstanceOf(HttpGetActionInterface::class, $this->controller);
+ $this->assertInstanceOf(HttpPostActionInterface::class, $this->controller);
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorWithDimensionTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorWithDimensionTest.php
index b97bd9f822666..e9cb2f2d6c9d4 100644
--- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorWithDimensionTest.php
+++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorWithDimensionTest.php
@@ -13,7 +13,6 @@
* @magentoDbIsolation disabled
* @magentoIndexerDimensionMode catalog_product_price website_and_customer_group
* @group indexer_dimension
- * @magentoAppArea frontend
*/
class FixedBundlePriceCalculatorWithDimensionTest extends BundlePriceAbstract
{
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php
index a2967878402d0..3ec8c806dcbb1 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php
@@ -5,13 +5,49 @@
*/
namespace Magento\Catalog\Controller\Adminhtml\Product\Action;
+use Magento\Catalog\Model\Product\Visibility;
+use Magento\Catalog\Model\ProductRepository;
use Magento\Framework\App\Request\Http as HttpRequest;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\MessageQueue\PublisherConsumerController;
/**
* @magentoAppArea adminhtml
*/
class AttributeTest extends \Magento\TestFramework\TestCase\AbstractBackendController
{
+ /** @var PublisherConsumerController */
+ private $publisherConsumerController;
+ private $consumers = ['product_action_attribute.update'];
+
+ protected function setUp()
+ {
+ $this->publisherConsumerController = Bootstrap::getObjectManager()->create(PublisherConsumerController::class, [
+ 'consumers' => $this->consumers,
+ 'logFilePath' => TESTS_TEMP_DIR . "/MessageQueueTestLog.txt",
+ 'maxMessages' => null,
+ 'appInitParams' => Bootstrap::getInstance()->getAppInitParams()
+ ]);
+
+ try {
+ $this->publisherConsumerController->startConsumers();
+ } catch (\Magento\TestFramework\MessageQueue\EnvironmentPreconditionException $e) {
+ $this->markTestSkipped($e->getMessage());
+ } catch (\Magento\TestFramework\MessageQueue\PreconditionFailedException $e) {
+ $this->fail(
+ $e->getMessage()
+ );
+ }
+
+ parent::setUp();
+ }
+
+ protected function tearDown()
+ {
+ $this->publisherConsumerController->stopConsumers();
+ parent::tearDown();
+ }
+
/**
* @covers \Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute\Save::execute
*
@@ -20,7 +56,7 @@ class AttributeTest extends \Magento\TestFramework\TestCase\AbstractBackendContr
*/
public function testSaveActionRedirectsSuccessfully()
{
- $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+ $objectManager = Bootstrap::getObjectManager();
/** @var $session \Magento\Backend\Model\Session */
$session = $objectManager->get(\Magento\Backend\Model\Session::class);
@@ -59,13 +95,14 @@ public function testSaveActionRedirectsSuccessfully()
*/
public function testSaveActionChangeVisibility($attributes)
{
- $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
- $repository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
- \Magento\Catalog\Model\ProductRepository::class
+ $objectManager = Bootstrap::getObjectManager();
+ /** @var ProductRepository $repository */
+ $repository = Bootstrap::getObjectManager()->create(
+ ProductRepository::class
);
$product = $repository->get('simple');
$product->setOrigData();
- $product->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE);
+ $product->setVisibility(Visibility::VISIBILITY_NOT_VISIBLE);
$product->save();
/** @var $session \Magento\Backend\Model\Session */
@@ -75,15 +112,29 @@ public function testSaveActionChangeVisibility($attributes)
$this->getRequest()->setMethod(HttpRequest::METHOD_POST);
$this->dispatch('backend/catalog/product_action_attribute/save/store/0');
+
/** @var \Magento\Catalog\Model\Category $category */
- $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
+ $categoryFactory = Bootstrap::getObjectManager()->get(
\Magento\Catalog\Model\CategoryFactory::class
);
/** @var \Magento\Catalog\Block\Product\ListProduct $listProduct */
- $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
+ $listProduct = Bootstrap::getObjectManager()->get(
\Magento\Catalog\Block\Product\ListProduct::class
);
+ $this->publisherConsumerController->waitForAsynchronousResult(
+ function () use ($repository) {
+ sleep(3);
+ return $repository->get(
+ 'simple',
+ false,
+ null,
+ true
+ )->getVisibility() != Visibility::VISIBILITY_NOT_VISIBLE;
+ },
+ []
+ );
+
$category = $categoryFactory->create()->load(2);
$layer = $listProduct->getLayer();
$layer->setCurrentCategory($category);
@@ -105,7 +156,7 @@ public function testSaveActionChangeVisibility($attributes)
*/
public function testValidateActionWithMassUpdate($attributes)
{
- $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+ $objectManager = Bootstrap::getObjectManager();
/** @var $session \Magento\Backend\Model\Session */
$session = $objectManager->get(\Magento\Backend\Model\Session::class);
@@ -156,8 +207,8 @@ public function validateActionDataProvider()
public function saveActionVisibilityAttrDataProvider()
{
return [
- ['arguments' => ['visibility' => \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH]],
- ['arguments' => ['visibility' => \Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG]]
+ ['arguments' => ['visibility' => Visibility::VISIBILITY_BOTH]],
+ ['arguments' => ['visibility' => Visibility::VISIBILITY_IN_CATALOG]]
];
}
}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/CategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/CategoryTest.php
index 5721982ab8dc3..d4926e78040d6 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/CategoryTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/CategoryTest.php
@@ -38,8 +38,7 @@ public function testGetProductCollection()
/** @var $collection \Magento\Catalog\Model\ResourceModel\Product\Collection */
$collection = $this->_model->getProductCollection();
$this->assertInstanceOf(\Magento\Catalog\Model\ResourceModel\Product\Collection::class, $collection);
- $ids = $collection->getAllIds();
- $this->assertEquals(2, count($ids));
+ $this->assertEquals(2, $collection->count());
$this->assertSame($collection, $this->_model->getProductCollection());
}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/PriceWithDimensionTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/PriceWithDimensionTest.php
index 280e83a863325..fe39de2729eac 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/PriceWithDimensionTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/PriceWithDimensionTest.php
@@ -3,6 +3,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
declare(strict_types=1);
namespace Magento\Catalog\Model\Product\Type;
@@ -108,7 +109,7 @@ public function testGetFinalPrice()
}
/**
- * Get formated price
+ * Get formatted price
*/
public function testGetFormatedPrice()
{
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/ProductTest.php
index 7954e2c36227f..476f01eb277df 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/ProductTest.php
@@ -12,6 +12,11 @@
class ProductTest extends TestCase
{
+ /**
+ * @var ProductRepositoryInterface
+ */
+ private $productRepository;
+
/**
* @var Product
*/
@@ -29,7 +34,8 @@ protected function setUp()
{
$this->objectManager = Bootstrap::getObjectManager();
- $this->model = $this->objectManager->get(Product::class);
+ $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class);
+ $this->model = $this->objectManager->create(Product::class);
}
/**
@@ -42,11 +48,29 @@ public function testGetAttributeRawValue()
$sku = 'simple';
$attribute = 'name';
- /** @var ProductRepositoryInterface $productRepository */
- $productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
- $product = $productRepository->get($sku);
-
+ $product = $this->productRepository->get($sku);
$actual = $this->model->getAttributeRawValue($product->getId(), $attribute, null);
self::assertEquals($product->getName(), $actual);
}
+
+ /**
+ * @magentoAppArea adminhtml
+ * @magentoDataFixture Magento/Catalog/_files/product_special_price.php
+ * @magentoAppIsolation enabled
+ * @magentoConfigFixture default_store catalog/price/scope 1
+ */
+ public function testUpdateStoreSpecificSpecialPrice()
+ {
+ /** @var \Magento\Catalog\Model\Product $product */
+ $product = $this->productRepository->get('simple', true, 1);
+ $this->assertEquals(5.99, $product->getSpecialPrice());
+
+ $product->setSpecialPrice('');
+ $this->model->save($product);
+ $product = $this->productRepository->get('simple', false, 1, true);
+ $this->assertEmpty($product->getSpecialPrice());
+
+ $product = $this->productRepository->get('simple', false, 0, true);
+ $this->assertEquals(5.99, $product->getSpecialPrice());
+ }
}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_full_option_set.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_full_option_set.php
index bd5dc541a15a5..5facba07d58f1 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_full_option_set.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_full_option_set.php
@@ -187,6 +187,50 @@
'price_type' => 'percent',
'sku' => 'sku2',
'max_characters' => 20,
+ ],
+ [
+ 'title' => 'multiple option',
+ 'type' => 'multiple',
+ 'is_require' => true,
+ 'sort_order' => 7,
+ 'values' => [
+ [
+ 'title' => 'multiple option 1',
+ 'price' => 10,
+ 'price_type' => 'fixed',
+ 'sku' => 'multiple option 1 sku',
+ 'sort_order' => 1,
+ ],
+ [
+ 'title' => 'multiple option 2',
+ 'price' => 20,
+ 'price_type' => 'fixed',
+ 'sku' => 'multiple option 2 sku',
+ 'sort_order' => 2,
+ ],
+ ],
+ ],
+ [
+ 'title' => 'checkbox option',
+ 'type' => 'checkbox',
+ 'is_require' => true,
+ 'sort_order' => 6,
+ 'values' => [
+ [
+ 'title' => 'checkbox option 1',
+ 'price' => 10,
+ 'price_type' => 'fixed',
+ 'sku' => 'checkbox option 1 sku',
+ 'sort_order' => 1,
+ ],
+ [
+ 'title' => 'checkbox option 2',
+ 'price' => 20,
+ 'price_type' => 'fixed',
+ 'sku' => 'checkbox option 2 sku',
+ 'sort_order' => 2,
+ ],
+ ],
]
];
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/text_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_attribute_rollback.php
similarity index 84%
rename from dev/tests/integration/testsuite/Magento/Catalog/_files/text_attribute_rollback.php
rename to dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_attribute_rollback.php
index cbc0476efd1b5..a9ab0e11312b2 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/text_attribute_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_attribute_rollback.php
@@ -3,13 +3,15 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
/* Delete attribute with text_attribute code */
-$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class);
$registry->unregister('isSecureArea');
$registry->register('isSecureArea', true);
+
/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */
$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
- 'Magento\Catalog\Model\ResourceModel\Eav\Attribute'
+ \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class
);
$attribute->load('text_attribute', 'attribute_code');
$attribute->delete();
diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_rollback.php
index 168073bc6ab74..c57c7c3fd6a92 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_rollback.php
@@ -5,10 +5,10 @@
*/
/** Delete all products */
-require dirname(dirname(__DIR__)) . '/Catalog/_files/products_with_multiselect_attribute_rollback.php';
+include dirname(dirname(__DIR__)) . '/Catalog/_files/products_with_multiselect_attribute_rollback.php';
/** Delete text attribute */
-require dirname(dirname(__DIR__)) . '/Catalog/_files/text_attribute_rollback.php';
+include dirname(dirname(__DIR__)) . '/Catalog/_files/product_text_attribute_rollback.php';
-require dirname(dirname(__DIR__)) . '/Store/_files/second_store_rollback.php';
+include dirname(dirname(__DIR__)) . '/Store/_files/second_store_rollback.php';
-require dirname(dirname(__DIR__)) . '/Catalog/_files/category_rollback.php';
+include dirname(dirname(__DIR__)) . '/Catalog/_files/category_rollback.php';
diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_special_chars_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_special_chars_rollback.php
index 168073bc6ab74..c57c7c3fd6a92 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_special_chars_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_special_chars_rollback.php
@@ -5,10 +5,10 @@
*/
/** Delete all products */
-require dirname(dirname(__DIR__)) . '/Catalog/_files/products_with_multiselect_attribute_rollback.php';
+include dirname(dirname(__DIR__)) . '/Catalog/_files/products_with_multiselect_attribute_rollback.php';
/** Delete text attribute */
-require dirname(dirname(__DIR__)) . '/Catalog/_files/text_attribute_rollback.php';
+include dirname(dirname(__DIR__)) . '/Catalog/_files/product_text_attribute_rollback.php';
-require dirname(dirname(__DIR__)) . '/Store/_files/second_store_rollback.php';
+include dirname(dirname(__DIR__)) . '/Store/_files/second_store_rollback.php';
-require dirname(dirname(__DIR__)) . '/Catalog/_files/category_rollback.php';
+include dirname(dirname(__DIR__)) . '/Catalog/_files/category_rollback.php';
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Plugin/Model/Quote/ResetQuoteAddressesTest.php b/dev/tests/integration/testsuite/Magento/Checkout/Plugin/Model/Quote/ResetQuoteAddressesTest.php
index 994076badddae..60ccdb88676aa 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/Plugin/Model/Quote/ResetQuoteAddressesTest.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/Plugin/Model/Quote/ResetQuoteAddressesTest.php
@@ -22,6 +22,7 @@ class ResetQuoteAddressesTest extends \PHPUnit\Framework\TestCase
/**
* @magentoDataFixture Magento/Checkout/_files/quote_with_virtual_product_and_address.php
*
+ * @magentoAppArea frontend
* @return void
*/
public function testAfterRemoveItem(): void
diff --git a/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php b/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php
index 73f1dd9e7b711..e59672f1b5e1a 100644
--- a/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php
+++ b/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php
@@ -7,6 +7,8 @@
namespace Magento\Config\Console\Command;
use Magento\Config\Model\Config\Backend\Admin\Custom;
+use Magento\Config\Model\Config\Structure\Converter;
+use Magento\Config\Model\Config\Structure\Data as StructureData;
use Magento\Directory\Model\Currency;
use Magento\Framework\App\Config\ConfigPathResolver;
use Magento\Framework\App\Config\ScopeConfigInterface;
@@ -91,6 +93,8 @@ protected function setUp()
{
Bootstrap::getInstance()->reinitialize();
$this->objectManager = Bootstrap::getObjectManager();
+ $this->extendSystemStructure();
+
$this->scopeConfig = $this->objectManager->get(ScopeConfigInterface::class);
$this->reader = $this->objectManager->get(FileReader::class);
$this->filesystem = $this->objectManager->get(Filesystem::class);
@@ -123,6 +127,21 @@ protected function tearDown()
$this->appConfig->reinit();
}
+ /**
+ * Add test system structure to main system structure
+ *
+ * @return void
+ */
+ private function extendSystemStructure()
+ {
+ $document = new \DOMDocument();
+ $document->load(__DIR__ . '/../../_files/system.xml');
+ $converter = $this->objectManager->get(Converter::class);
+ $systemConfig = $converter->convert($document);
+ $structureData = $this->objectManager->get(StructureData::class);
+ $structureData->merge($systemConfig);
+ }
+
/**
* @return array
*/
@@ -191,6 +210,8 @@ public function runLockDataProvider()
['general/region/display_all', '1'],
['general/region/state_required', 'BR,FR', ScopeInterface::SCOPE_WEBSITE, 'base'],
['admin/security/use_form_key', '0'],
+ ['general/group/subgroup/field', 'default_value'],
+ ['general/group/subgroup/field', 'website_value', ScopeInterface::SCOPE_WEBSITE, 'base'],
];
}
diff --git a/dev/tests/integration/testsuite/Magento/Config/_files/system.xml b/dev/tests/integration/testsuite/Magento/Config/_files/system.xml
new file mode 100644
index 0000000000000..f0063a3c0bf7f
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Config/_files/system.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProductsTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProductsTest.php
index 234f0aae6a3ea..676433c0a1e6c 100644
--- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProductsTest.php
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProductsTest.php
@@ -5,7 +5,19 @@
*/
namespace Magento\ConfigurableProduct\Ui\DataProvider\Product\Form\Modifier\Data;
-class AssociatedProductsTest extends \PHPUnit\Framework\TestCase
+use Magento\Framework\View\Element\UiComponentFactory;
+use Magento\Ui\Component\Filters\FilterModifier;
+use Magento\Framework\View\Element\UiComponent\ContextInterface;
+use Magento\ConfigurableProduct\Ui\DataProvider\Product\Form\Modifier\ConfigurablePanel;
+use Magento\Framework\App\RequestInterface;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * AssociatedProductsTest
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class AssociatedProductsTest extends TestCase
{
/**
* @var \Magento\Framework\ObjectManagerInterface $objectManager
@@ -17,7 +29,10 @@ class AssociatedProductsTest extends \PHPUnit\Framework\TestCase
*/
private $registry;
- public function setUp()
+ /**
+ * @inheritdoc
+ */
+ public function setUp(): void
{
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
$this->registry = $this->objectManager->get(\Magento\Framework\Registry::class);
@@ -64,6 +79,53 @@ public function testGetProductMatrix($interfaceLocale)
}
}
+ /**
+ * Tests configurable product won't appear in product listing.
+ *
+ * Tests configurable product won't appear in configurable associated product listing if its options attribute
+ * is not filterable in grid.
+ *
+ * @return void
+ * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+ * @magentoAppArea adminhtml
+ */
+ public function testAddManuallyConfigurationsWithNotFilterableInGridAttribute(): void
+ {
+ /** @var RequestInterface $request */
+ $request = $this->objectManager->get(RequestInterface::class);
+ $request->setParams([
+ FilterModifier::FILTER_MODIFIER => [
+ 'test_configurable' => [
+ 'condition_type' => 'notnull',
+ ],
+ ],
+ 'attributes_codes' => [
+ 'test_configurable'
+ ],
+ ]);
+ $context = $this->objectManager->create(ContextInterface::class, ['request' => $request]);
+ /** @var UiComponentFactory $uiComponentFactory */
+ $uiComponentFactory = $this->objectManager->get(UiComponentFactory::class);
+ $uiComponent = $uiComponentFactory->create(
+ ConfigurablePanel::ASSOCIATED_PRODUCT_LISTING,
+ null,
+ ['context' => $context]
+ );
+
+ foreach ($uiComponent->getChildComponents() as $childUiComponent) {
+ $childUiComponent->prepare();
+ }
+
+ $dataSource = $uiComponent->getDataSourceData();
+ $skus = array_column($dataSource['data']['items'], 'sku');
+
+ $this->assertNotContains(
+ 'configurable',
+ $skus,
+ 'Only products with specified attribute should be in product list'
+ );
+ }
+
/**
* @return array
*/
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
index ea7a7710acbc3..10b632c002475 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
@@ -751,6 +751,21 @@ public function loginPostRedirectDataProvider()
];
}
+ /**
+ * @magentoDataFixture Magento/Customer/_files/customer.php
+ * @magentoDataFixture Magento/Customer/_files/customer_address.php
+ * @magentoAppArea frontend
+ */
+ public function testCheckVisitorModel()
+ {
+ /** @var \Magento\Customer\Model\Visitor $visitor */
+ $visitor = $this->_objectManager->get(\Magento\Customer\Model\Visitor::class);
+ $this->login(1);
+ $this->assertNull($visitor->getId());
+ $this->dispatch('customer/account/index');
+ $this->assertNotNull($visitor->getId());
+ }
+
/**
* @param string $email
* @return void
diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/AdapterTest.php
index 978815f665341..a52c5bb9e21b7 100644
--- a/dev/tests/integration/testsuite/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/AdapterTest.php
+++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/AdapterTest.php
@@ -43,7 +43,7 @@ protected function setUp()
$contentManager = $this->getMockBuilder(\Magento\Elasticsearch\SearchAdapter\ConnectionManager::class)
->disableOriginalConstructor()
->getMock();
- $this->clientMock = $this->getMockBuilder(\Magento\Elasticsearch\Model\Client\Elasticsearch::class)
+ $this->clientMock = $this->getMockBuilder(\Magento\Elasticsearch6\Model\Client\Elasticsearch::class)
->disableOriginalConstructor()
->getMock();
$contentManager
@@ -78,7 +78,7 @@ protected function setUp()
/**
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
* @return void
*/
diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Client/ElasticsearchTest.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Client/ElasticsearchTest.php
index 61add5f7d0ea7..3eea2497daa1f 100644
--- a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Client/ElasticsearchTest.php
+++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Client/ElasticsearchTest.php
@@ -10,7 +10,7 @@
use Magento\TestFramework\Helper\Bootstrap;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Elasticsearch\SearchAdapter\ConnectionManager;
-use Magento\Elasticsearch\Model\Client\Elasticsearch as ElasticsearchClient;
+use Magento\Elasticsearch6\Model\Client\Elasticsearch as ElasticsearchClient;
use Magento\Elasticsearch\Model\Config;
use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver;
@@ -95,7 +95,7 @@ private function search($text)
}
/**
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix composite_product_search
*/
public function testSearchConfigurableProductBySimpleProductName()
@@ -104,7 +104,7 @@ public function testSearchConfigurableProductBySimpleProductName()
}
/**
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix composite_product_search
*/
public function testSearchConfigurableProductBySimpleProductAttributeMultiselect()
@@ -113,7 +113,7 @@ public function testSearchConfigurableProductBySimpleProductAttributeMultiselect
}
/**
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix composite_product_search
*/
public function testSearchConfigurableProductBySimpleProductAttributeSelect()
@@ -122,7 +122,7 @@ public function testSearchConfigurableProductBySimpleProductAttributeSelect()
}
/**
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix composite_product_search
*/
public function testSearchConfigurableProductBySimpleProductAttributeShortDescription()
diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php
index 014aaf7679bc9..77533e83b719c 100755
--- a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php
+++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php
@@ -13,7 +13,7 @@
use Magento\TestFramework\Helper\Bootstrap;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Elasticsearch\SearchAdapter\ConnectionManager;
-use Magento\Elasticsearch\Model\Client\Elasticsearch as ElasticsearchClient;
+use Magento\Elasticsearch6\Model\Client\Elasticsearch as ElasticsearchClient;
use Magento\Elasticsearch\Model\Config;
use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver;
use Magento\Indexer\Model\Indexer;
@@ -87,7 +87,7 @@ protected function setUp()
}
/**
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest
* @return void
*/
@@ -106,7 +106,7 @@ public function testReindexAll(): void
/**
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest
* @return void
*/
@@ -131,7 +131,7 @@ public function testReindexRowAfterEdit(): void
}
/**
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest
* @return void
*/
@@ -170,7 +170,7 @@ public function testReindexRowAfterMassAction(): void
}
/**
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest
* @magentoAppArea adminhtml
* @return void
@@ -192,7 +192,7 @@ public function testReindexRowAfterDelete(): void
/**
* @magentoDbIsolation enabled
* @magentoAppArea adminhtml
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest
* @magentoDataFixture Magento/Elasticsearch/_files/configurable_products.php
* @return void
diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/ReindexAllTest.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/ReindexAllTest.php
index d40ce9e8a0706..7d4aa8e005e4e 100644
--- a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/ReindexAllTest.php
+++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/ReindexAllTest.php
@@ -68,7 +68,7 @@ protected function setUp()
/**
* Test search of all products after full reindex
*
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest_configurable
* @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_products.php
*/
@@ -82,7 +82,7 @@ public function testSearchAll()
/**
* Test search of specific product after full reindex
*
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest_configurable
* @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_products.php
*/
diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/SearchAdapter/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/SearchAdapter/AdapterTest.php
index dc288a18fadb7..a3da32e0d6c40 100644
--- a/dev/tests/integration/testsuite/Magento/Elasticsearch/SearchAdapter/AdapterTest.php
+++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/SearchAdapter/AdapterTest.php
@@ -5,8 +5,6 @@
*/
namespace Magento\Elasticsearch\SearchAdapter;
-use Magento\Elasticsearch\Model\Config;
-
/**
* Class AdapterTest
*
@@ -26,7 +24,7 @@ class AdapterTest extends \Magento\Framework\Search\Adapter\Mysql\AdapterTest
/**
* @var string
*/
- protected $searchEngine = Config::ENGINE_NAME;
+ protected $searchEngine = 'elasticsearch6';
/**
* Get request config path
@@ -43,12 +41,12 @@ protected function getRequestConfigPath()
*/
protected function createAdapter()
{
- return $this->objectManager->create(\Magento\Elasticsearch\SearchAdapter\Adapter::class);
+ return $this->objectManager->create(\Magento\Elasticsearch\Elasticsearch5\SearchAdapter\Adapter::class);
}
/**
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testMatchQuery()
@@ -58,7 +56,7 @@ public function testMatchQuery()
/**
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testMatchOrderedQuery()
@@ -70,7 +68,7 @@ public function testMatchOrderedQuery()
/**
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testAggregationsQuery()
@@ -80,7 +78,7 @@ public function testAggregationsQuery()
/**
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testMatchQueryFilters()
@@ -92,7 +90,7 @@ public function testMatchQueryFilters()
* Range filter test with all fields filled
*
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testRangeFilterWithAllFields()
@@ -104,7 +102,7 @@ public function testRangeFilterWithAllFields()
* Range filter test with all fields filled
*
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testRangeFilterWithoutFromField()
@@ -116,7 +114,7 @@ public function testRangeFilterWithoutFromField()
* Range filter test with all fields filled
*
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testRangeFilterWithoutToField()
@@ -128,7 +126,7 @@ public function testRangeFilterWithoutToField()
* Term filter test
*
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testTermFilter()
@@ -140,7 +138,7 @@ public function testTermFilter()
* Term filter test
*
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testTermFilterArray()
@@ -152,7 +150,7 @@ public function testTermFilterArray()
* Term filter test
*
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testWildcardFilter()
@@ -164,7 +162,7 @@ public function testWildcardFilter()
* Request limits test
*
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testSearchLimit()
@@ -176,7 +174,7 @@ public function testSearchLimit()
* Bool filter test
*
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testBoolFilter()
@@ -188,7 +186,7 @@ public function testBoolFilter()
* Test bool filter with nested negative bool filter
*
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testBoolFilterWithNestedNegativeBoolFilter()
@@ -200,7 +198,7 @@ public function testBoolFilterWithNestedNegativeBoolFilter()
* Test range inside nested negative bool filter
*
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testBoolFilterWithNestedRangeInNegativeBoolFilter()
@@ -213,7 +211,7 @@ public function testBoolFilterWithNestedRangeInNegativeBoolFilter()
*
* @dataProvider elasticSearchAdvancedSearchDataProvider
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
* @param string $nameQuery
* @param string $descriptionQuery
@@ -259,7 +257,7 @@ public function elasticSearchAdvancedSearchDataProvider()
/**
* @magentoAppIsolation enabled
* @magentoDataFixture Magento/Framework/Search/_files/filterable_attribute.php
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testCustomFilterableAttribute()
@@ -274,7 +272,7 @@ public function testCustomFilterableAttribute()
*
* @magentoAppIsolation enabled
* @magentoDataFixture Magento/Framework/Search/_files/filterable_attributes.php
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
* @dataProvider filterByAttributeValuesDataProvider
* @param string $requestName
@@ -294,7 +292,7 @@ public function testFilterByAttributeValues($requestName, $additionalData)
* @param $rangeFilter
* @param $expectedRecordsCount
* @magentoDataFixture Magento/Framework/Search/_files/date_attribute.php
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
* @magentoAppIsolation enabled
* @dataProvider dateDataProvider
@@ -309,7 +307,7 @@ public function testAdvancedSearchDateField($rangeFilter, $expectedRecordsCount)
/**
* @magentoDataFixture Magento/Framework/Search/_files/product_configurable.php
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testAdvancedSearchCompositeProductWithOutOfStockOption()
@@ -320,7 +318,7 @@ public function testAdvancedSearchCompositeProductWithOutOfStockOption()
/**
* @magentoDataFixture Magento/Framework/Search/_files/product_configurable_with_disabled_child.php
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testAdvancedSearchCompositeProductWithDisabledChild()
@@ -333,7 +331,7 @@ public function testAdvancedSearchCompositeProductWithDisabledChild()
/**
* @magentoDataFixture Magento/Framework/Search/_files/search_weight_products.php
* @magentoAppIsolation enabled
- * @magentoConfigFixture default/catalog/search/engine elasticsearch
+ * @magentoConfigFixture default/catalog/search/engine elasticsearch6
* @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix adaptertest
*/
public function testSearchQueryBoost()
@@ -369,4 +367,18 @@ public function dateDataProvider()
[['from' => '2000-02-01T00:00:00Z', 'to' => ''], 0],
];
}
+
+ public function filterByAttributeValuesDataProvider()
+ {
+ $variations = parent::filterByAttributeValuesDataProvider();
+
+ $variations['quick search by date'] = [
+ 'quick_search_container',
+ [
+ 'search_term' => '2000-10-30',
+ ],
+ ];
+
+ return $variations;
+ }
}
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Lock/Backend/FileLockTest.php b/dev/tests/integration/testsuite/Magento/Framework/Lock/Backend/FileLockTest.php
new file mode 100644
index 0000000000000..e64b3c505acf1
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Framework/Lock/Backend/FileLockTest.php
@@ -0,0 +1,55 @@
+objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+ $this->model = $this->objectManager->create(
+ \Magento\Framework\Lock\Backend\FileLock::class,
+ ['path' => '/tmp']
+ );
+ }
+
+ public function testLockAndUnlock()
+ {
+ $name = 'test_lock';
+
+ $this->assertFalse($this->model->isLocked($name));
+
+ $this->assertTrue($this->model->lock($name));
+ $this->assertTrue($this->model->isLocked($name));
+ $this->assertFalse($this->model->lock($name, 2));
+
+ $this->assertTrue($this->model->unlock($name));
+ $this->assertFalse($this->model->isLocked($name));
+ }
+
+ public function testUnlockWithoutExistingLock()
+ {
+ $name = 'test_lock';
+
+ $this->assertFalse($this->model->isLocked($name));
+ $this->assertFalse($this->model->unlock($name));
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Lock/Backend/ZookeeperTest.php b/dev/tests/integration/testsuite/Magento/Framework/Lock/Backend/ZookeeperTest.php
new file mode 100644
index 0000000000000..8d0caad5d55e4
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Framework/Lock/Backend/ZookeeperTest.php
@@ -0,0 +1,90 @@
+markTestSkipped('php extension Zookeeper is not installed.');
+ }
+
+ $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+ $this->configReader = $this->objectManager->get(FileReader::class);
+ $this->lockBackendFactory = $this->objectManager->create(LockBackendFactory::class);
+ $this->arrayManager = $this->objectManager->create(ArrayManager::class);
+ $config = $this->configReader->load(ConfigFilePool::APP_ENV);
+
+ if ($this->arrayManager->get('lock/provider', $config) !== 'zookeeper') {
+ $this->markTestSkipped('Zookeeper is not configured during installation.');
+ }
+
+ $this->model = $this->lockBackendFactory->create();
+ $this->assertInstanceOf(ZookeeperLock::class, $this->model);
+ }
+
+ public function testLockAndUnlock()
+ {
+ $name = 'test_lock';
+
+ $this->assertFalse($this->model->isLocked($name));
+
+ $this->assertTrue($this->model->lock($name));
+ $this->assertTrue($this->model->isLocked($name));
+ $this->assertFalse($this->model->lock($name, 2));
+
+ $this->assertTrue($this->model->unlock($name));
+ $this->assertFalse($this->model->isLocked($name));
+ }
+
+ public function testUnlockWithoutExistingLock()
+ {
+ $name = 'test_lock';
+
+ $this->assertFalse($this->model->isLocked($name));
+ $this->assertFalse($this->model->unlock($name));
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attributes.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attributes.php
index b09af48b5f943..f4f3337a253c0 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attributes.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attributes.php
@@ -20,6 +20,10 @@
CategorySetup::class,
['resourceName' => 'catalog_setup']
);
+$productEntityTypeId = $installer->getEntityTypeId(
+ \Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE
+);
+
$selectOptions = [];
$selectAttributes = [];
foreach (range(1, 2) as $index) {
@@ -30,7 +34,7 @@
$selectAttribute->setData(
[
'attribute_code' => 'select_attribute_' . $index,
- 'entity_type_id' => $installer->getEntityTypeId('catalog_product'),
+ 'entity_type_id' => $productEntityTypeId,
'is_global' => 1,
'is_user_defined' => 1,
'frontend_input' => 'select',
@@ -56,7 +60,8 @@
);
$selectAttribute->save();
/* Assign attribute to attribute set */
- $installer->addAttributeToGroup('catalog_product', 'Default', 'General', $selectAttribute->getId());
+ $installer->addAttributeToGroup($productEntityTypeId, 'Default', 'General', $selectAttribute->getId());
+
/** @var $selectOptions Collection */
$selectOption = Bootstrap::getObjectManager()->create(
Collection::class
@@ -65,6 +70,26 @@
$selectAttributes[$index] = $selectAttribute;
$selectOptions[$index] = $selectOption;
}
+
+$dateAttribute = Bootstrap::getObjectManager()->create(Attribute::class);
+$dateAttribute->setData(
+ [
+ 'attribute_code' => 'date_attribute',
+ 'entity_type_id' => $productEntityTypeId,
+ 'is_global' => 1,
+ 'is_filterable' => 1,
+ 'backend_type' => 'datetime',
+ 'frontend_input' => 'date',
+ 'frontend_label' => 'Test Date',
+ 'is_searchable' => 1,
+ 'is_filterable_in_search' => 1,
+ ]
+);
+$dateAttribute->save();
+/* Assign attribute to attribute set */
+$installer->addAttributeToGroup($productEntityTypeId, 'Default', 'General', $dateAttribute->getId());
+
+$productAttributeSetId = $installer->getAttributeSetId($productEntityTypeId, 'Default');
/* Create simple products per each first attribute option */
foreach ($selectOptions[1] as $option) {
/** @var $product Product */
@@ -74,7 +99,7 @@
$product->setTypeId(
Type::TYPE_SIMPLE
)->setAttributeSetId(
- $installer->getAttributeSetId('catalog_product', 'Default')
+ $productAttributeSetId
)->setWebsiteIds(
[1]
)->setName(
@@ -92,6 +117,7 @@
)->setStockData(
['use_config_manage_stock' => 1, 'qty' => 5, 'is_in_stock' => 1]
)->save();
+
Bootstrap::getObjectManager()->get(
Action::class
)->updateAttributes(
@@ -99,6 +125,7 @@
[
$selectAttributes[1]->getAttributeCode() => $option->getId(),
$selectAttributes[2]->getAttributeCode() => $selectOptions[2]->getLastItem()->getId(),
+ $dateAttribute->getAttributeCode() => '10/30/2000',
],
$product->getStoreId()
);
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attributes_rollback.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attributes_rollback.php
index 18a5372d06d98..fd413726b2637 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attributes_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attributes_rollback.php
@@ -13,6 +13,7 @@
$registry = Bootstrap::getObjectManager()->get(Registry::class);
$registry->unregister('isSecureArea');
$registry->register('isSecureArea', true);
+
/** @var $productCollection \Magento\Catalog\Model\ResourceModel\Product\Collection */
$productCollection = Bootstrap::getObjectManager()
->create(Product::class)
@@ -20,17 +21,26 @@
foreach ($productCollection as $product) {
$product->delete();
}
+
/** @var $attribute Attribute */
$attribute = Bootstrap::getObjectManager()->create(
Attribute::class
);
/** @var $installer CategorySetup */
$installer = Bootstrap::getObjectManager()->create(CategorySetup::class);
+$productEntityTypeId = $installer->getEntityTypeId(
+ \Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE
+);
foreach (range(1, 2) as $index) {
- $attribute->loadByCode($installer->getEntityTypeId('catalog_product'), 'select_attribute_' . $index);
+ $attribute->loadByCode($productEntityTypeId, 'select_attribute_' . $index);
if ($attribute->getId()) {
$attribute->delete();
}
}
+$attribute->loadByCode($productEntityTypeId, 'date_attribute');
+if ($attribute->getId()) {
+ $attribute->delete();
+}
+
$registry->unregister('isSecureArea');
$registry->register('isSecureArea', false);
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_request_merged.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_request_merged.php
index 8586f47a0f7fa..0aaa3f4e15bda 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_request_merged.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_request_merged.php
@@ -35,6 +35,7 @@
'match_query' => [
'value' => '$match_term_override$',
'name' => 'match_query',
+ 'boost' => '1',
'match' => [
0 => [
'field' => 'match_field',
@@ -50,6 +51,7 @@
],
'must_query' => [
'name' => 'must_query',
+ 'boost' => '1',
'filterReference' => [
0 => [
'clause' => 'must',
@@ -60,6 +62,7 @@
],
'should_query' => [
'name' => 'should_query',
+ 'boost' => '1',
'filterReference' => [
0 => [
'clause' => 'should',
@@ -70,6 +73,7 @@
],
'not_query' => [
'name' => 'not_query',
+ 'boost' => '1',
'filterReference' => [
0 => [
'clause' => 'not',
@@ -80,6 +84,7 @@
],
'match_query_2' => [
'value' => '$match_term_override$',
+ 'boost' => '1',
'name' => 'match_query_2',
'match' => [
0 => [
@@ -163,6 +168,7 @@
'queries' => [
'filter_query' => [
'name' => 'filter_query',
+ 'boost' => '1',
'filterReference' => [
0 =>
[
@@ -230,6 +236,7 @@
'new_match_query' => [
'value' => '$match_term$',
'name' => 'new_match_query',
+ 'boost' => '1',
'match' => [
0 =>
[
diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Block/Adminhtml/Subscriber/GridTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Block/Adminhtml/Subscriber/GridTest.php
new file mode 100644
index 0000000000000..48d3356525f49
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Newsletter/Block/Adminhtml/Subscriber/GridTest.php
@@ -0,0 +1,105 @@
+objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+ $this->layout = $this->objectManager->create(\Magento\Framework\View\LayoutInterface::class);
+ $this->layout->getUpdate()->load('newsletter_subscriber_grid');
+ $this->layout->generateXml();
+ $this->layout->generateElements();
+ }
+
+ /**
+ * Check if mass action block exists.
+ */
+ public function testMassActionBlockExists()
+ {
+ $this->assertNotFalse(
+ $this->getMassActionBlock(),
+ 'Mass action block does not exist in the grid, or it name was changed.'
+ );
+ }
+
+ /**
+ * Check if mass action id field is correct.
+ */
+ public function testMassActionFieldIdIsCorrect()
+ {
+ $this->assertEquals(
+ 'subscriber_id',
+ $this->getMassActionBlock()->getMassactionIdField(),
+ 'Mass action id field is incorrect.'
+ );
+ }
+
+ /**
+ * Check if function returns correct result.
+ *
+ * @magentoDataFixture Magento/Newsletter/_files/subscribers.php
+ */
+ public function testMassActionBlockContainsCorrectIdList()
+ {
+ $this->assertEquals(
+ implode(',', $this->getAllSubscriberIdList()),
+ $this->getMassActionBlock()->getGridIdsJson(),
+ 'Function returns incorrect result.'
+ );
+ }
+
+ /**
+ * Retrieve mass action block.
+ *
+ * @return bool|\Magento\Backend\Block\Widget\Grid\Massaction
+ */
+ private function getMassActionBlock()
+ {
+ return $this->layout->getBlock('adminhtml.newslettrer.subscriber.grid.massaction');
+ }
+
+ /**
+ * Retrieve list of id of all subscribers.
+ *
+ * @return array
+ */
+ private function getAllSubscriberIdList()
+ {
+ /** @var \Magento\Framework\App\ResourceConnection $resourceConnection */
+ $resourceConnection = $this->objectManager->get(\Magento\Framework\App\ResourceConnection::class);
+ $select = $resourceConnection->getConnection()
+ ->select()
+ ->from($resourceConnection->getTableName('newsletter_subscriber'))
+ ->columns(['subscriber_id' => 'subscriber_id']);
+
+ return $resourceConnection->getConnection()->fetchCol($select);
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/enable_offline_shipping_methods.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/enable_offline_shipping_methods.php
new file mode 100644
index 0000000000000..08694bf8c7d0b
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/enable_offline_shipping_methods.php
@@ -0,0 +1,22 @@
+get(WriterInterface::class);
+
+$configWriter->save('carriers/flatrate/active', 1);
+$configWriter->save('carriers/tablerate/active', 1);
+$configWriter->save('carriers/freeshipping/active', 1);
+
+$scopeConfig = $objectManager->get(ScopeConfigInterface::class);
+$scopeConfig->clean();
diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/enable_offline_shipping_methods_rollback.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/enable_offline_shipping_methods_rollback.php
new file mode 100644
index 0000000000000..31a16f42adfce
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/enable_offline_shipping_methods_rollback.php
@@ -0,0 +1,18 @@
+create(WriterInterface::class);
+
+$configWriter->delete('carriers/flatrate/active');
+$configWriter->delete('carriers/tablerate/active');
+$configWriter->delete('carriers/freeshipping/active');
diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight.php
new file mode 100644
index 0000000000000..40e01a81ac807
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight.php
@@ -0,0 +1,29 @@
+get(\Magento\Framework\App\ResourceConnection::class);
+$connection = $resource->getConnection();
+$resourceModel = $objectManager->create(\Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate::class);
+$entityTable = $resourceModel->getTable('shipping_tablerate');
+$data =
+ [
+ 'website_id' => 1,
+ 'dest_country_id' => 'US',
+ 'dest_region_id' => 0,
+ 'dest_zip' => '*',
+ 'condition_name' => 'package_weight',
+ 'condition_value' => 0,
+ 'price' => 10,
+ 'cost' => 0
+ ];
+$connection->query(
+ "INSERT INTO {$entityTable} (`website_id`, `dest_country_id`, `dest_region_id`, `dest_zip`, `condition_name`,"
+ . "`condition_value`, `price`, `cost`) VALUES (:website_id, :dest_country_id, :dest_region_id, :dest_zip,"
+ . " :condition_name, :condition_value, :price, :cost);",
+ $data
+);
diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight_rollback.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight_rollback.php
new file mode 100644
index 0000000000000..cb6e9353b8972
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight_rollback.php
@@ -0,0 +1,8 @@
+get(\Magento\Payment\Api\PaymentMethodListInterface::class);
+$rollbackConfigKey = 'test/payment/disabled_payment_methods';
+$configData = [];
+$disabledPaymentMethods = [];
+
+// Get all active Payment Methods
+foreach ($paymentMethodList->getActiveList(Store::DEFAULT_STORE_ID) as $paymentMethod) {
+ $configData['payment/' . $paymentMethod->getCode() . '/active'] = 0;
+ $disabledPaymentMethods[] = $paymentMethod->getCode();
+}
+// Remember all manually disabled Payment Methods for rollback
+$configData[$rollbackConfigKey] = implode(',', $disabledPaymentMethods);
+
+/** @var Config $defConfig */
+$defConfig = $objectManager->create(Config::class);
+$defConfig->setScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT);
+
+foreach ($configData as $key => $value) {
+ $defConfig->setDataByPath($key, $value);
+ $defConfig->save();
+}
diff --git a/dev/tests/integration/testsuite/Magento/Payment/_files/disable_all_active_payment_methods_rollback.php b/dev/tests/integration/testsuite/Magento/Payment/_files/disable_all_active_payment_methods_rollback.php
new file mode 100644
index 0000000000000..4a56888058e4d
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Payment/_files/disable_all_active_payment_methods_rollback.php
@@ -0,0 +1,33 @@
+create(WriterInterface::class);
+$rollbackConfigValue = $objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)
+ ->getStore(\Magento\Store\Model\Store::DEFAULT_STORE_ID)
+ ->getConfig($rollbackConfigKey);
+
+$disabledPaymentMethods = [];
+if (!empty($rollbackConfigValue)) {
+ $disabledPaymentMethods = explode(',', $rollbackConfigValue);
+}
+
+if (count($disabledPaymentMethods)) {
+ foreach ($disabledPaymentMethods as $keyToRemove) {
+ $configWriter->delete(sprintf('payment/%s/active', $keyToRemove));
+ }
+}
+$configWriter->delete($rollbackConfigKey);
+
+$scopeConfig = $objectManager->get(ScopeConfigInterface::class);
+$scopeConfig->clean();
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
index cb83fa3abd857..3f7f8719fd587 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
@@ -72,7 +72,7 @@ protected function setUp()
$this->api = $this->getMockBuilder(Nvp::class)
->disableOriginalConstructor()
- ->setMethods(['call', 'getExportedShippingAddress', 'getExportedBillingAddress'])
+ ->setMethods(['call', 'getExportedShippingAddress', 'getExportedBillingAddress', 'getShippingRateCode'])
->getMock();
$this->api->expects($this->any())
@@ -302,6 +302,8 @@ public function testReturnFromPaypal()
public function testReturnFromPaypalButton()
{
$quote = $this->getFixtureQuote();
+ $quote->getShippingAddress()->setShippingMethod('');
+
$this->prepareCheckoutModel($quote);
$quote->getPayment()->setAdditionalInformation(Checkout::PAYMENT_INFO_BUTTON, 1);
@@ -317,6 +319,8 @@ public function testReturnFromPaypalButton()
$this->assertEquals($exportedShippingData['telephone'], $shippingAddress->getTelephone());
$this->assertEquals($exportedShippingData['email'], $shippingAddress->getEmail());
+ $this->assertEquals('flatrate_flatrate', $shippingAddress->getShippingMethod());
+
$this->assertEquals([$exportedShippingData['street']], $billingAddress->getStreet());
$this->assertEquals($exportedShippingData['firstname'], $billingAddress->getFirstname());
$this->assertEquals($exportedShippingData['city'], $billingAddress->getCity());
@@ -551,6 +555,9 @@ private function prepareCheckoutModel(Quote $quote, $prefix = '')
$this->api->method('getExportedShippingAddress')
->willReturn($exportedShippingAddress);
+ $this->api->method('getShippingRateCode')
+ ->willReturn('flatrate_flatrate Flat Rate - Fixed');
+
$this->paypalInfo->method('importToPayment')
->with($this->api, $quote->getPayment());
}
@@ -573,7 +580,7 @@ private function getExportedData(): array
'city' => 'Denver',
'street' => '66 Pearl St',
'postcode' => '80203',
- 'telephone' => '555-555-555'
+ 'telephone' => '555-555-555',
],
'billing' => [
'email' => 'customer@example.com',
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/FormTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/FormTest.php
new file mode 100644
index 0000000000000..1067a474e19aa
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/FormTest.php
@@ -0,0 +1,109 @@
+prepareRequestData();
+ $this->dispatch('sales/guest/view/');
+ $content = $this->getResponse()->getBody();
+ $this->assertContains('Order # 100000001', $content);
+ }
+
+ /**
+ * View order as logged in customer
+ *
+ * @magentoDataFixture Magento/Sales/_files/order.php
+ * @magentoDataFixture Magento/Customer/_files/customer.php
+ */
+ public function testViewOrderAsLoggedIn()
+ {
+ $this->login(1);
+ $this->dispatch('sales/guest/view/');
+ $this->assertRedirect($this->stringContains('sales/order/history/'));
+ }
+
+ /**
+ * Test attempting to open the Returns form as logged in customer
+ *
+ * @magentoDataFixture Magento/Sales/_files/order.php
+ * @magentoDataFixture Magento/Customer/_files/customer.php
+ */
+ public function testAttemptToOpenTheFormAsLoggedIn()
+ {
+ $this->login(1);
+ $this->dispatch('sales/guest/form/');
+ $this->assertRedirect($this->stringContains('customer/account'));
+ }
+
+ /**
+ * Test Return Order for guest with incorrect data
+ */
+ public function testViewOrderAsGuestWithIncorrectData()
+ {
+ $this->prepareRequestData(true);
+ $this->dispatch('sales/guest/view/');
+ $this->assertSessionMessages(
+ $this->equalTo(['You entered incorrect data. Please try again.']),
+ MessageInterface::TYPE_ERROR
+ );
+ }
+
+ /**
+ * Login the user
+ *
+ * @param string $customerId Customer to mark as logged in for the session
+ * @return void
+ */
+ protected function login($customerId)
+ {
+ /** @var Session $session */
+ $session = $this->_objectManager->get(Session::class);
+ $session->loginById($customerId);
+ }
+
+ /**
+ * @param bool $invalidData
+ * @return void
+ */
+ private function prepareRequestData($invalidData = false)
+ {
+ $orderId = 100000001;
+ $email = $invalidData ? 'wrong@example.com' : 'customer@null.com';
+
+ /** @var FormKey $formKey */
+ $formKey = $this->_objectManager->get(FormKey::class);
+ $post = [
+ 'oar_order_id' => $orderId,
+ 'oar_billing_lastname' => 'lastname',
+ 'oar_type' => 'email',
+ 'oar_email' => $email,
+ 'oar_zip' => '',
+ 'form_key' => $formKey->getFormKey(),
+ ];
+
+ $this->getRequest()->setMethod(Request::METHOD_POST);
+ $this->getRequest()->setPostValue($post);
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Service/InvoiceServiceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/InvoiceServiceTest.php
new file mode 100644
index 0000000000000..e35c480e44c66
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/InvoiceServiceTest.php
@@ -0,0 +1,92 @@
+invoiceService = Bootstrap::getObjectManager()->create(InvoiceService::class);
+ }
+
+ /**
+ * @param int $invoiceQty
+ * @magentoDataFixture Magento/Sales/_files/order_configurable_product.php
+ * @return void
+ * @dataProvider prepareInvoiceConfigurableProductDataProvider
+ */
+ public function testPrepareInvoiceConfigurableProduct(int $invoiceQty): void
+ {
+ /** @var OrderInterface $order */
+ $order = Bootstrap::getObjectManager()->create(Order::class)->load('100000001', 'increment_id');
+ $orderItems = $order->getItems();
+ foreach ($orderItems as $orderItem) {
+ if ($orderItem->getParentItemId()) {
+ $parentItemId = $orderItem->getParentItemId();
+ }
+ }
+ $invoice = $this->invoiceService->prepareInvoice($order, [$parentItemId => $invoiceQty]);
+ $invoiceItems = $invoice->getItems();
+ foreach ($invoiceItems as $invoiceItem) {
+ $this->assertEquals($invoiceQty, $invoiceItem->getQty());
+ }
+ }
+
+ public function prepareInvoiceConfigurableProductDataProvider()
+ {
+ return [
+ 'full invoice' => [2],
+ 'partial invoice' => [1]
+ ];
+ }
+
+ /**
+ * @param int $invoiceQty
+ * @magentoDataFixture Magento/Sales/_files/order.php
+ * @return void
+ * @dataProvider prepareInvoiceSimpleProductDataProvider
+ */
+ public function testPrepareInvoiceSimpleProduct(int $invoiceQty): void
+ {
+ /** @var OrderInterface $order */
+ $order = Bootstrap::getObjectManager()->create(Order::class)->load('100000001', 'increment_id');
+ $orderItems = $order->getItems();
+ $invoiceQtys = [];
+ foreach ($orderItems as $orderItem) {
+ $invoiceQtys[$orderItem->getItemId()] = $invoiceQty;
+ }
+ $invoice = $this->invoiceService->prepareInvoice($order, $invoiceQtys);
+ $invoiceItems = $invoice->getItems();
+ foreach ($invoiceItems as $invoiceItem) {
+ $this->assertEquals($invoiceQty, $invoiceItem->getQty());
+ }
+ }
+
+ public function prepareInvoiceSimpleProductDataProvider()
+ {
+ return [
+ 'full invoice' => [2],
+ 'partial invoice' => [1]
+ ];
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Search/Model/SynonymReaderTest.php b/dev/tests/integration/testsuite/Magento/Search/Model/SynonymReaderTest.php
index b9ba89ba53144..2d0020ba22680 100644
--- a/dev/tests/integration/testsuite/Magento/Search/Model/SynonymReaderTest.php
+++ b/dev/tests/integration/testsuite/Magento/Search/Model/SynonymReaderTest.php
@@ -48,7 +48,22 @@ public static function loadByPhraseDataProvider()
['synonyms' => 'queen,monarch', 'store_id' => 1, 'website_id' => 0],
['synonyms' => 'british,english', 'store_id' => 1, 'website_id' => 0]
]
- ]
+ ],
+ [
+ 'query_value', []
+ ],
+ [
+ 'query_value+', []
+ ],
+ [
+ 'query_value-', []
+ ],
+ [
+ 'query_@value', []
+ ],
+ [
+ 'query_value+@', []
+ ],
];
}
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
new file mode 100644
index 0000000000000..5c6c60866fafb
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php
@@ -0,0 +1,20 @@
+get(WriterInterface::class);
+
+$configWriter->save('carriers/ups/active', 1);
+
+$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
new file mode 100644
index 0000000000000..6d7894879f97b
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php
@@ -0,0 +1,16 @@
+create(WriterInterface::class);
+
+$configWriter->delete('carriers/ups/active');
diff --git a/dev/tests/integration/testsuite/Magento/UrlRewrite/Model/UrlFinderInterfaceTest.php b/dev/tests/integration/testsuite/Magento/UrlRewrite/Model/UrlFinderInterfaceTest.php
new file mode 100644
index 0000000000000..b6055f14e79d2
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/UrlRewrite/Model/UrlFinderInterfaceTest.php
@@ -0,0 +1,71 @@
+urlFinder = Bootstrap::getObjectManager()->create(UrlFinderInterface::class);
+ }
+
+ /**
+ * @dataProvider findOneDataProvider
+ * @param string $requestPath
+ * @param string $targetPath
+ * @param int $redirectType
+ */
+ public function testFindOneByData(string $requestPath, string $targetPath, int $redirectType)
+ {
+ $data = [
+ UrlRewrite::REQUEST_PATH => $requestPath,
+ ];
+ $urlRewrite = $this->urlFinder->findOneByData($data);
+ $this->assertEquals($targetPath, $urlRewrite->getTargetPath());
+ $this->assertEquals($redirectType, $urlRewrite->getRedirectType());
+ }
+
+ /**
+ * @return array
+ */
+ public function findOneDataProvider(): array
+ {
+ return [
+ ['string', 'test_page1', 0],
+ ['string/', 'string', 301],
+ ['string_permanent', 'test_page1', 301],
+ ['string_permanent/', 'test_page1', 301],
+ ['string_temporary', 'test_page1', 302],
+ ['string_temporary/', 'test_page1', 302],
+ ['строка', 'test_page1', 0],
+ ['строка/', 'строка', 301],
+ [urlencode('строка'), 'test_page2', 0],
+ [urlencode('строка') . '/', urlencode('строка'), 301],
+ ['другая_строка', 'test_page1', 302],
+ ['другая_строка/', 'test_page1', 302],
+ [urlencode('другая_строка'), 'test_page1', 302],
+ [urlencode('другая_строка') . '/', 'test_page1', 302],
+ ['السلسلة', 'test_page1', 0],
+ [urlencode('السلسلة'), 'test_page1', 0],
+ ];
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrites.php b/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrites.php
new file mode 100644
index 0000000000000..9edc6507308ee
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrites.php
@@ -0,0 +1,42 @@
+create(\Magento\UrlRewrite\Model\ResourceModel\UrlRewrite::class);
+foreach ($rewritesData as $rewriteData) {
+ list ($requestPath, $targetPath, $redirectType) = $rewriteData;
+ $rewrite = $objectManager->create(\Magento\UrlRewrite\Model\UrlRewrite::class);
+ $rewrite->setEntityType('custom')
+ ->setRequestPath($requestPath)
+ ->setTargetPath($targetPath)
+ ->setRedirectType($redirectType);
+ $rewriteResource->save($rewrite);
+}
diff --git a/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrites_rollback.php b/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrites_rollback.php
new file mode 100644
index 0000000000000..a98f947d614e0
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrites_rollback.php
@@ -0,0 +1,20 @@
+get(\Magento\Framework\Registry::class);
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+$urlRewriteCollection = $objectManager->create(\Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection::class);
+$collection = $urlRewriteCollection
+ ->addFieldToFilter('target_path', ['test_page1', 'test_page2'])
+ ->load()
+ ->walk('delete');
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php
index 92eae7a3fe3d7..940d05eb4d5d7 100644
--- a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php
+++ b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php
@@ -128,6 +128,7 @@ public function testAddActionProductNameXss()
public function testAllcartAction()
{
$formKey = $this->_objectManager->get(\Magento\Framework\Data\Form\FormKey::class)->getFormKey();
+ $this->getRequest()->setMethod('POST');
$this->getRequest()->setParam('form_key', $formKey);
$this->dispatch('wishlist/index/allcart');
diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/ShareTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/ShareTest.php
new file mode 100644
index 0000000000000..47705262caaf3
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/ShareTest.php
@@ -0,0 +1,92 @@
+login(1);
+ $this->prepareRequestData();
+ $this->dispatch('wishlist/index/send/');
+
+ $this->assertSessionMessages(
+ $this->equalTo(['Your wish list has been shared.']),
+ MessageInterface::TYPE_SUCCESS
+ );
+ }
+
+ /**
+ * Test share wishlist with incorrect data
+ *
+ * @magentoDataFixture Magento/Wishlist/_files/wishlist.php
+ */
+ public function testShareWishlistWithoutEmails()
+ {
+ $this->login(1);
+ $this->prepareRequestData(true);
+ $this->dispatch('wishlist/index/send/');
+
+ $this->assertSessionMessages(
+ $this->equalTo(['Please enter an email address.']),
+ MessageInterface::TYPE_ERROR
+ );
+ }
+
+ /**
+ * Login the user
+ *
+ * @param string $customerId Customer to mark as logged in for the session
+ * @return void
+ */
+ protected function login($customerId)
+ {
+ /** @var Session $session */
+ $session = $this->_objectManager->get(Session::class);
+ $session->loginById($customerId);
+ }
+
+ /**
+ * Prepares the request with data
+ *
+ * @param bool $invalidData
+ * @return void
+ */
+ private function prepareRequestData($invalidData = false)
+ {
+ Bootstrap::getInstance()->loadArea(Area::AREA_FRONTEND);
+ $emails = !$invalidData ? 'email-1@example.com,email-2@example.com' : '';
+
+ /** @var FormKey $formKey */
+ $formKey = $this->_objectManager->get(FormKey::class);
+ $post = [
+ 'emails' => $emails,
+ 'message' => '',
+ 'form_key' => $formKey->getFormKey(),
+ ];
+
+ $this->getRequest()->setMethod(Request::METHOD_POST);
+ $this->getRequest()->setPostValue($post);
+ }
+}
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js
index 2e238eb993029..fc60fbb0bdccc 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js
@@ -151,12 +151,14 @@ define([
}
}],
result = [{
+ defaultLabelVisible: true,
label: 'Label 2',
name: 'Name 2',
required: false,
columnsHeaderClasses: '',
sortOrder: 5
}, {
+ defaultLabelVisible: true,
label: 'Label 1',
name: 'Name 1',
required: false,
diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule1/revisions/without_setup_version/module.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule1/revisions/without_setup_version/module.xml
new file mode 100644
index 0000000000000..ed831eb6e9354
--- /dev/null
+++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule1/revisions/without_setup_version/module.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/drop_table_with_external_dependency/db_schema.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/drop_table_with_external_dependency/db_schema.xml
new file mode 100644
index 0000000000000..c22c41b7a5c03
--- /dev/null
+++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/drop_table_with_external_dependency/db_schema.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/without_setup_version/module.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/without_setup_version/module.xml
new file mode 100644
index 0000000000000..27e21dc3fe898
--- /dev/null
+++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/without_setup_version/module.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/dev/tests/setup-integration/testsuite/Magento/Setup/DeclarativeInstallerTest.php b/dev/tests/setup-integration/testsuite/Magento/Setup/DeclarativeInstallerTest.php
index 6097348d4fabc..e8698965de007 100644
--- a/dev/tests/setup-integration/testsuite/Magento/Setup/DeclarativeInstallerTest.php
+++ b/dev/tests/setup-integration/testsuite/Magento/Setup/DeclarativeInstallerTest.php
@@ -249,6 +249,45 @@ public function testInstallationWithDroppingTables()
self::assertEquals($this->getData(), $shardData);
}
+ /**
+ * @moduleName Magento_TestSetupDeclarationModule1
+ * @moduleName Magento_TestSetupDeclarationModule3
+ */
+ public function testInstallationWithDroppingTablesFromSecondaryModule()
+ {
+ $modules = [
+ 'Magento_TestSetupDeclarationModule1',
+ 'Magento_TestSetupDeclarationModule3',
+ ];
+
+ $this->moduleManager->updateRevision(
+ 'Magento_TestSetupDeclarationModule3',
+ 'drop_table_with_external_dependency',
+ 'db_schema.xml',
+ 'etc'
+ );
+
+ foreach ($modules as $moduleName) {
+ $this->moduleManager->updateRevision(
+ $moduleName,
+ 'without_setup_version',
+ 'module.xml',
+ 'etc'
+ );
+ }
+
+ try {
+ $this->cliCommand->install($modules);
+ } catch (\Exception $e) {
+ $installException = $e->getPrevious();
+ self::assertSame(1, $installException->getCode());
+ self::assertContains(
+ 'The reference table named "reference_table" is disabled',
+ $installException->getMessage()
+ );
+ }
+ }
+
/**
* @moduleName Magento_TestSetupDeclarationModule1
* @dataProviderFromFile Magento/TestSetupDeclarationModule1/fixture/declarative_installer/rollback.php
diff --git a/dev/tests/static/framework/Magento/TestFramework/Dependency/AnalyticsConfigRule.php b/dev/tests/static/framework/Magento/TestFramework/Dependency/AnalyticsConfigRule.php
new file mode 100644
index 0000000000000..b1a6da5e43822
--- /dev/null
+++ b/dev/tests/static/framework/Magento/TestFramework/Dependency/AnalyticsConfigRule.php
@@ -0,0 +1,43 @@
+]*class=[\'"]([^\'"]+)[\'"]#i', $contents, $matches)) {
+ $classes = array_pop($matches);
+ foreach ($classes as $class) {
+ $classParts = explode('\\', $class);
+ $module = implode('\\', array_slice($classParts, 0, 2));
+ if (strtolower($currentModule) !== strtolower($module)) {
+ $dependenciesInfo[] = [
+ 'module' => $module,
+ 'type' => RuleInterface::TYPE_HARD,
+ 'source' => $file,
+ ];
+ }
+ }
+ }
+
+ return $dependenciesInfo;
+ }
+}
diff --git a/dev/tests/static/framework/Magento/ruleset.xml b/dev/tests/static/framework/Magento/ruleset.xml
index d0f0d38f8fa03..9dde4b7bd7d32 100644
--- a/dev/tests/static/framework/Magento/ruleset.xml
+++ b/dev/tests/static/framework/Magento/ruleset.xml
@@ -84,5 +84,6 @@
+
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php
index a4113abed8030..e2e0357a38f77 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php
@@ -16,6 +16,7 @@
use Magento\TestFramework\Dependency\LayoutRule;
use Magento\TestFramework\Dependency\PhpRule;
use Magento\TestFramework\Dependency\ReportsConfigRule;
+use Magento\TestFramework\Dependency\AnalyticsConfigRule;
use Magento\TestFramework\Dependency\VirtualType\VirtualTypeMapper;
/**
@@ -78,6 +79,17 @@ class DependencyTest extends \PHPUnit\Framework\TestCase
*/
protected static $_listRoutesXml = [];
+ /**
+ * List of analytics.xml
+ *
+ * Format: array(
+ * '{Module_Name}' => '{Filename}'
+ * )
+ *
+ * @var array
+ */
+ protected static $_listAnalyticsXml = [];
+
/**
* List of routers
*
@@ -176,6 +188,7 @@ public static function setUpBeforeClass()
self::_prepareListConfigXml();
self::_prepareListDbSchemaXml();
self::_prepareListRoutesXml();
+ self::_prepareListAnalyticsXml();
self::_prepareMapRouters();
self::_prepareMapLayoutBlocks();
@@ -240,6 +253,7 @@ protected static function _initRules()
),
new DiRule(new VirtualTypeMapper()),
new ReportsConfigRule($dbRuleTables),
+ new AnalyticsConfigRule(),
];
}
@@ -571,6 +585,20 @@ protected static function _prepareListRoutesXml()
}
}
+ /**
+ * Prepare list of analytics.xml files
+ */
+ protected static function _prepareListAnalyticsXml()
+ {
+ $files = Files::init()->getDbSchemaFiles('analytics.xml', [], false);
+ foreach ($files as $file) {
+ if (preg_match('/(?[A-Z][a-z]+)[_\/\\\\](?[A-Z][a-zA-Z]+)/', $file, $matches)) {
+ $module = $matches['namespace'] . '\\' . $matches['module'];
+ self::$_listAnalyticsXml[$module] = $file;
+ }
+ }
+ }
+
/**
* Prepare map of routers
*/
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/RequestConfigTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/RequestConfigTest.php
index 4c0fed148aea8..f0177c449a3f9 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/RequestConfigTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/RequestConfigTest.php
@@ -102,8 +102,7 @@ public function testFileSchemaUsingInvalidXml($expectedErrors = null)
Element 'metric', attribute 'type': [facet 'enumeration'] " .
"The value 'sumasdasd' is not an element of the set {'sum', 'count', 'min', 'max', 'avg'}.
Element 'metric', attribute 'type': 'sumasdasd' is not a valid value of the local atomic type.
-Element 'bucket': Missing child element(s). Expected is one of ( metrics, ranges ).
-Element 'request': Missing child element(s). Expected is ( from )."
+Element 'bucket': Missing child element(s). Expected is one of ( metrics, ranges )."
)
);
parent::testFileSchemaUsingInvalidXml($expectedErrors);
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 0450ae1330cd8..35ba5803b09cc 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
@@ -209,3 +209,8 @@ Magento/Customer/Model/FileUploaderDataResolver.php
Magento/Customer/Model/Customer/DataProvider.php
Magento/InventoryShippingAdminUi/Ui/DataProvider
Magento/Elasticsearch6/Model/Client
+Magento/CatalogSearch/Model/ResourceModel/Fulltext
+Magento/Elasticsearch/Model/Layer/Search
+Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/FieldName/Resolver
+Magento/Elasticsearch6/Model/Client
+Magento/Config/App/Config/Type
diff --git a/lib/internal/Magento/Framework/App/FrontControllerInterface.php b/lib/internal/Magento/Framework/App/FrontControllerInterface.php
index a552d88e68f50..afd3091097d19 100644
--- a/lib/internal/Magento/Framework/App/FrontControllerInterface.php
+++ b/lib/internal/Magento/Framework/App/FrontControllerInterface.php
@@ -8,7 +8,7 @@
/**
* Application front controller responsible for dispatching application requests.
* Front controller contains logic common for all actions.
- * Evary application area has own front controller
+ * Every application area has own front controller.
*
* @api
*/
diff --git a/lib/internal/Magento/Framework/Cache/LockGuardedCacheLoader.php b/lib/internal/Magento/Framework/Cache/LockGuardedCacheLoader.php
new file mode 100644
index 0000000000000..216d8e9a0a01b
--- /dev/null
+++ b/lib/internal/Magento/Framework/Cache/LockGuardedCacheLoader.php
@@ -0,0 +1,116 @@
+locker = $locker;
+ $this->lockTimeout = $lockTimeout;
+ $this->delayTimeout = $delayTimeout;
+ }
+
+ /**
+ * Load data.
+ *
+ * @param string $lockName
+ * @param callable $dataLoader
+ * @param callable $dataCollector
+ * @param callable $dataSaver
+ * @return mixed
+ */
+ public function lockedLoadData(
+ string $lockName,
+ callable $dataLoader,
+ callable $dataCollector,
+ callable $dataSaver
+ ) {
+ $cachedData = $dataLoader(); //optimistic read
+
+ while ($cachedData === false && $this->locker->isLocked($lockName)) {
+ usleep($this->delayTimeout * 1000);
+ $cachedData = $dataLoader();
+ }
+
+ while ($cachedData === false) {
+ try {
+ if ($this->locker->lock($lockName, $this->lockTimeout / 1000)) {
+ $data = $dataCollector();
+ $dataSaver($data);
+ $cachedData = $data;
+ }
+ } finally {
+ $this->locker->unlock($lockName);
+ }
+
+ if ($cachedData === false) {
+ usleep($this->delayTimeout * 1000);
+ $cachedData = $dataLoader();
+ }
+ }
+
+ return $cachedData;
+ }
+
+ /**
+ * Clean data.
+ *
+ * @param string $lockName
+ * @param callable $dataCleaner
+ * @return void
+ */
+ public function lockedCleanData(string $lockName, callable $dataCleaner)
+ {
+ while ($this->locker->isLocked($lockName)) {
+ usleep($this->delayTimeout * 1000);
+ }
+ try {
+ if ($this->locker->lock($lockName, $this->lockTimeout / 1000)) {
+ $dataCleaner();
+ }
+ } finally {
+ $this->locker->unlock($lockName);
+ }
+ }
+}
diff --git a/lib/internal/Magento/Framework/Config/Dom.php b/lib/internal/Magento/Framework/Config/Dom.php
index 1d995bab007e5..f4721660d8da6 100644
--- a/lib/internal/Magento/Framework/Config/Dom.php
+++ b/lib/internal/Magento/Framework/Config/Dom.php
@@ -318,7 +318,7 @@ public static function validateDomDocument(
libxml_set_external_entity_loader([self::$urnResolver, 'registerEntityLoader']);
$errors = [];
try {
- $result = $dom->schemaValidate($schema);
+ $result = $dom->schemaValidate($schema, LIBXML_SCHEMA_CREATE);
if (!$result) {
$errors = self::getXmlErrors($errorFormat);
}
diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php
index 5c8f66683877c..0508b5e4fb359 100644
--- a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php
+++ b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php
@@ -135,6 +135,48 @@ public function validateDataProvider()
];
}
+ /**
+ * @param string $xml
+ * @param string $expectedValue
+ * @dataProvider validateWithDefaultValueDataProvider
+ */
+ public function testValidateWithDefaultValue($xml, $expectedValue)
+ {
+ if (!function_exists('libxml_set_external_entity_loader')) {
+ $this->markTestSkipped('Skipped on HHVM. Will be fixed in MAGETWO-45033');
+ }
+
+ $actualErrors = [];
+
+ $dom = new \Magento\Framework\Config\Dom($xml, $this->validationStateMock);
+ $dom->validate(__DIR__ . '/_files/sample.xsd', $actualErrors);
+
+ $actualValue = $dom->getDom()
+ ->getElementsByTagName('root')->item(0)
+ ->getElementsByTagName('node')->item(0)
+ ->getAttribute('attribute_with_default_value');
+
+ $this->assertEmpty($actualErrors);
+ $this->assertEquals($expectedValue, $actualValue);
+ }
+
+ /**
+ * @return array
+ */
+ public function validateWithDefaultValueDataProvider()
+ {
+ return [
+ 'default_value' => [
+ '',
+ 'default_value'
+ ],
+ 'custom_value' => [
+ '',
+ 'non_default_value'
+ ],
+ ];
+ }
+
public function testValidateCustomErrorFormat()
{
$xml = '';
diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/sample.xsd b/lib/internal/Magento/Framework/Config/Test/Unit/_files/sample.xsd
index 1f635b7081e05..701a2eb18c2a1 100644
--- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/sample.xsd
+++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/sample.xsd
@@ -21,6 +21,7 @@
+
diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
index 90186707177c9..fb62b720e0b1c 100644
--- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
+++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
@@ -2154,7 +2154,6 @@ public function createTable(Table $table)
*/
public function createTemporaryTable(\Magento\Framework\DB\Ddl\Table $table)
{
- $columns = $table->getColumns();
$sqlFragment = array_merge(
$this->_getColumnsDefinition($table),
$this->_getIndexesDefinition($table),
diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php
index dbafc9734e091..9c789e81913c4 100644
--- a/lib/internal/Magento/Framework/Data/Collection.php
+++ b/lib/internal/Magento/Framework/Data/Collection.php
@@ -7,7 +7,6 @@
use Magento\Framework\Data\Collection\EntityFactoryInterface;
use Magento\Framework\Option\ArrayInterface;
-use Magento\Framework\Exception\InputException;
/**
* Data collection
@@ -235,20 +234,12 @@ protected function _setIsLoaded($flag = true)
* Get current collection page
*
* @param int $displacement
- * @throws \Magento\Framework\Exception\InputException
* @return int
*/
public function getCurPage($displacement = 0)
{
if ($this->_curPage + $displacement < 1) {
return 1;
- } elseif ($this->_curPage > $this->getLastPageNumber() && $displacement === 0) {
- throw new InputException(
- __(
- 'currentPage value %1 specified is greater than the %2 page(s) available.',
- [$this->_curPage, $this->getLastPageNumber()]
- )
- );
} elseif ($this->_curPage + $displacement > $this->getLastPageNumber()) {
return $this->getLastPageNumber();
} else {
diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php
index 80c256d8553ef..daadeae2ac0e2 100644
--- a/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php
+++ b/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php
@@ -144,19 +144,6 @@ public function testGetCurPage()
$this->assertEquals(1, $this->_model->getCurPage());
}
- /**
- * Test for getCurPage with exception.
- *
- * @expectedException \Magento\Framework\Exception\StateException
- * @return void
- */
- public function testGetCurPageWithException()
- {
- $this->_model->setCurPage(10);
- $this->expectException(\Magento\Framework\Exception\InputException::class);
- $this->_model->getCurPage();
- }
-
/**
* Test for method possibleFlowWithItem.
*
diff --git a/lib/internal/Magento/Framework/Filesystem/DirectoryList.php b/lib/internal/Magento/Framework/Filesystem/DirectoryList.php
index 20874f60791c1..b3ab51b948109 100644
--- a/lib/internal/Magento/Framework/Filesystem/DirectoryList.php
+++ b/lib/internal/Magento/Framework/Filesystem/DirectoryList.php
@@ -8,6 +8,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Framework\Filesystem;
/**
@@ -96,7 +97,8 @@ public function __construct($root, array $config = [])
static::validate($config);
$this->root = $this->normalizePath($root);
$this->directories = static::getDefaultConfig();
- $this->directories[self::SYS_TMP] = [self::PATH => realpath(sys_get_temp_dir())];
+ $sysTmpPath = get_cfg_var('upload_tmp_dir') ?: sys_get_temp_dir();
+ $this->directories[self::SYS_TMP] = [self::PATH => realpath($sysTmpPath)];
// inject custom values from constructor
foreach ($this->directories as $code => $dir) {
diff --git a/lib/internal/Magento/Framework/Locale/Format.php b/lib/internal/Magento/Framework/Locale/Format.php
index ca50cdb2440f4..adcffe01b910e 100644
--- a/lib/internal/Magento/Framework/Locale/Format.php
+++ b/lib/internal/Magento/Framework/Locale/Format.php
@@ -5,6 +5,9 @@
*/
namespace Magento\Framework\Locale;
+/**
+ * Price locale format.
+ */
class Format implements \Magento\Framework\Locale\FormatInterface
{
/**
@@ -38,7 +41,8 @@ public function __construct(
}
/**
- * Returns the first found number from a string
+ * Returns the first found number from a string.
+ *
* Parsing depends on given locale (grouping and decimal)
*
* Examples for input:
@@ -100,7 +104,7 @@ public function getPriceFormat($localeCode = null, $currencyCode = null)
}
$formatter = new \NumberFormatter(
- $localeCode . '@currency=' . $currency->getCode(),
+ $currency->getCode() ? $localeCode . '@currency=' . $currency->getCode() : $localeCode,
\NumberFormatter::CURRENCY
);
$format = $formatter->getPattern();
diff --git a/lib/internal/Magento/Framework/Locale/Resolver.php b/lib/internal/Magento/Framework/Locale/Resolver.php
index b401da8960f05..d058bfd41ab1a 100644
--- a/lib/internal/Magento/Framework/Locale/Resolver.php
+++ b/lib/internal/Magento/Framework/Locale/Resolver.php
@@ -6,7 +6,12 @@
namespace Magento\Framework\Locale;
use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\App\DeploymentConfig;
+use Magento\Framework\App\ObjectManager;
+/**
+ * Manages locale config information.
+ */
class Resolver implements ResolverInterface
{
/**
@@ -52,26 +57,34 @@ class Resolver implements ResolverInterface
*/
private $defaultLocalePath;
+ /**
+ * @var DeploymentConfig
+ */
+ private $deploymentConfig;
+
/**
* @param ScopeConfigInterface $scopeConfig
* @param string $defaultLocalePath
* @param string $scopeType
* @param mixed $locale
+ * @param DeploymentConfig|null $deploymentConfig
*/
public function __construct(
ScopeConfigInterface $scopeConfig,
$defaultLocalePath,
$scopeType,
- $locale = null
+ $locale = null,
+ DeploymentConfig $deploymentConfig = null
) {
$this->scopeConfig = $scopeConfig;
$this->defaultLocalePath = $defaultLocalePath;
$this->scopeType = $scopeType;
+ $this->deploymentConfig = $deploymentConfig ?: ObjectManager::getInstance()->create(DeploymentConfig::class);
$this->setLocale($locale);
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getDefaultLocalePath()
{
@@ -79,7 +92,7 @@ public function getDefaultLocalePath()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDefaultLocale($locale)
{
@@ -88,12 +101,15 @@ public function setDefaultLocale($locale)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getDefaultLocale()
{
if (!$this->defaultLocale) {
- $locale = $this->scopeConfig->getValue($this->getDefaultLocalePath(), $this->scopeType);
+ $locale = false;
+ if ($this->deploymentConfig->isAvailable() && $this->deploymentConfig->isDbAvailable()) {
+ $locale = $this->scopeConfig->getValue($this->getDefaultLocalePath(), $this->scopeType);
+ }
if (!$locale) {
$locale = self::DEFAULT_LOCALE;
}
@@ -103,7 +119,7 @@ public function getDefaultLocale()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setLocale($locale = null)
{
@@ -116,7 +132,7 @@ public function setLocale($locale = null)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getLocale()
{
@@ -127,7 +143,7 @@ public function getLocale()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function emulate($scopeId)
{
@@ -147,7 +163,7 @@ public function emulate($scopeId)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function revert()
{
diff --git a/lib/internal/Magento/Framework/Lock/Backend/Cache.php b/lib/internal/Magento/Framework/Lock/Backend/Cache.php
index 61818cbb8c53c..dfe6bbb828352 100644
--- a/lib/internal/Magento/Framework/Lock/Backend/Cache.php
+++ b/lib/internal/Magento/Framework/Lock/Backend/Cache.php
@@ -14,6 +14,11 @@
*/
class Cache implements \Magento\Framework\Lock\LockManagerInterface
{
+ /**
+ * Prefix for marking that key is locked or not.
+ */
+ const LOCK_PREFIX = 'LOCKED_RECORD_INFO_';
+
/**
* @var FrontendInterface
*/
@@ -26,12 +31,13 @@ public function __construct(FrontendInterface $cache)
{
$this->cache = $cache;
}
+
/**
* @inheritdoc
*/
public function lock(string $name, int $timeout = -1): bool
{
- return $this->cache->save('1', $name, [], $timeout);
+ return $this->cache->save('1', $this->getIdentifier($name), [], $timeout);
}
/**
@@ -39,7 +45,7 @@ public function lock(string $name, int $timeout = -1): bool
*/
public function unlock(string $name): bool
{
- return $this->cache->remove($name);
+ return $this->cache->remove($this->getIdentifier($name));
}
/**
@@ -47,6 +53,17 @@ public function unlock(string $name): bool
*/
public function isLocked(string $name): bool
{
- return (bool)$this->cache->test($name);
+ return (bool)$this->cache->test($this->getIdentifier($name));
+ }
+
+ /**
+ * Get cache locked identifier based on cache identifier.
+ *
+ * @param string $cacheIdentifier
+ * @return string
+ */
+ private function getIdentifier(string $cacheIdentifier): string
+ {
+ return self::LOCK_PREFIX . $cacheIdentifier;
}
}
diff --git a/lib/internal/Magento/Framework/Lock/Backend/FileLock.php b/lib/internal/Magento/Framework/Lock/Backend/FileLock.php
new file mode 100644
index 0000000000000..d168e910a4ab7
--- /dev/null
+++ b/lib/internal/Magento/Framework/Lock/Backend/FileLock.php
@@ -0,0 +1,194 @@
+fileDriver = $fileDriver;
+ $this->path = rtrim($path, '/') . '/';
+
+ try {
+ if (!$this->fileDriver->isExists($this->path)) {
+ $this->fileDriver->createDirectory($this->path);
+ }
+ } catch (FileSystemException $exception) {
+ throw new RuntimeException(
+ new Phrase('Cannot create the directory for locks: %1', [$this->path]),
+ $exception
+ );
+ }
+ }
+
+ /**
+ * Acquires a lock by name
+ *
+ * @param string $name The lock name
+ * @param int $timeout Timeout in seconds. A negative timeout value means infinite timeout
+ * @return bool Returns true if the lock is acquired, otherwise returns false
+ * @throws RuntimeException Throws RuntimeException if cannot acquires the lock because FS problems
+ */
+ public function lock(string $name, int $timeout = -1): bool
+ {
+ try {
+ $lockFile = $this->getLockPath($name);
+ $fileResource = $this->fileDriver->fileOpen($lockFile, 'w+');
+ $skipDeadline = $timeout < 0;
+ $deadline = microtime(true) + $timeout;
+
+ while (!$this->tryToLock($fileResource)) {
+ if (!$skipDeadline && $deadline <= microtime(true)) {
+ $this->fileDriver->fileClose($fileResource);
+ return false;
+ }
+ usleep($this->sleepCycle);
+ }
+ } catch (FileSystemException $exception) {
+ throw new RuntimeException(new Phrase('Cannot acquire a lock.'), $exception);
+ }
+
+ $this->locks[$lockFile] = $fileResource;
+ return true;
+ }
+
+ /**
+ * Checks if a lock exists by name
+ *
+ * @param string $name The lock name
+ * @return bool Returns true if the lock exists, otherwise returns false
+ * @throws RuntimeException Throws RuntimeException if cannot check that the lock exists
+ */
+ public function isLocked(string $name): bool
+ {
+ $lockFile = $this->getLockPath($name);
+ $result = false;
+
+ try {
+ if ($this->fileDriver->isExists($lockFile)) {
+ $fileResource = $this->fileDriver->fileOpen($lockFile, 'w+');
+ if ($this->tryToLock($fileResource)) {
+ $result = false;
+ } else {
+ $result = true;
+ }
+ $this->fileDriver->fileClose($fileResource);
+ }
+ } catch (FileSystemException $exception) {
+ throw new RuntimeException(new Phrase('Cannot verify that the lock exists.'), $exception);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Remove the lock by name
+ *
+ * @param string $name The lock name
+ * @return bool If the lock is removed returns true, otherwise returns false
+ */
+ public function unlock(string $name): bool
+ {
+ $lockFile = $this->getLockPath($name);
+
+ if (isset($this->locks[$lockFile]) && $this->tryToUnlock($this->locks[$lockFile])) {
+ unset($this->locks[$lockFile]);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the full path to the lock file by name
+ *
+ * @param string $name The lock name
+ * @return string The path to the lock file
+ */
+ private function getLockPath(string $name): string
+ {
+ return $this->path . $name;
+ }
+
+ /**
+ * Tries to lock a file resource
+ *
+ * @param resource $resource The file resource
+ * @return bool If the lock is acquired returns true, otherwise returns false
+ */
+ private function tryToLock($resource): bool
+ {
+ try {
+ return $this->fileDriver->fileLock($resource, LOCK_EX | LOCK_NB);
+ } catch (FileSystemException $exception) {
+ return false;
+ }
+ }
+
+ /**
+ * Tries to unlock a file resource
+ *
+ * @param resource $resource The file resource
+ * @return bool If the lock is removed returns true, otherwise returns false
+ */
+ private function tryToUnlock($resource): bool
+ {
+ try {
+ return $this->fileDriver->fileLock($resource, LOCK_UN | LOCK_NB);
+ } catch (FileSystemException $exception) {
+ return false;
+ }
+ }
+}
diff --git a/lib/internal/Magento/Framework/Lock/Backend/Zookeeper.php b/lib/internal/Magento/Framework/Lock/Backend/Zookeeper.php
new file mode 100644
index 0000000000000..cbba981ae1b51
--- /dev/null
+++ b/lib/internal/Magento/Framework/Lock/Backend/Zookeeper.php
@@ -0,0 +1,280 @@
+\Zookeeper::PERM_ALL, 'scheme' => 'world', 'id' => 'anyone']];
+
+ /**
+ * The mapping list of the lock name with the full lock path
+ *
+ * @var array
+ */
+ private $locks = [];
+
+ /**
+ * The default path to storage locks
+ */
+ const DEFAULT_PATH = '/magento/locks';
+
+ /**
+ * @param string $host The host to connect to Zookeeper
+ * @param string $path The base path to locks in Zookeeper
+ * @throws RuntimeException
+ */
+ public function __construct(string $host, string $path = self::DEFAULT_PATH)
+ {
+ if (!$path) {
+ throw new RuntimeException(
+ new Phrase('The path needs to be a non-empty string.')
+ );
+ }
+
+ if (!$host) {
+ throw new RuntimeException(
+ new Phrase('The host needs to be a non-empty string.')
+ );
+ }
+
+ $this->host = $host;
+ $this->path = rtrim($path, '/') . '/';
+ }
+
+ /**
+ * @inheritdoc
+ *
+ * You can see the lock algorithm by the link
+ * @link https://zookeeper.apache.org/doc/r3.1.2/recipes.html#sc_recipes_Locks
+ *
+ * @throws RuntimeException
+ */
+ public function lock(string $name, int $timeout = -1): bool
+ {
+ $skipDeadline = $timeout < 0;
+ $lockPath = $this->getFullPathToLock($name);
+ $deadline = microtime(true) + $timeout;
+
+ if (!$this->checkAndCreateParentNode($lockPath)) {
+ throw new RuntimeException(new Phrase('Failed creating the path %1', [$lockPath]));
+ }
+
+ $lockKey = $this->getProvider()
+ ->create($lockPath, '1', $this->acl, \Zookeeper::EPHEMERAL | \Zookeeper::SEQUENCE);
+
+ if (!$lockKey) {
+ throw new RuntimeException(new Phrase('Failed creating lock %1', [$lockPath]));
+ }
+
+ while ($this->isAnyLock($lockKey, $this->getIndex($lockKey))) {
+ if (!$skipDeadline && $deadline <= microtime(true)) {
+ $this->getProvider()->delete($lockKey);
+ return false;
+ }
+
+ usleep($this->sleepCycle);
+ }
+
+ $this->locks[$name] = $lockKey;
+
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ *
+ * @throws RuntimeException
+ */
+ public function unlock(string $name): bool
+ {
+ if (!isset($this->locks[$name])) {
+ return false;
+ }
+
+ return $this->getProvider()->delete($this->locks[$name]);
+ }
+
+ /**
+ * @inheritdoc
+ *
+ * @throws RuntimeException
+ */
+ public function isLocked(string $name): bool
+ {
+ return $this->isAnyLock($this->getFullPathToLock($name));
+ }
+
+ /**
+ * Gets full path to lock by its name
+ *
+ * @param string $name
+ * @return string
+ */
+ private function getFullPathToLock(string $name): string
+ {
+ return $this->path . $name . '/' . $this->lockName;
+ }
+
+ /**
+ * Initiolizes and returns Zookeeper provider
+ *
+ * @return \Zookeeper
+ * @throws RuntimeException
+ */
+ private function getProvider(): \Zookeeper
+ {
+ if (!$this->zookeeper) {
+ $this->zookeeper = new \Zookeeper($this->host);
+ }
+
+ $deadline = microtime(true) + $this->connectionTimeout;
+ while ($this->zookeeper->getState() != \Zookeeper::CONNECTED_STATE) {
+ if ($deadline <= microtime(true)) {
+ throw new RuntimeException(new Phrase('Zookeeper connection timed out!'));
+ }
+ usleep($this->sleepCycle);
+ }
+
+ return $this->zookeeper;
+ }
+
+ /**
+ * Checks and creates base path recursively
+ *
+ * @param string $path
+ * @return bool
+ * @throws RuntimeException
+ */
+ private function checkAndCreateParentNode(string $path): bool
+ {
+ $path = dirname($path);
+ if ($this->getProvider()->exists($path)) {
+ return true;
+ }
+
+ if (!$this->checkAndCreateParentNode($path)) {
+ return false;
+ }
+
+ if ($this->getProvider()->create($path, '1', $this->acl)) {
+ return true;
+ }
+
+ return $this->getProvider()->exists($path);
+ }
+
+ /**
+ * Gets int increment of lock key
+ *
+ * @param string $key
+ * @return int|null
+ */
+ private function getIndex(string $key)
+ {
+ if (!preg_match('/' . $this->lockName . '([0-9]+)$/', $key, $matches)) {
+ return null;
+ }
+
+ return intval($matches[1]);
+ }
+
+ /**
+ * Checks if there is any sequence node under parent of $fullKey.
+ *
+ * At first checks that the $fullKey node is present, if not - returns false.
+ * If $indexKey is non-null and there is a smaller index than $indexKey then returns true,
+ * otherwise returns false.
+ *
+ * @param string $fullKey The full path without any sequence info
+ * @param int|null $indexKey The index to compare
+ * @return bool
+ * @throws RuntimeException
+ */
+ private function isAnyLock(string $fullKey, int $indexKey = null): bool
+ {
+ $parent = dirname($fullKey);
+
+ if (!$this->getProvider()->exists($parent)) {
+ return false;
+ }
+
+ $children = $this->getProvider()->getChildren($parent);
+
+ if (null === $indexKey && !empty($children)) {
+ return true;
+ }
+
+ foreach ($children as $childKey) {
+ $childIndex = $this->getIndex($childKey);
+
+ if (null === $childIndex) {
+ continue;
+ }
+
+ if ($childIndex < $indexKey) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/lib/internal/Magento/Framework/Lock/LockBackendFactory.php b/lib/internal/Magento/Framework/Lock/LockBackendFactory.php
new file mode 100644
index 0000000000000..b142085ef6563
--- /dev/null
+++ b/lib/internal/Magento/Framework/Lock/LockBackendFactory.php
@@ -0,0 +1,111 @@
+ DatabaseLock::class,
+ self::LOCK_ZOOKEEPER => ZookeeperLock::class,
+ self::LOCK_CACHE => CacheLock::class,
+ self::LOCK_FILE => FileLock::class,
+ ];
+
+ /**
+ * @param ObjectManagerInterface $objectManager The Object Manager instance
+ * @param DeploymentConfig $deploymentConfig The Application deployment configuration
+ */
+ public function __construct(
+ ObjectManagerInterface $objectManager,
+ DeploymentConfig $deploymentConfig
+ ) {
+ $this->objectManager = $objectManager;
+ $this->deploymentConfig = $deploymentConfig;
+ }
+
+ /**
+ * Creates an instance of LockManagerInterface using information from deployment config
+ *
+ * @return LockManagerInterface
+ * @throws RuntimeException
+ */
+ public function create(): LockManagerInterface
+ {
+ $provider = $this->deploymentConfig->get('lock/provider', self::LOCK_DB);
+ $config = $this->deploymentConfig->get('lock/config', []);
+
+ if (!isset($this->lockers[$provider])) {
+ throw new RuntimeException(new Phrase('Unknown locks provider: %1', [$provider]));
+ }
+
+ if (self::LOCK_ZOOKEEPER === $provider && !extension_loaded(self::LOCK_ZOOKEEPER)) {
+ throw new RuntimeException(new Phrase('php extension Zookeeper is not installed.'));
+ }
+
+ return $this->objectManager->create($this->lockers[$provider], $config);
+ }
+}
diff --git a/lib/internal/Magento/Framework/Lock/Proxy.php b/lib/internal/Magento/Framework/Lock/Proxy.php
new file mode 100644
index 0000000000000..2718bf6cb3456
--- /dev/null
+++ b/lib/internal/Magento/Framework/Lock/Proxy.php
@@ -0,0 +1,83 @@
+factory = $factory;
+ }
+
+ /**
+ * @inheritdoc
+ *
+ * @throws RuntimeException
+ */
+ public function isLocked(string $name): bool
+ {
+ return $this->getLocker()->isLocked($name);
+ }
+
+ /**
+ * @inheritdoc
+ *
+ * @throws RuntimeException
+ */
+ public function lock(string $name, int $timeout = -1): bool
+ {
+ return $this->getLocker()->lock($name, $timeout);
+ }
+
+ /**
+ * @inheritdoc
+ *
+ * @throws RuntimeException
+ */
+ public function unlock(string $name): bool
+ {
+ return $this->getLocker()->unlock($name);
+ }
+
+ /**
+ * Gets LockManagerInterface implementation using Factory
+ *
+ * @return LockManagerInterface
+ * @throws RuntimeException
+ */
+ private function getLocker(): LockManagerInterface
+ {
+ if (!$this->locker) {
+ $this->locker = $this->factory->create();
+ }
+
+ return $this->locker;
+ }
+}
diff --git a/lib/internal/Magento/Framework/Lock/Test/Unit/Backend/ZookeeperTest.php b/lib/internal/Magento/Framework/Lock/Test/Unit/Backend/ZookeeperTest.php
new file mode 100644
index 0000000000000..62521b9de3082
--- /dev/null
+++ b/lib/internal/Magento/Framework/Lock/Test/Unit/Backend/ZookeeperTest.php
@@ -0,0 +1,68 @@
+markTestSkipped('Test was skipped because php extension Zookeeper is not installed.');
+ }
+ }
+
+ /**
+ * @expectedException \Magento\Framework\Exception\RuntimeException
+ * @expectedExceptionMessage The path needs to be a non-empty string.
+ * @return void
+ */
+ public function testConstructionWithPathException()
+ {
+ $this->zookeeperProvider = new ZookeeperProvider($this->host, '');
+ }
+
+ /**
+ * @expectedException \Magento\Framework\Exception\RuntimeException
+ * @expectedExceptionMessage The host needs to be a non-empty string.
+ * @return void
+ */
+ public function testConstructionWithHostException()
+ {
+ $this->zookeeperProvider = new ZookeeperProvider('', $this->path);
+ }
+
+ /**
+ * @return void
+ */
+ public function testConstructionWithoutException()
+ {
+ $this->zookeeperProvider = new ZookeeperProvider($this->host, $this->path);
+ }
+}
diff --git a/lib/internal/Magento/Framework/Lock/Test/Unit/LockBackendFactoryTest.php b/lib/internal/Magento/Framework/Lock/Test/Unit/LockBackendFactoryTest.php
new file mode 100644
index 0000000000000..ebf2f54f3e093
--- /dev/null
+++ b/lib/internal/Magento/Framework/Lock/Test/Unit/LockBackendFactoryTest.php
@@ -0,0 +1,116 @@
+objectManagerMock = $this->getMockForAbstractClass(ObjectManagerInterface::class);
+ $this->deploymentConfigMock = $this->createMock(DeploymentConfig::class);
+ $this->factory = new LockBackendFactory($this->objectManagerMock, $this->deploymentConfigMock);
+ }
+
+ /**
+ * @expectedException \Magento\Framework\Exception\RuntimeException
+ * @expectedExceptionMessage Unknown locks provider: someProvider
+ */
+ public function testCreateWithException()
+ {
+ $this->deploymentConfigMock->expects($this->exactly(2))
+ ->method('get')
+ ->withConsecutive(['lock/provider', LockBackendFactory::LOCK_DB], ['lock/config', []])
+ ->willReturnOnConsecutiveCalls('someProvider', []);
+
+ $this->factory->create();
+ }
+
+ /**
+ * @param string $lockProvider
+ * @param string $lockProviderClass
+ * @param array $config
+ * @dataProvider createDataProvider
+ */
+ public function testCreate(string $lockProvider, string $lockProviderClass, array $config)
+ {
+ $lockManagerMock = $this->getMockForAbstractClass(LockManagerInterface::class);
+ $this->deploymentConfigMock->expects($this->exactly(2))
+ ->method('get')
+ ->withConsecutive(['lock/provider', LockBackendFactory::LOCK_DB], ['lock/config', []])
+ ->willReturnOnConsecutiveCalls($lockProvider, $config);
+ $this->objectManagerMock->expects($this->once())
+ ->method('create')
+ ->with($lockProviderClass, $config)
+ ->willReturn($lockManagerMock);
+
+ $this->assertSame($lockManagerMock, $this->factory->create());
+ }
+
+ /**
+ * @return array
+ */
+ public function createDataProvider(): array
+ {
+ $data = [
+ 'db' => [
+ 'lockProvider' => LockBackendFactory::LOCK_DB,
+ 'lockProviderClass' => DatabaseLock::class,
+ 'config' => ['prefix' => 'somePrefix'],
+ ],
+ 'cache' => [
+ 'lockProvider' => LockBackendFactory::LOCK_CACHE,
+ 'lockProviderClass' => CacheLock::class,
+ 'config' => [],
+ ],
+ 'file' => [
+ 'lockProvider' => LockBackendFactory::LOCK_FILE,
+ 'lockProviderClass' => FileLock::class,
+ 'config' => ['path' => '/my/path'],
+ ],
+ ];
+
+ if (extension_loaded('zookeeper')) {
+ $data['zookeeper'] = [
+ 'lockProvider' => LockBackendFactory::LOCK_ZOOKEEPER,
+ 'lockProviderClass' => ZookeeperLock::class,
+ 'config' => ['host' => 'some host'],
+ ];
+ }
+
+ return $data;
+ }
+}
diff --git a/lib/internal/Magento/Framework/Lock/Test/Unit/ProxyTest.php b/lib/internal/Magento/Framework/Lock/Test/Unit/ProxyTest.php
new file mode 100644
index 0000000000000..c71dad701d715
--- /dev/null
+++ b/lib/internal/Magento/Framework/Lock/Test/Unit/ProxyTest.php
@@ -0,0 +1,106 @@
+factoryMock = $this->createMock(LockBackendFactory::class);
+ $this->lockerMock = $this->getMockForAbstractClass(LockManagerInterface::class);
+ $this->proxy = new Proxy($this->factoryMock);
+ }
+
+ /**
+ * @return void
+ */
+ public function testIsLocked()
+ {
+ $lockName = 'testLock';
+ $this->factoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($this->lockerMock);
+ $this->lockerMock->expects($this->exactly(2))
+ ->method('isLocked')
+ ->with($lockName)
+ ->willReturn(true);
+
+ $this->assertTrue($this->proxy->isLocked($lockName));
+
+ // Call one more time to check that method Factory::create is called one time
+ $this->assertTrue($this->proxy->isLocked($lockName));
+ }
+
+ /**
+ * @return void
+ */
+ public function testLock()
+ {
+ $lockName = 'testLock';
+ $timeout = 123;
+ $this->factoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($this->lockerMock);
+ $this->lockerMock->expects($this->exactly(2))
+ ->method('lock')
+ ->with($lockName, $timeout)
+ ->willReturn(true);
+
+ $this->assertTrue($this->proxy->lock($lockName, $timeout));
+
+ // Call one more time to check that method Factory::create is called one time
+ $this->assertTrue($this->proxy->lock($lockName, $timeout));
+ }
+
+ /**
+ * @return void
+ */
+ public function testUnlock()
+ {
+ $lockName = 'testLock';
+ $this->factoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($this->lockerMock);
+ $this->lockerMock->expects($this->exactly(2))
+ ->method('unlock')
+ ->with($lockName)
+ ->willReturn(true);
+
+ $this->assertTrue($this->proxy->unlock($lockName));
+
+ // Call one more time to check that method Factory::create is called one time
+ $this->assertTrue($this->proxy->unlock($lockName));
+ }
+}
diff --git a/lib/internal/Magento/Framework/MessageQueue/CallbackInvoker.php b/lib/internal/Magento/Framework/MessageQueue/CallbackInvoker.php
index cb80bc4becaec..48c33c48f12e6 100644
--- a/lib/internal/Magento/Framework/MessageQueue/CallbackInvoker.php
+++ b/lib/internal/Magento/Framework/MessageQueue/CallbackInvoker.php
@@ -9,7 +9,7 @@
/**
* Class CallbackInvoker to invoke callbacks for consumer classes
*/
-class CallbackInvoker
+class CallbackInvoker implements CallbackInvokerInterface
{
/**
* Run short running process
diff --git a/lib/internal/Magento/Framework/MessageQueue/CallbackInvokerInterface.php b/lib/internal/Magento/Framework/MessageQueue/CallbackInvokerInterface.php
new file mode 100644
index 0000000000000..36658f2e4eebe
--- /dev/null
+++ b/lib/internal/Magento/Framework/MessageQueue/CallbackInvokerInterface.php
@@ -0,0 +1,24 @@
+getMockForAbstractClass();
$configuration->expects($this->atLeastOnce())->method('getHandlers')->willReturn([]);
$this->messageStatusProcessor->expects($this->exactly(2))->method('acknowledgeMessages');
- $mergedMessage = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class)
+ $mergedMessage = $this->getMockBuilder(\Magento\Framework\Api\CustomAttributesDataInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$message = $this->getMockBuilder(\Magento\Framework\MessageQueue\EnvelopeInterface::class)
@@ -116,7 +116,7 @@ public function testProcessWithConnectionLostException()
$exception = new \Magento\Framework\MessageQueue\ConnectionLostException(__('Exception Message'));
$configuration->expects($this->atLeastOnce())->method('getHandlers')->willThrowException($exception);
$this->messageStatusProcessor->expects($this->once())->method('acknowledgeMessages');
- $mergedMessage = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class)
+ $mergedMessage = $this->getMockBuilder(\Magento\Framework\Api\CustomAttributesDataInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$message = $this->getMockBuilder(\Magento\Framework\MessageQueue\EnvelopeInterface::class)
@@ -158,7 +158,7 @@ public function testProcessWithException()
$configuration->expects($this->atLeastOnce())->method('getHandlers')->willThrowException($exception);
$this->messageStatusProcessor->expects($this->once())->method('acknowledgeMessages');
$this->messageStatusProcessor->expects($this->atLeastOnce())->method('rejectMessages');
- $mergedMessage = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class)
+ $mergedMessage = $this->getMockBuilder(\Magento\Framework\Api\CustomAttributesDataInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$message = $this->getMockBuilder(\Magento\Framework\MessageQueue\EnvelopeInterface::class)
diff --git a/lib/internal/Magento/Framework/Oauth/Oauth.php b/lib/internal/Magento/Framework/Oauth/Oauth.php
index 5e48fb5ed30f9..919b0e4c86ba0 100644
--- a/lib/internal/Magento/Framework/Oauth/Oauth.php
+++ b/lib/internal/Magento/Framework/Oauth/Oauth.php
@@ -9,6 +9,9 @@
use Magento\Framework\Encryption\Helper\Security;
use Magento\Framework\Phrase;
+/**
+ * Authorization service.
+ */
class Oauth implements OauthInterface
{
/**
@@ -61,7 +64,7 @@ public static function getSupportedSignatureMethods()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getRequestToken($params, $requestUrl, $httpMethod = 'POST')
{
@@ -74,7 +77,7 @@ public function getRequestToken($params, $requestUrl, $httpMethod = 'POST')
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getAccessToken($params, $requestUrl, $httpMethod = 'POST')
{
@@ -102,7 +105,7 @@ public function getAccessToken($params, $requestUrl, $httpMethod = 'POST')
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function validateAccessTokenRequest($params, $requestUrl, $httpMethod = 'POST')
{
@@ -125,7 +128,7 @@ public function validateAccessTokenRequest($params, $requestUrl, $httpMethod = '
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function validateAccessToken($accessToken)
{
@@ -133,7 +136,7 @@ public function validateAccessToken($accessToken)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function buildAuthorizationHeader(
$params,
@@ -199,7 +202,7 @@ protected function _validateSignature($params, $consumerSecret, $httpMethod, $re
);
if (!Security::compareStrings($calculatedSign, $params['oauth_signature'])) {
- throw new Exception(new Phrase('The signatire is invalid. Verify and try again.'));
+ throw new Exception(new Phrase('The signature is invalid. Verify and try again.'));
}
}
diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Adapter.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Adapter.php
index 897b67d8d46ec..e1b423d738a20 100644
--- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Adapter.php
+++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Adapter.php
@@ -7,6 +7,7 @@
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DB\Ddl\Table;
+use Magento\Framework\DB\Select;
use Magento\Framework\Search\Adapter\Mysql\Aggregation\Builder as AggregationBuilder;
use Magento\Framework\Search\AdapterInterface;
use Magento\Framework\Search\RequestInterface;
@@ -49,6 +50,16 @@ class Adapter implements AdapterInterface
*/
private $temporaryStorageFactory;
+ /**
+ * Query Select Parts to be skipped when prepare query for count
+ *
+ * @var array
+ */
+ private $countSqlSkipParts = [
+ \Magento\Framework\DB\Select::LIMIT_COUNT => true,
+ \Magento\Framework\DB\Select::LIMIT_OFFSET => true,
+ ];
+
/**
* @param Mapper $mapper
* @param ResponseFactory $responseFactory
@@ -86,6 +97,7 @@ public function query(RequestInterface $request)
$response = [
'documents' => $documents,
'aggregations' => $aggregations,
+ 'total' => $this->getSize($query)
];
return $this->responseFactory->create($response);
}
@@ -114,4 +126,39 @@ private function getConnection()
{
return $this->resource->getConnection();
}
+
+ /**
+ * Get rows size
+ *
+ * @param Select $query
+ * @return int
+ */
+ private function getSize(Select $query): int
+ {
+ $sql = $this->getSelectCountSql($query);
+ $parentSelect = $this->getConnection()->select();
+ $parentSelect->from(['core_select' => $sql]);
+ $parentSelect->reset(\Magento\Framework\DB\Select::COLUMNS);
+ $parentSelect->columns('COUNT(*)');
+ $totalRecords = $this->getConnection()->fetchOne($parentSelect);
+
+ return intval($totalRecords);
+ }
+
+ /**
+ * Reset limit and offset
+ *
+ * @param Select $query
+ * @return Select
+ */
+ private function getSelectCountSql(Select $query): Select
+ {
+ foreach ($this->countSqlSkipParts as $part => $toSkip) {
+ if ($toSkip) {
+ $query->reset($part);
+ }
+ }
+
+ return $query;
+ }
}
diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/ResponseFactory.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/ResponseFactory.php
index 776dab93c2dcd..b41a43883fde5 100644
--- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/ResponseFactory.php
+++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/ResponseFactory.php
@@ -68,7 +68,8 @@ public function create($rawResponse)
\Magento\Framework\Search\Response\QueryResponse::class,
[
'documents' => $documents,
- 'aggregations' => $aggregations
+ 'aggregations' => $aggregations,
+ 'total' => $rawResponse['total']
]
);
}
diff --git a/lib/internal/Magento/Framework/Search/Request.php b/lib/internal/Magento/Framework/Search/Request.php
index d55b2085e87ef..60f3338046613 100644
--- a/lib/internal/Magento/Framework/Search/Request.php
+++ b/lib/internal/Magento/Framework/Search/Request.php
@@ -54,6 +54,11 @@ class Request implements RequestInterface
*/
protected $dimensions;
+ /**
+ * @var array
+ */
+ private $sort;
+
/**
* @param string $name
* @param string $indexName
@@ -62,6 +67,7 @@ class Request implements RequestInterface
* @param int|null $size
* @param Dimension[] $dimensions
* @param RequestBucketInterface[] $buckets
+ * @param array $sort
*/
public function __construct(
$name,
@@ -70,7 +76,8 @@ public function __construct(
$from = null,
$size = null,
array $dimensions = [],
- array $buckets = []
+ array $buckets = [],
+ $sort = []
) {
$this->name = $name;
$this->index = $indexName;
@@ -79,10 +86,11 @@ public function __construct(
$this->size = $size;
$this->buckets = $buckets;
$this->dimensions = $dimensions;
+ $this->sort = $sort;
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getName()
{
@@ -90,7 +98,7 @@ public function getName()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getIndex()
{
@@ -98,7 +106,7 @@ public function getIndex()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getDimensions()
{
@@ -106,7 +114,7 @@ public function getDimensions()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getAggregation()
{
@@ -114,7 +122,7 @@ public function getAggregation()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getQuery()
{
@@ -122,7 +130,7 @@ public function getQuery()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getFrom()
{
@@ -130,10 +138,18 @@ public function getFrom()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getSize()
{
return $this->size;
}
+
+ /**
+ * @inheritdoc
+ */
+ public function getSort()
+ {
+ return $this->sort;
+ }
}
diff --git a/lib/internal/Magento/Framework/Search/Request/Binder.php b/lib/internal/Magento/Framework/Search/Request/Binder.php
index 34b5d72005e74..9df1ee87eb869 100644
--- a/lib/internal/Magento/Framework/Search/Request/Binder.php
+++ b/lib/internal/Magento/Framework/Search/Request/Binder.php
@@ -6,6 +6,8 @@
namespace Magento\Framework\Search\Request;
/**
+ * Data binder for search request.
+ *
* @api
*/
class Binder
@@ -24,6 +26,9 @@ public function bind(array $requestData, array $bindData)
$data['queries'] = $this->processData($requestData['queries'], $bindData['placeholder']);
$data['filters'] = $this->processData($requestData['filters'], $bindData['placeholder']);
$data['aggregations'] = $this->processData($requestData['aggregations'], $bindData['placeholder']);
+ if (isset($bindData['sort']) && isset($requestData['sort'])) {
+ $data['sort'] = $this->processData($requestData['sort'], $bindData['sort']);
+ }
return $data;
}
@@ -48,6 +53,8 @@ private function processLimits($data, $bindData)
}
/**
+ * Dimensions process.
+ *
* @param array $data
* @param array $bindData
* @return array
diff --git a/lib/internal/Magento/Framework/Search/Request/Builder.php b/lib/internal/Magento/Framework/Search/Request/Builder.php
index a16b3369cdda0..74bc65010a934 100644
--- a/lib/internal/Magento/Framework/Search/Request/Builder.php
+++ b/lib/internal/Magento/Framework/Search/Request/Builder.php
@@ -11,7 +11,10 @@
use Magento\Framework\Search\RequestInterface;
/**
+ * Search request builder.
+ *
* @api
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Builder
{
@@ -95,6 +98,18 @@ public function setFrom($from)
return $this;
}
+ /**
+ * Set sort.
+ *
+ * @param \Magento\Framework\Api\SortOrder[] $sort
+ * @return $this
+ */
+ public function setSort($sort)
+ {
+ $this->data['sort'] = $sort;
+ return $this;
+ }
+
/**
* Bind dimension data by name
*
@@ -139,6 +154,9 @@ public function create()
}
$data = $this->binder->bind($data, $this->data);
+ if (isset($this->data['sort'])) {
+ $data['sort'] = $this->prepareSorts($this->data['sort']);
+ }
$data = $this->cleaner->clean($data);
$this->clear();
@@ -146,6 +164,25 @@ public function create()
return $this->convert($data);
}
+ /**
+ * Prepare sort data for request.
+ *
+ * @param array $sorts
+ * @return array
+ */
+ private function prepareSorts(array $sorts)
+ {
+ $sortData = [];
+ foreach ($sorts as $sortField => $direction) {
+ $sortData[] = [
+ 'field' => $sortField,
+ 'direction' => $direction,
+ ];
+ }
+
+ return $sortData;
+ }
+
/**
* Clear data
*
@@ -178,21 +215,27 @@ private function convert($data)
'filters' => $data['filters']
]
);
+ $requestData = [
+ 'name' => $data['query'],
+ 'indexName' => $data['index'],
+ 'from' => $data['from'],
+ 'size' => $data['size'],
+ 'query' => $mapper->getRootQuery(),
+ 'dimensions' => $this->buildDimensions(isset($data['dimensions']) ? $data['dimensions'] : []),
+ 'buckets' => $mapper->getBuckets()
+ ];
+ if (isset($data['sort'])) {
+ $requestData['sort'] = $data['sort'];
+ }
return $this->objectManager->create(
\Magento\Framework\Search\Request::class,
- [
- 'name' => $data['query'],
- 'indexName' => $data['index'],
- 'from' => $data['from'],
- 'size' => $data['size'],
- 'query' => $mapper->getRootQuery(),
- 'dimensions' => $this->buildDimensions(isset($data['dimensions']) ? $data['dimensions'] : []),
- 'buckets' => $mapper->getBuckets()
- ]
+ $requestData
);
}
/**
+ * Build dimensions.
+ *
* @param array $dimensionsData
* @return array
*/
diff --git a/lib/internal/Magento/Framework/Search/RequestInterface.php b/lib/internal/Magento/Framework/Search/RequestInterface.php
index 16df80f755c07..2de756e754a27 100644
--- a/lib/internal/Magento/Framework/Search/RequestInterface.php
+++ b/lib/internal/Magento/Framework/Search/RequestInterface.php
@@ -64,4 +64,11 @@ public function getFrom();
* @return int|null
*/
public function getSize();
+
+ /**
+ * Get Sort items
+ *
+ * @return array
+ */
+ public function getSort();
}
diff --git a/lib/internal/Magento/Framework/Search/Response/QueryResponse.php b/lib/internal/Magento/Framework/Search/Response/QueryResponse.php
index c2328398e53dc..90c7056ea2549 100644
--- a/lib/internal/Magento/Framework/Search/Response/QueryResponse.php
+++ b/lib/internal/Magento/Framework/Search/Response/QueryResponse.php
@@ -29,18 +29,26 @@ class QueryResponse implements ResponseInterface
*/
protected $aggregations;
+ /**
+ * @var int
+ */
+ private $total;
+
/**
* @param Document[] $documents
* @param AggregationInterface $aggregations
+ * @param int $total
*/
- public function __construct(array $documents, AggregationInterface $aggregations)
+ public function __construct(array $documents, AggregationInterface $aggregations, int $total = 0)
{
$this->documents = $documents;
$this->aggregations = $aggregations;
+ $this->total = $total;
}
/**
- * Countable: return count of fields in document
+ * Countable: return count of fields in document.
+ *
* @return int
*/
public function count()
@@ -59,10 +67,18 @@ public function getIterator()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getAggregations()
{
return $this->aggregations;
}
+
+ /**
+ * @inheritdoc
+ */
+ public function getTotal(): int
+ {
+ return $this->total;
+ }
}
diff --git a/lib/internal/Magento/Framework/Search/ResponseInterface.php b/lib/internal/Magento/Framework/Search/ResponseInterface.php
index 3b89528532602..c6c0d0ab59e10 100644
--- a/lib/internal/Magento/Framework/Search/ResponseInterface.php
+++ b/lib/internal/Magento/Framework/Search/ResponseInterface.php
@@ -16,4 +16,11 @@ interface ResponseInterface extends \IteratorAggregate, \Countable
* @return \Magento\Framework\Api\Search\AggregationInterface
*/
public function getAggregations();
+
+ /**
+ * Return total count of items.
+ *
+ * @return int
+ */
+ public function getTotal(): int;
}
diff --git a/lib/internal/Magento/Framework/Search/Search.php b/lib/internal/Magento/Framework/Search/Search.php
index 16dfc6fdd1ddb..fe228546b55fb 100644
--- a/lib/internal/Magento/Framework/Search/Search.php
+++ b/lib/internal/Magento/Framework/Search/Search.php
@@ -10,6 +10,9 @@
use Magento\Framework\App\ScopeResolverInterface;
use Magento\Framework\Search\Request\Builder;
+/**
+ * Search API for all requests.
+ */
class Search implements SearchInterface
{
/**
@@ -51,7 +54,7 @@ public function __construct(
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function search(SearchCriteriaInterface $searchCriteria)
{
@@ -68,6 +71,7 @@ public function search(SearchCriteriaInterface $searchCriteria)
$this->requestBuilder->setFrom($searchCriteria->getCurrentPage() * $searchCriteria->getPageSize());
$this->requestBuilder->setSize($searchCriteria->getPageSize());
+ $this->requestBuilder->setSort($searchCriteria->getSortOrders());
$request = $this->requestBuilder->create();
$searchResponse = $this->searchEngine->search($request);
diff --git a/lib/internal/Magento/Framework/Search/SearchResponseBuilder.php b/lib/internal/Magento/Framework/Search/SearchResponseBuilder.php
index 40fcd493861d7..2314252f4609c 100644
--- a/lib/internal/Magento/Framework/Search/SearchResponseBuilder.php
+++ b/lib/internal/Magento/Framework/Search/SearchResponseBuilder.php
@@ -9,6 +9,9 @@
use Magento\Framework\Api\Search\DocumentFactory;
use Magento\Framework\Api\Search\SearchResultFactory;
+/**
+ * Builder for search response.
+ */
class SearchResponseBuilder
{
/**
@@ -35,6 +38,8 @@ public function __construct(
}
/**
+ * Build search result by search response.
+ *
* @param ResponseInterface $response
* @return SearchResultInterface
*/
@@ -46,7 +51,7 @@ public function build(ResponseInterface $response)
$documents = iterator_to_array($response);
$searchResult->setItems($documents);
$searchResult->setAggregations($response->getAggregations());
- $searchResult->setTotalCount(count($documents));
+ $searchResult->setTotalCount($response->getTotal());
return $searchResult;
}
diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/AdapterTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/AdapterTest.php
index 55d26493ca379..fbb56361bfe71 100644
--- a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/AdapterTest.php
+++ b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/AdapterTest.php
@@ -155,15 +155,22 @@ public function testQuery()
'aggregation2' => [2, 4],
],
],
+ 'total' => 1
];
$select = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
->disableOriginalConstructor()
->getMock();
- $this->connectionAdapter->expects($this->once())
+
+ $this->connectionAdapter->expects($this->exactly(2))
->method('select')
->willReturn($select);
+ $this->connectionAdapter->expects($this->once())
+ ->method('fetchOne')
+ ->with($select)
+ ->willReturn($selectResult['total']);
+
$table = $this->getMockBuilder(\Magento\Framework\DB\Ddl\Table::class)
->disableOriginalConstructor()
->getMock();
diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/ResponseFactoryTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/ResponseFactoryTest.php
index c0699156decd0..3d21064b13d47 100644
--- a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/ResponseFactoryTest.php
+++ b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/ResponseFactoryTest.php
@@ -49,6 +49,7 @@ public function testCreate()
['title' => 'twoTitle', 'description' => 'twoDescription'],
],
'aggregations' => [],
+ 'total' => 2
];
$this->documentFactory->expects($this->at(0))->method('create')
@@ -61,7 +62,7 @@ public function testCreate()
$this->objectManager->expects($this->once())->method('create')
->with(
$this->equalTo(\Magento\Framework\Search\Response\QueryResponse::class),
- $this->equalTo(['documents' => ['document1', 'document2'], 'aggregations' => null])
+ $this->equalTo(['documents' => ['document1', 'document2'], 'aggregations' => null, 'total' => 2])
)
->will($this->returnValue('QueryResponseObject'));
diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Response/QueryResponseTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Response/QueryResponseTest.php
index a60a280cb602a..a994559f28f0b 100644
--- a/lib/internal/Magento/Framework/Search/Test/Unit/Response/QueryResponseTest.php
+++ b/lib/internal/Magento/Framework/Search/Test/Unit/Response/QueryResponseTest.php
@@ -46,6 +46,7 @@ protected function setUp()
[
'documents' => $this->documents,
'aggregations' => $this->aggregations,
+ 'total' => 1
]
);
}
diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/SearchResponseBuilderTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/SearchResponseBuilderTest.php
index a0b11959a42db..9ffafae9622f3 100644
--- a/lib/internal/Magento/Framework/Search/Test/Unit/SearchResponseBuilderTest.php
+++ b/lib/internal/Magento/Framework/Search/Test/Unit/SearchResponseBuilderTest.php
@@ -67,7 +67,7 @@ public function testBuild()
/** @var QueryResponse|\PHPUnit_Framework_MockObject_MockObject $response */
$response = $this->getMockBuilder(\Magento\Framework\Search\Response\QueryResponse::class)
- ->setMethods(['getIterator', 'getAggregations'])
+ ->setMethods(['getIterator', 'getAggregations', 'getTotal'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$response->expects($this->any())
@@ -76,6 +76,9 @@ public function testBuild()
$response->expects($this->once())
->method('getAggregations')
->willReturn($aggregations);
+ $response->expects($this->any())
+ ->method('getTotal')
+ ->willReturn(1);
$result = $this->model->build($response);
diff --git a/lib/internal/Magento/Framework/Search/etc/requests.xsd b/lib/internal/Magento/Framework/Search/etc/requests.xsd
index a49124748b295..7d277382b698f 100644
--- a/lib/internal/Magento/Framework/Search/etc/requests.xsd
+++ b/lib/internal/Magento/Framework/Search/etc/requests.xsd
@@ -28,8 +28,8 @@
-
-
+
+
diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Declaration/SchemaBuilder.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Declaration/SchemaBuilder.php
index 34a99f26a4ef1..4c65d8a70bed5 100644
--- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Declaration/SchemaBuilder.php
+++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Declaration/SchemaBuilder.php
@@ -350,6 +350,13 @@ private function processConstraints(array $tableData, string $resource, Schema $
if ($constraintData['type'] === 'foreign') {
$constraintData['column'] = $this->getColumnByName($constraintData['column'], $table);
$referenceTableData = $this->tablesData[$constraintData['referenceTable']];
+
+ if ($this->isDisabled($referenceTableData)) {
+ throw new \LogicException(
+ sprintf('The reference table named "%s" is disabled', $referenceTableData['name'])
+ );
+ }
+
//If we are referenced to the same table we need to specify it
//Get table name from resource connection regarding prefix settings
$refTableName = $this->resourceConnection->getTableName($referenceTableData['name']);
diff --git a/lib/internal/Magento/Framework/Setup/OldDbValidator.php b/lib/internal/Magento/Framework/Setup/OldDbValidator.php
index 4c224a6c713ef..018b010e8fe4a 100644
--- a/lib/internal/Magento/Framework/Setup/OldDbValidator.php
+++ b/lib/internal/Magento/Framework/Setup/OldDbValidator.php
@@ -13,7 +13,7 @@
/**
* Old Validator for database
*
- * Used in order to support backward compatability of modules that are installed
+ * Used in order to support backward compatibility of modules that are installed
* in old way (with Install/Upgrade Schema/Data scripts)
*/
class OldDbValidator implements UpToDateValidatorInterface
diff --git a/lib/internal/Magento/Framework/View/Element/AbstractBlock.php b/lib/internal/Magento/Framework/View/Element/AbstractBlock.php
index 335006555d2f1..6c4746d8218ea 100644
--- a/lib/internal/Magento/Framework/View/Element/AbstractBlock.php
+++ b/lib/internal/Magento/Framework/View/Element/AbstractBlock.php
@@ -3,9 +3,12 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Framework\View\Element;
+use Magento\Framework\Cache\LockGuardedCacheLoader;
use Magento\Framework\DataObject\IdentityInterface;
+use Magento\Framework\App\ObjectManager;
/**
* Base class for all blocks.
@@ -175,14 +178,23 @@ abstract class AbstractBlock extends \Magento\Framework\DataObject implements Bl
*/
protected $_cache;
+ /**
+ * @var LockGuardedCacheLoader
+ */
+ private $lockQuery;
+
/**
* Constructor
*
* @param \Magento\Framework\View\Element\Context $context
* @param array $data
+ * @param LockGuardedCacheLoader|null $lockQuery
*/
- public function __construct(\Magento\Framework\View\Element\Context $context, array $data = [])
- {
+ public function __construct(
+ \Magento\Framework\View\Element\Context $context,
+ array $data = [],
+ LockGuardedCacheLoader $lockQuery = null
+ ) {
$this->_request = $context->getRequest();
$this->_layout = $context->getLayout();
$this->_eventManager = $context->getEventManager();
@@ -204,6 +216,8 @@ public function __construct(\Magento\Framework\View\Element\Context $context, ar
$this->jsLayout = $data['jsLayout'];
unset($data['jsLayout']);
}
+ $this->lockQuery = $lockQuery
+ ?: ObjectManager::getInstance()->get(LockGuardedCacheLoader::class);
parent::__construct($data);
$this->_construct();
}
@@ -658,19 +672,6 @@ public function toHtml()
}
$html = $this->_loadCache();
- if ($html === false) {
- if ($this->hasData('translate_inline')) {
- $this->inlineTranslation->suspend($this->getData('translate_inline'));
- }
-
- $this->_beforeToHtml();
- $html = $this->_toHtml();
- $this->_saveCache($html);
-
- if ($this->hasData('translate_inline')) {
- $this->inlineTranslation->resume();
- }
- }
$html = $this->_afterToHtml($html);
/** @var \Magento\Framework\DataObject */
@@ -1083,23 +1084,54 @@ protected function getCacheLifetime()
/**
* Load block html from cache storage
*
- * @return string|false
+ * @return string
*/
protected function _loadCache()
{
+ $collectAction = function () {
+ if ($this->hasData('translate_inline')) {
+ $this->inlineTranslation->suspend($this->getData('translate_inline'));
+ }
+
+ $this->_beforeToHtml();
+ return $this->_toHtml();
+ };
+
if ($this->getCacheLifetime() === null || !$this->_cacheState->isEnabled(self::CACHE_GROUP)) {
- return false;
- }
- $cacheKey = $this->getCacheKey();
- $cacheData = $this->_cache->load($cacheKey);
- if ($cacheData) {
- $cacheData = str_replace(
- $this->_getSidPlaceholder($cacheKey),
- $this->_sidResolver->getSessionIdQueryParam($this->_session) . '=' . $this->_session->getSessionId(),
- $cacheData
- );
+ $html = $collectAction();
+ if ($this->hasData('translate_inline')) {
+ $this->inlineTranslation->resume();
+ }
+ return $html;
}
- return $cacheData;
+ $loadAction = function () {
+ $cacheKey = $this->getCacheKey();
+ $cacheData = $this->_cache->load($cacheKey);
+ if ($cacheData) {
+ $cacheData = str_replace(
+ $this->_getSidPlaceholder($cacheKey),
+ $this->_sidResolver->getSessionIdQueryParam($this->_session)
+ . '='
+ . $this->_session->getSessionId(),
+ $cacheData
+ );
+ }
+ return $cacheData;
+ };
+
+ $saveAction = function ($data) {
+ $this->_saveCache($data);
+ if ($this->hasData('translate_inline')) {
+ $this->inlineTranslation->resume();
+ }
+ };
+
+ return (string)$this->lockQuery->lockedLoadData(
+ $this->getCacheKey(),
+ $loadAction,
+ $collectAction,
+ $saveAction
+ );
}
/**
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php
index 5f7508438a6ed..dba775ea894f4 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php
@@ -6,6 +6,7 @@
namespace Magento\Framework\View\Test\Unit\Element;
+use Magento\Framework\Cache\LockGuardedCacheLoader;
use Magento\Framework\View\Element\AbstractBlock;
use Magento\Framework\View\Element\Context;
use Magento\Framework\Config\View;
@@ -13,7 +14,6 @@
use Magento\Framework\Event\ManagerInterface as EventManagerInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Cache\StateInterface as CacheStateInterface;
-use Magento\Framework\App\CacheInterface;
use Magento\Framework\Session\SidResolverInterface;
use Magento\Framework\Session\SessionManagerInterface;
@@ -42,11 +42,6 @@ class AbstractBlockTest extends \PHPUnit\Framework\TestCase
*/
private $cacheStateMock;
- /**
- * @var CacheInterface|\PHPUnit_Framework_MockObject_MockObject
- */
- private $cacheMock;
-
/**
* @var SidResolverInterface|\PHPUnit_Framework_MockObject_MockObject
*/
@@ -57,6 +52,11 @@ class AbstractBlockTest extends \PHPUnit\Framework\TestCase
*/
private $sessionMock;
+ /**
+ * @var LockGuardedCacheLoader|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $lockQuery;
+
/**
* @return void
*/
@@ -65,7 +65,10 @@ protected function setUp()
$this->eventManagerMock = $this->getMockForAbstractClass(EventManagerInterface::class);
$this->scopeConfigMock = $this->getMockForAbstractClass(ScopeConfigInterface::class);
$this->cacheStateMock = $this->getMockForAbstractClass(CacheStateInterface::class);
- $this->cacheMock = $this->getMockForAbstractClass(CacheInterface::class);
+ $this->lockQuery = $this->getMockBuilder(LockGuardedCacheLoader::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['lockedLoadData'])
+ ->getMockForAbstractClass();
$this->sidResolverMock = $this->getMockForAbstractClass(SidResolverInterface::class);
$this->sessionMock = $this->getMockForAbstractClass(SessionManagerInterface::class);
$contextMock = $this->createMock(Context::class);
@@ -78,9 +81,6 @@ protected function setUp()
$contextMock->expects($this->once())
->method('getCacheState')
->willReturn($this->cacheStateMock);
- $contextMock->expects($this->once())
- ->method('getCache')
- ->willReturn($this->cacheMock);
$contextMock->expects($this->once())
->method('getSidResolver')
->willReturn($this->sidResolverMock);
@@ -89,7 +89,11 @@ protected function setUp()
->willReturn($this->sessionMock);
$this->block = $this->getMockForAbstractClass(
AbstractBlock::class,
- ['context' => $contextMock]
+ [
+ 'context' => $contextMock,
+ 'data' => [],
+ 'lockQuery' => $this->lockQuery
+ ]
);
}
@@ -219,10 +223,7 @@ public function testToHtmlWhenModuleIsDisabled()
/**
* @param string|bool $cacheLifetime
* @param string|bool $dataFromCache
- * @param string $dataForSaveCache
* @param \PHPUnit\Framework\MockObject\Matcher\InvokedCount $expectsDispatchEvent
- * @param \PHPUnit\Framework\MockObject\Matcher\InvokedCount $expectsCacheLoad
- * @param \PHPUnit\Framework\MockObject\Matcher\InvokedCount $expectsCacheSave
* @param string $expectedResult
* @return void
* @dataProvider getCacheLifetimeDataProvider
@@ -230,10 +231,7 @@ public function testToHtmlWhenModuleIsDisabled()
public function testGetCacheLifetimeViaToHtml(
$cacheLifetime,
$dataFromCache,
- $dataForSaveCache,
$expectsDispatchEvent,
- $expectsCacheLoad,
- $expectsCacheSave,
$expectedResult
) {
$moduleName = 'Test';
@@ -252,13 +250,9 @@ public function testGetCacheLifetimeViaToHtml(
->method('isEnabled')
->with(AbstractBlock::CACHE_GROUP)
->willReturn(true);
- $this->cacheMock->expects($expectsCacheLoad)
- ->method('load')
- ->with(AbstractBlock::CACHE_KEY_PREFIX . $cacheKey)
+ $this->lockQuery->expects($this->any())
+ ->method('lockedLoadData')
->willReturn($dataFromCache);
- $this->cacheMock->expects($expectsCacheSave)
- ->method('save')
- ->with($dataForSaveCache, AbstractBlock::CACHE_KEY_PREFIX . $cacheKey);
$this->sidResolverMock->expects($this->any())
->method('getSessionIdQueryParam')
->with($this->sessionMock)
@@ -279,46 +273,31 @@ public function getCacheLifetimeDataProvider()
[
'cacheLifetime' => null,
'dataFromCache' => 'dataFromCache',
- 'dataForSaveCache' => '',
'expectsDispatchEvent' => $this->exactly(2),
- 'expectsCacheLoad' => $this->never(),
- 'expectsCacheSave' => $this->never(),
'expectedResult' => '',
],
[
'cacheLifetime' => false,
'dataFromCache' => 'dataFromCache',
- 'dataForSaveCache' => '',
'expectsDispatchEvent' => $this->exactly(2),
- 'expectsCacheLoad' => $this->never(),
- 'expectsCacheSave' => $this->never(),
'expectedResult' => '',
],
[
'cacheLifetime' => 120,
'dataFromCache' => 'dataFromCache',
- 'dataForSaveCache' => '',
'expectsDispatchEvent' => $this->exactly(2),
- 'expectsCacheLoad' => $this->once(),
- 'expectsCacheSave' => $this->never(),
'expectedResult' => 'dataFromCache',
],
[
'cacheLifetime' => '120string',
'dataFromCache' => 'dataFromCache',
- 'dataForSaveCache' => '',
'expectsDispatchEvent' => $this->exactly(2),
- 'expectsCacheLoad' => $this->once(),
- 'expectsCacheSave' => $this->never(),
'expectedResult' => 'dataFromCache',
],
[
'cacheLifetime' => 120,
'dataFromCache' => false,
- 'dataForSaveCache' => '',
'expectsDispatchEvent' => $this->exactly(2),
- 'expectsCacheLoad' => $this->once(),
- 'expectsCacheSave' => $this->once(),
'expectedResult' => '',
],
];
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/LinkTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/LinkTest.php
index b911a38dbb488..4c76087bfea12 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/LinkTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/LinkTest.php
@@ -3,10 +3,18 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Framework\View\Test\Unit\Element\Html;
class LinkTest extends \PHPUnit\Framework\TestCase
{
+ private $objectManager;
+
+ protected function setUp()
+ {
+ $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+ }
+
/**
* @var array
*/
@@ -24,24 +32,8 @@ class LinkTest extends \PHPUnit\Framework\TestCase
*/
protected $link;
- /**
- * @param \Magento\Framework\View\Element\Html\Link $link
- * @param string $expected
- *
- * @dataProvider getLinkAttributesDataProvider
- */
- public function testGetLinkAttributes($link, $expected)
- {
- $this->assertEquals($expected, $link->getLinkAttributes());
- }
-
- /**
- * @return array
- */
- public function getLinkAttributesDataProvider()
+ public function testGetLinkAttributes()
{
- $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
-
$escaperMock = $this->getMockBuilder(\Magento\Framework\Escaper::class)
->setMethods(['escapeHtml'])->disableOriginalConstructor()->getMock();
@@ -54,13 +46,19 @@ public function getLinkAttributesDataProvider()
$urlBuilderMock->expects($this->any())
->method('getUrl')
- ->will($this->returnArgument('http://site.com/link.html'));
+ ->willReturn('http://site.com/link.html');
$validtorMock = $this->getMockBuilder(\Magento\Framework\View\Element\Template\File\Validator::class)
->setMethods(['isValid'])->disableOriginalConstructor()->getMock();
+ $validtorMock->expects($this->any())
+ ->method('isValid')
+ ->willReturn(false);
$scopeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config::class)
->setMethods(['isSetFlag'])->disableOriginalConstructor()->getMock();
+ $scopeConfigMock->expects($this->any())
+ ->method('isSetFlag')
+ ->willReturn(true);
$resolverMock = $this->getMockBuilder(\Magento\Framework\View\Element\Template\File\Resolver::class)
->setMethods([])->disableOriginalConstructor()->getMock();
@@ -72,48 +70,48 @@ public function getLinkAttributesDataProvider()
$contextMock->expects($this->any())
->method('getValidator')
- ->will($this->returnValue($validtorMock));
+ ->willReturn($validtorMock);
$contextMock->expects($this->any())
->method('getResolver')
- ->will($this->returnValue($resolverMock));
+ ->willReturn($resolverMock);
$contextMock->expects($this->any())
->method('getEscaper')
- ->will($this->returnValue($escaperMock));
+ ->willReturn($escaperMock);
$contextMock->expects($this->any())
->method('getUrlBuilder')
- ->will($this->returnValue($urlBuilderMock));
+ ->willReturn($urlBuilderMock);
$contextMock->expects($this->any())
->method('getScopeConfig')
- ->will($this->returnValue($scopeConfigMock));
+ ->willReturn($scopeConfigMock);
/** @var \Magento\Framework\View\Element\Html\Link $linkWithAttributes */
- $linkWithAttributes = $objectManagerHelper->getObject(
+ $linkWithAttributes = $this->objectManager->getObject(
\Magento\Framework\View\Element\Html\Link::class,
['context' => $contextMock]
);
+
+ $this->assertEquals(
+ 'href="http://site.com/link.html"',
+ $linkWithAttributes->getLinkAttributes()
+ );
+
/** @var \Magento\Framework\View\Element\Html\Link $linkWithoutAttributes */
- $linkWithoutAttributes = $objectManagerHelper->getObject(
+ $linkWithoutAttributes = $this->objectManager->getObject(
\Magento\Framework\View\Element\Html\Link::class,
['context' => $contextMock]
);
-
foreach ($this->allowedAttributes as $attribute) {
- $linkWithAttributes->setDataUsingMethod($attribute, $attribute);
+ $linkWithoutAttributes->setDataUsingMethod($attribute, $attribute);
}
- return [
- 'full' => [
- 'link' => $linkWithAttributes,
- 'expected' => 'shape="shape" tabindex="tabindex" onfocus="onfocus" onblur="onblur" id="id"',
- ],
- 'empty' => [
- 'link' => $linkWithoutAttributes,
- 'expected' => '',
- ],
- ];
+ $this->assertEquals(
+ 'href="http://site.com/link.html" shape="shape" tabindex="tabindex"'
+ . ' onfocus="onfocus" onblur="onblur" id="id"',
+ $linkWithoutAttributes->getLinkAttributes()
+ );
}
}
diff --git a/lib/web/css/source/lib/_resets.less b/lib/web/css/source/lib/_resets.less
index 4499c314ce6ca..08d16842b849c 100644
--- a/lib/web/css/source/lib/_resets.less
+++ b/lib/web/css/source/lib/_resets.less
@@ -105,13 +105,6 @@
.lib-css(box-shadow, @focus__box-shadow);
}
}
-
- input[type="radio"],
- input[type="checkbox"] {
- &:focus {
- box-shadow: none;
- }
- }
}
//
diff --git a/lib/web/mage/adminhtml/globals.js b/lib/web/mage/adminhtml/globals.js
index 12c97fdfcd2c5..683606e576497 100644
--- a/lib/web/mage/adminhtml/globals.js
+++ b/lib/web/mage/adminhtml/globals.js
@@ -12,7 +12,7 @@ define([
/**
* Set of a temporary methods used to provide
- * backward compatability with a legacy code.
+ * backward compatibility with a legacy code.
*/
window.setLocation = function (url) {
window.location.href = url;
diff --git a/lib/web/mage/backend/floating-header.js b/lib/web/mage/backend/floating-header.js
index 06861277559a4..a6f767259488a 100644
--- a/lib/web/mage/backend/floating-header.js
+++ b/lib/web/mage/backend/floating-header.js
@@ -48,6 +48,7 @@ define([
this.element.wrapInner($('', {
'class': 'page-actions-inner', 'data-title': title
}));
+ this.element.removeClass('floating-header');
},
/**
diff --git a/lib/web/mage/tabs.js b/lib/web/mage/tabs.js
index b441477ab8d8a..65c452d33bf12 100644
--- a/lib/web/mage/tabs.js
+++ b/lib/web/mage/tabs.js
@@ -72,7 +72,7 @@ define([
if (anchor && isValid) {
$.each(self.contents, function (i) {
- if ($(this).attr('id') === anchorId) {
+ if ($(this).attr('id') === anchorId || $(this).find('#' + anchorId).length) {
self.collapsibles.not(self.collapsibles.eq(i)).collapsible('forceDeactivate');
return false;
diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx
index 765d0a616f77c..0e1860405e946 100644
--- a/setup/performance-toolkit/benchmark.jmx
+++ b/setup/performance-toolkit/benchmark.jmx
@@ -27267,843 +27267,6 @@ if (testLabel
mpaf/tool/fragments/_system/thread_group.jmx
-
- 1
- false
- 1
- ${productGridMassActionPercentage}
- mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx
-
-
-
-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());
-}
-
- javascript
- mpaf/tool/fragments/_system/setup_label.jmx
-
-
-
- vars.put("testLabel", "Product Grid Mass Actions");
-
- true
-
-
-
-
-
- function getFormKeyFromResponse()
- {
- var url = prev.getUrlAsString(),
- responseCode = prev.getResponseCode(),
- formKey = null;
- searchPattern = /var FORM_KEY = '(.+)'/;
- if (responseCode == "200" && url) {
- response = prev.getResponseDataAsString();
- formKey = response && response.match(searchPattern) ? response.match(searchPattern)[1] : null;
- }
- return formKey;
- }
-
- formKey = vars.get("form_key_storage");
-
- currentFormKey = getFormKeyFromResponse();
-
- if (currentFormKey != null && currentFormKey != formKey) {
- vars.put("form_key_storage", currentFormKey);
- }
-
- javascript
- mpaf/tool/fragments/ce/admin/handle_admin_form_key.jmx
-
-
-
- formKey = vars.get("form_key_storage");
- if (formKey
- && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy'
- && sampler.getMethod() == "POST")
- {
- arguments = sampler.getArguments();
- for (i=0; i<arguments.getArgumentCount(); i++)
- {
- argument = arguments.getArgument(i);
- if (argument.getName() == 'form_key' && argument.getValue() != formKey) {
- log.info("admin form key updated: " + argument.getValue() + " => " + formKey);
- argument.setValue(formKey);
- }
- }
- }
-
- javascript
-
-
-
-
-
- false
- mpaf/tool/fragments/ce/http_cookie_manager_without_clear_each_iteration.jmx
-
-
-
- mpaf/tool/fragments/ce/simple_controller.jmx
-
-
-
- get-admin-email
- mpaf/tool/fragments/ce/lock_controller.jmx
-
-
-
- mpaf/tool/fragments/ce/get_admin_email.jmx
-
-adminUserList = props.get("adminUserList");
-adminUserListIterator = props.get("adminUserListIterator");
-adminUsersDistribution = Integer.parseInt(vars.get("admin_users_distribution_per_admin_pool"));
-
-if (adminUsersDistribution == 1) {
- adminUser = adminUserList.poll();
-} else {
- if (!adminUserListIterator.hasNext()) {
- adminUserListIterator = adminUserList.descendingIterator();
- }
-
- adminUser = adminUserListIterator.next();
-}
-
-if (adminUser == null) {
- SampleResult.setResponseMessage("adminUser list is empty");
- SampleResult.setResponseData("adminUser list is empty","UTF-8");
- IsSuccess=false;
- SampleResult.setSuccessful(false);
- SampleResult.setStopThread(true);
-}
-vars.put("admin_user", adminUser);
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
- 60000
- 200000
- ${request_protocol}
-
- ${base_path}${admin_path}/admin/
- GET
- true
- false
- true
- false
- false
-
- mpaf/tool/fragments/ce/admin_login/admin_login.jmx
-
-
-
- Welcome
- <title>Magento Admin</title>
-
- Assertion.response_data
- false
- 2
-
-
-
- false
- admin_form_key
- <input name="form_key" type="hidden" value="([^'"]+)" />
- $1$
-
- 1
-
-
-
-
- ^.+$
-
- Assertion.response_data
- false
- 1
- variable
- admin_form_key
-
-
-
-
-
-
-
-
- true
-
- =
- true
- dummy
-
-
- true
- ${admin_form_key}
- =
- true
- form_key
-
-
- true
- ${admin_password}
- =
- true
- login[password]
-
-
- true
- ${admin_user}
- =
- true
- login[username]
-
-
-
-
-
- 60000
- 200000
- ${request_protocol}
-
- ${base_path}${admin_path}/admin/dashboard/
- POST
- true
- false
- true
- false
- Java
- false
-
- mpaf/tool/fragments/ce/admin_login/admin_login_submit_form.jmx
-
-
-
- false
- admin_form_key
- <input name="form_key" type="hidden" value="([^'"]+)" />
- $1$
-
- 1
- mpaf/tool/fragments/ce/admin_login/admin_retrieve_form_key.jmx
-
-
-
-
-
- mpaf/tool/fragments/ce/simple_controller.jmx
-
-
-
-
-
-
- true
- ${admin_form_key}
- =
- true
- form_key
-
-
- true
- product_listing
- =
- true
- namespace
- true
-
-
- true
-
- =
- true
- search
- true
-
-
- true
- true
- =
- true
- filters[placeholder]
- true
-
-
- true
- 20
- =
- true
- paging[pageSize]
- true
-
-
- true
- 1
- =
- true
- paging[current]
- true
-
-
- true
- entity_id
- =
- true
- sorting[field]
- true
-
-
- true
- asc
- =
- true
- sorting[direction]
- true
-
-
- true
- true
- =
- true
- isAjax
- true
-
-
-
-
-
- 60000
- 200000
- ${request_protocol}
-
- ${base_path}${admin_path}/mui/index/render/
- GET
- true
- false
- true
- false
- false
-
- mpaf/tool/fragments/ce/admin_browse_products_grid/get_product_pages_count.jmx
-
-
- $.totalRecords
- 0
- true
- false
- true
-
-
-
- products_number
- $.totalRecords
-
-
- BODY
-
-
-
- false
-
-
- var productsPageSize = Integer.parseInt(vars.get("products_page_size"));
-var productsTotal = Integer.parseInt(vars.get("products_number"));
-var pageCountProducts = Math.round(productsTotal/productsPageSize);
-
-vars.put("pages_count_product", String.valueOf(pageCountProducts));
-
-
-
-
-
-
-import java.util.Random;
-Random random = new Random();
-if (${seedForRandom} > 0) {
-random.setSeed(${seedForRandom});
-}
-var productsPageSize = Integer.parseInt(vars.get("products_page_size"));
-var totalNumberOfPages = Integer.parseInt(vars.get("pages_count_product"));
-
-// Randomly select a page.
-var randomProductsPage = random.nextInt(totalNumberOfPages) + 1;
-
-// Get the first and last product id on that page.
-var lastProductIdOnPage = randomProductsPage * productsPageSize;
-var firstProductIdOnPage = lastProductIdOnPage - productsPageSize + 1;
-
-var randomProductId1 = Math.floor(random.nextInt(productsPageSize)) + firstProductIdOnPage;
-var randomProductId2 = Math.floor(random.nextInt(productsPageSize)) + firstProductIdOnPage;
-var randomProductId3 = Math.floor(random.nextInt(productsPageSize)) + firstProductIdOnPage;
-
-vars.put("page_number", String.valueOf(randomProductsPage));
-vars.put("productId1", String.valueOf(randomProductId1));
-vars.put("productId2", String.valueOf(randomProductId2));
-vars.put("productId3", String.valueOf(randomProductId3));
-
-var randomQuantity = random.nextInt(1000) + 1;
-var randomPrice = random.nextInt(500) + 10;
-var randomVisibility = random.nextInt(4) + 1;
-
-vars.put("quantity", String.valueOf(randomQuantity));
-vars.put("price", String.valueOf(randomPrice));
-vars.put("visibility", String.valueOf(randomVisibility));
-
-
-
- false
- mpaf/tool/fragments/ce/admin_browse_products_grid/products_grid_mass_actions/setup.jmx
-
-
-
-
-
-
- true
- ${admin_form_key}
- =
- true
- form_key
- true
-
-
- true
- product_listing
- =
- true
- namespace
- true
-
-
- true
-
- =
- true
- search
- true
-
-
- true
- true
- =
- true
- filters[placeholder]
- true
-
-
- true
- ${products_page_size}
- =
- true
- paging[pageSize]
- true
-
-
- true
- ${page_number}
- =
- true
- paging[current]
- true
-
-
- true
- entity_id
- =
- true
- sorting[field]
- true
-
-
- true
- asc
- =
- true
- sorting[direction]
- true
-
-
- true
- true
- =
- true
- isAjax
- true
-
-
-
-
-
- 60000
- 200000
- ${request_protocol}
-
- ${base_path}${admin_path}/mui/index/render/
- GET
- true
- false
- true
- false
- false
-
- mpaf/tool/fragments/ce/admin_browse_products_grid/products_grid_mass_actions/display_grid.jmx
-
-
-
- totalRecords
-
- Assertion.response_data
- false
- 2
-
-
-
-
-
-
-
-
- true
- ${productId1}
- =
- true
- selected[0]
-
-
- true
- ${productId2}
- =
- true
- selected[1]
-
-
- true
- ${productId3}
- =
- true
- selected[2]
- true
-
-
- true
- true
- =
- true
- filters[placeholder]
- false
-
-
- true
- ${admin_form_key}
- =
- true
- form_key
- false
-
-
- true
- product_listing
- =
- true
- namespace
- false
-
-
-
-
-
- 60000
- 200000
- ${request_protocol}
-
- ${base_path}${admin_path}/catalog/product_action_attribute/edit
- GET
- true
- false
- true
- false
- false
-
- mpaf/tool/fragments/ce/admin_browse_products_grid/products_grid_mass_actions/display_update_attributes.jmx
-
-
-
- Update Attributes
-
- Assertion.response_data
- false
- 2
-
-
-
-
-
-
-
-
- true
- true
- =
- true
- isAjax
- true
-
-
- true
- ${admin_form_key}
- =
- true
- form_key
- true
-
-
- true
- 1
- =
- true
- product[product_has_weight]
- true
-
-
- true
- 1
- =
- true
- product[use_config_gift_message_available]
- true
-
-
- true
- 1
- =
- true
- product[use_config_gift_wrapping_available]
- true
-
-
- true
- ${quantity}
- =
- true
- inventory[qty]
- true
-
-
- true
- ${price}
- =
- true
- attributes[price]
-
-
- true
- ${visibility}
- =
- true
- attributes[visibility]
-
-
-
-
-
- 60000
- 200000
- ${request_protocol}
-
- ${base_path}${admin_path}/catalog/product_action_attribute/validate
- POST
- true
- false
- true
- false
- false
-
- mpaf/tool/fragments/ce/admin_browse_products_grid/products_grid_mass_actions/change_attributes.jmx
-
-
-
- {"error":false}
-
- Assertion.response_data
- false
- 2
-
-
-
-
-
-
-
- true
- true
- =
- true
- isAjax
- false
-
-
- true
- ${admin_form_key}
- =
- true
- form_key
- false
-
-
- true
- 1
- =
- true
- product[product_has_weight]
- true
-
-
- true
- 1
- =
- true
- product[use_config_gift_message_available]
-
-
- true
- 1
- =
- true
- product[use_config_gift_wrapping_available]
- true
-
-
- true
- ${quantity}
- =
- true
- inventory[qty]
-
-
- true
- on
- =
- true
- toggle_price
- true
-
-
- true
- ${price}
- =
- true
- attributes[price]
-
-
- true
- on
- =
- true
- toggle_price
- true
-
-
- true
- ${visibility}
- =
- true
- attributes[visibility]
-
-
- true
- on
- =
- true
- toggle_visibility
- true
-
-
-
-
-
- 60000
- 200000
- ${request_protocol}
-
- ${base_path}${admin_path}/catalog/product_action_attribute/save/store/0/active_tab/attributes
- POST
- true
- false
- true
- true
- false
-
-
-
-
-
- were updated.
-
- Assertion.response_data
- false
- 2
-
-
-
-
-
-
-
-
-
-
-
- 60000
- 200000
- ${request_protocol}
-
- ${base_path}${admin_path}/admin/auth/logout/
- GET
- true
- false
- true
- false
- false
-
- mpaf/tool/fragments/ce/setup/admin_logout.jmx
-
-
-
- false
-
-
-
- adminUsersDistribution = Integer.parseInt(vars.get("admin_users_distribution_per_admin_pool"));
- if (adminUsersDistribution == 1) {
- adminUserList = props.get("adminUserList");
- adminUserList.add(vars.get("admin_user"));
- }
-
- mpaf/tool/fragments/ce/common/return_admin_email_to_pool.jmx
-
-
-
-
-
1
false
diff --git a/setup/src/Magento/Setup/Controller/Session.php b/setup/src/Magento/Setup/Controller/Session.php
index e310dd485ace5..c9caa5a8de792 100644
--- a/setup/src/Magento/Setup/Controller/Session.php
+++ b/setup/src/Magento/Setup/Controller/Session.php
@@ -5,6 +5,9 @@
*/
namespace Magento\Setup\Controller;
+/**
+ * Sets up session for setup/index.php/session/prolong or redirects to error page
+ */
class Session extends \Zend\Mvc\Controller\AbstractActionController
{
/**
@@ -52,23 +55,28 @@ public function prolongAction()
try {
if ($this->serviceManager->get(\Magento\Framework\App\DeploymentConfig::class)->isAvailable()) {
$objectManager = $this->objectManagerProvider->get();
- /** @var \Magento\Framework\App\State $adminAppState */
- $adminAppState = $objectManager->get(\Magento\Framework\App\State::class);
- $adminAppState->setAreaCode(\Magento\Framework\App\Area::AREA_ADMINHTML);
- $sessionConfig = $objectManager->get(\Magento\Backend\Model\Session\AdminConfig::class);
- /** @var \Magento\Backend\Model\Url $backendUrl */
- $backendUrl = $objectManager->get(\Magento\Backend\Model\Url::class);
- $urlPath = parse_url($backendUrl->getBaseUrl(), PHP_URL_PATH);
- $cookiePath = $urlPath . 'setup';
- $sessionConfig->setCookiePath($cookiePath);
/* @var \Magento\Backend\Model\Auth\Session $session */
- $session = $objectManager->create(
- \Magento\Backend\Model\Auth\Session::class,
- [
- 'sessionConfig' => $sessionConfig,
- 'appState' => $adminAppState
- ]
- );
+ $session = $objectManager->get(\Magento\Backend\Model\Auth\Session::class);
+ // check if session was already set in \Magento\Setup\Mvc\Bootstrap\InitParamListener::authPreDispatch
+ if (!$session->isSessionExists()) {
+ /** @var \Magento\Framework\App\State $adminAppState */
+ $adminAppState = $objectManager->get(\Magento\Framework\App\State::class);
+ $adminAppState->setAreaCode(\Magento\Framework\App\Area::AREA_ADMINHTML);
+ $sessionConfig = $objectManager->get(\Magento\Backend\Model\Session\AdminConfig::class);
+ /** @var \Magento\Backend\Model\Url $backendUrl */
+ $backendUrl = $objectManager->get(\Magento\Backend\Model\Url::class);
+ $urlPath = parse_url($backendUrl->getBaseUrl(), PHP_URL_PATH);
+ $cookiePath = $urlPath . 'setup';
+ $sessionConfig->setCookiePath($cookiePath);
+ /* @var \Magento\Backend\Model\Auth\Session $session */
+ $session = $objectManager->create(
+ \Magento\Backend\Model\Auth\Session::class,
+ [
+ 'sessionConfig' => $sessionConfig,
+ 'appState' => $adminAppState
+ ]
+ );
+ }
$session->prolong();
return new \Zend\View\Model\JsonModel(['success' => true]);
}
@@ -78,6 +86,8 @@ public function prolongAction()
}
/**
+ * Unlogin action, return 401 error page
+ *
* @return \Zend\View\Model\ViewModel|\Zend\Http\Response
*/
public function unloginAction()
diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList.php b/setup/src/Magento/Setup/Model/ConfigOptionsList.php
index afe1a5d9e2591..3f2aedae1373c 100644
--- a/setup/src/Magento/Setup/Model/ConfigOptionsList.php
+++ b/setup/src/Magento/Setup/Model/ConfigOptionsList.php
@@ -50,7 +50,8 @@ class ConfigOptionsList implements ConfigOptionsListInterface
private $configOptionsListClasses = [
\Magento\Setup\Model\ConfigOptionsList\Session::class,
\Magento\Setup\Model\ConfigOptionsList\Cache::class,
- \Magento\Setup\Model\ConfigOptionsList\PageCache::class
+ \Magento\Setup\Model\ConfigOptionsList\PageCache::class,
+ \Magento\Setup\Model\ConfigOptionsList\Lock::class,
];
/**
diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList/Lock.php b/setup/src/Magento/Setup/Model/ConfigOptionsList/Lock.php
new file mode 100644
index 0000000000000..66f41128c46b1
--- /dev/null
+++ b/setup/src/Magento/Setup/Model/ConfigOptionsList/Lock.php
@@ -0,0 +1,342 @@
+ [
+ self::INPUT_KEY_LOCK_PROVIDER => self::CONFIG_PATH_LOCK_PROVIDER,
+ self::INPUT_KEY_LOCK_DB_PREFIX => self::CONFIG_PATH_LOCK_DB_PREFIX,
+ ],
+ LockBackendFactory::LOCK_ZOOKEEPER => [
+ self::INPUT_KEY_LOCK_PROVIDER => self::CONFIG_PATH_LOCK_PROVIDER,
+ self::INPUT_KEY_LOCK_ZOOKEEPER_HOST => self::CONFIG_PATH_LOCK_ZOOKEEPER_HOST,
+ self::INPUT_KEY_LOCK_ZOOKEEPER_PATH => self::CONFIG_PATH_LOCK_ZOOKEEPER_PATH,
+ ],
+ LockBackendFactory::LOCK_CACHE => [
+ self::INPUT_KEY_LOCK_PROVIDER => self::CONFIG_PATH_LOCK_PROVIDER,
+ ],
+ LockBackendFactory::LOCK_FILE => [
+ self::INPUT_KEY_LOCK_PROVIDER => self::CONFIG_PATH_LOCK_PROVIDER,
+ self::INPUT_KEY_LOCK_FILE_PATH => self::CONFIG_PATH_LOCK_FILE_PATH,
+ ],
+ ];
+
+ /**
+ * The list of default values
+ *
+ * @var array
+ */
+ private $defaultConfigValues = [
+ self::INPUT_KEY_LOCK_PROVIDER => LockBackendFactory::LOCK_DB,
+ self::INPUT_KEY_LOCK_DB_PREFIX => null,
+ self::INPUT_KEY_LOCK_ZOOKEEPER_PATH => ZookeeperLock::DEFAULT_PATH,
+ ];
+
+ /**
+ * @inheritdoc
+ */
+ public function getOptions()
+ {
+ return [
+ new SelectConfigOption(
+ self::INPUT_KEY_LOCK_PROVIDER,
+ SelectConfigOption::FRONTEND_WIZARD_SELECT,
+ $this->validLockProviders,
+ self::CONFIG_PATH_LOCK_PROVIDER,
+ 'Lock provider name',
+ LockBackendFactory::LOCK_DB
+ ),
+ new TextConfigOption(
+ self::INPUT_KEY_LOCK_DB_PREFIX,
+ TextConfigOption::FRONTEND_WIZARD_TEXT,
+ self::CONFIG_PATH_LOCK_DB_PREFIX,
+ 'Installation specific lock prefix to avoid lock conflicts'
+ ),
+ new TextConfigOption(
+ self::INPUT_KEY_LOCK_ZOOKEEPER_HOST,
+ TextConfigOption::FRONTEND_WIZARD_TEXT,
+ self::CONFIG_PATH_LOCK_ZOOKEEPER_HOST,
+ 'Host and port to connect to Zookeeper cluster. For example: 127.0.0.1:2181'
+ ),
+ new TextConfigOption(
+ self::INPUT_KEY_LOCK_ZOOKEEPER_PATH,
+ TextConfigOption::FRONTEND_WIZARD_TEXT,
+ self::CONFIG_PATH_LOCK_ZOOKEEPER_PATH,
+ 'The path where Zookeeper will save locks. The default path is: ' . ZookeeperLock::DEFAULT_PATH
+ ),
+ new TextConfigOption(
+ self::INPUT_KEY_LOCK_FILE_PATH,
+ TextConfigOption::FRONTEND_WIZARD_TEXT,
+ self::CONFIG_PATH_LOCK_FILE_PATH,
+ 'The path where file locks will be saved.'
+ ),
+ ];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function createConfig(array $options, DeploymentConfig $deploymentConfig)
+ {
+ $configData = new ConfigData(ConfigFilePool::APP_ENV);
+ $configData->setOverrideWhenSave(true);
+ $lockProvider = $this->getLockProvider($options, $deploymentConfig);
+
+ $this->setDefaultConfiguration($configData, $deploymentConfig, $lockProvider);
+
+ foreach ($this->mappingInputKeyToConfigPath[$lockProvider] as $input => $path) {
+ if (isset($options[$input])) {
+ $configData->set($path, $options[$input]);
+ }
+ }
+
+ return $configData;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function validate(array $options, DeploymentConfig $deploymentConfig)
+ {
+ $lockProvider = $this->getLockProvider($options, $deploymentConfig);
+ switch ($lockProvider) {
+ case LockBackendFactory::LOCK_ZOOKEEPER:
+ $errors = $this->validateZookeeperConfig($options, $deploymentConfig);
+ break;
+ case LockBackendFactory::LOCK_FILE:
+ $errors = $this->validateFileConfig($options, $deploymentConfig);
+ break;
+ case LockBackendFactory::LOCK_CACHE:
+ case LockBackendFactory::LOCK_DB:
+ $errors = [];
+ break;
+ default:
+ $errors[] = 'The lock provider ' . $lockProvider . ' does not exist.';
+ }
+
+ return $errors;
+ }
+
+ /**
+ * Validates File locks configuration
+ *
+ * @param array $options
+ * @param DeploymentConfig $deploymentConfig
+ * @return array
+ */
+ private function validateFileConfig(array $options, DeploymentConfig $deploymentConfig): array
+ {
+ $errors = [];
+
+ $path = $options[self::INPUT_KEY_LOCK_FILE_PATH]
+ ?? $deploymentConfig->get(
+ self::CONFIG_PATH_LOCK_FILE_PATH,
+ $this->getDefaultValue(self::INPUT_KEY_LOCK_FILE_PATH)
+ );
+
+ if (!$path) {
+ $errors[] = 'The path needs to be a non-empty string.';
+ }
+
+ return $errors;
+ }
+
+ /**
+ * Validates Zookeeper configuration
+ *
+ * @param array $options
+ * @param DeploymentConfig $deploymentConfig
+ * @return array
+ */
+ private function validateZookeeperConfig(array $options, DeploymentConfig $deploymentConfig): array
+ {
+ $errors = [];
+
+ if (!extension_loaded(LockBackendFactory::LOCK_ZOOKEEPER)) {
+ $errors[] = 'php extension Zookeeper is not installed.';
+ }
+
+ $host = $options[self::INPUT_KEY_LOCK_ZOOKEEPER_HOST]
+ ?? $deploymentConfig->get(
+ self::CONFIG_PATH_LOCK_ZOOKEEPER_HOST,
+ $this->getDefaultValue(self::INPUT_KEY_LOCK_ZOOKEEPER_HOST)
+ );
+ $path = $options[self::INPUT_KEY_LOCK_ZOOKEEPER_PATH]
+ ?? $deploymentConfig->get(
+ self::CONFIG_PATH_LOCK_ZOOKEEPER_PATH,
+ $this->getDefaultValue(self::INPUT_KEY_LOCK_ZOOKEEPER_PATH)
+ );
+
+ if (!$path) {
+ $errors[] = 'Zookeeper path needs to be a non-empty string.';
+ }
+
+ if (!$host) {
+ $errors[] = 'Zookeeper host is should be set.';
+ }
+
+ return $errors;
+ }
+
+ /**
+ * Returns the name of lock provider
+ *
+ * @param array $options
+ * @param DeploymentConfig $deploymentConfig
+ * @return string
+ */
+ private function getLockProvider(array $options, DeploymentConfig $deploymentConfig): string
+ {
+ if (!isset($options[self::INPUT_KEY_LOCK_PROVIDER])) {
+ return (string) $deploymentConfig->get(
+ self::CONFIG_PATH_LOCK_PROVIDER,
+ $this->getDefaultValue(self::INPUT_KEY_LOCK_PROVIDER)
+ );
+ }
+
+ return (string) $options[self::INPUT_KEY_LOCK_PROVIDER];
+ }
+
+ /**
+ * Sets default configuration for locks
+ *
+ * @param ConfigData $configData
+ * @param DeploymentConfig $deploymentConfig
+ * @param string $lockProvider
+ * @return ConfigData
+ */
+ private function setDefaultConfiguration(
+ ConfigData $configData,
+ DeploymentConfig $deploymentConfig,
+ string $lockProvider
+ ) {
+ foreach ($this->mappingInputKeyToConfigPath[$lockProvider] as $input => $path) {
+ $configData->set($path, $deploymentConfig->get($path, $this->getDefaultValue($input)));
+ }
+
+ return $configData;
+ }
+
+ /**
+ * Returns default value by input key
+ *
+ * If default value is not set returns null
+ *
+ * @param string $inputKey
+ * @return mixed|null
+ */
+ private function getDefaultValue(string $inputKey)
+ {
+ if (isset($this->defaultConfigValues[$inputKey])) {
+ return $this->defaultConfigValues[$inputKey];
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/setup/src/Magento/Setup/Test/Unit/Controller/SessionTest.php b/setup/src/Magento/Setup/Test/Unit/Controller/SessionTest.php
index f8e5e7cdc4d70..216013ebfc8d9 100644
--- a/setup/src/Magento/Setup/Test/Unit/Controller/SessionTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Controller/SessionTest.php
@@ -48,6 +48,12 @@ public function testUnloginAction()
$this->createPartialMock(\Magento\Framework\App\DeploymentConfig::class, ['isAvailable']);
$deployConfigMock->expects($this->once())->method('isAvailable')->will($this->returnValue(true));
+ $sessionMock = $this->createPartialMock(
+ \Magento\Backend\Model\Auth\Session::class,
+ ['prolong', 'isSessionExists']
+ );
+ $sessionMock->expects($this->once())->method('isSessionExists')->will($this->returnValue(false));
+
$stateMock = $this->createPartialMock(\Magento\Framework\App\State::class, ['setAreaCode']);
$stateMock->expects($this->once())->method('setAreaCode');
@@ -57,6 +63,7 @@ public function testUnloginAction()
$urlMock = $this->createMock(\Magento\Backend\Model\Url::class);
$returnValueMap = [
+ [\Magento\Backend\Model\Auth\Session::class, $sessionMock],
[\Magento\Framework\App\State::class, $stateMock],
[\Magento\Backend\Model\Session\AdminConfig::class, $sessionConfigMock],
[\Magento\Backend\Model\Url::class, $urlMock]
@@ -68,7 +75,6 @@ public function testUnloginAction()
->method('get')
->will($this->returnValueMap($returnValueMap));
- $sessionMock = $this->createPartialMock(\Magento\Backend\Model\Auth\Session::class, ['prolong']);
$this->objectManager->expects($this->once())
->method('create')
->will($this->returnValue($sessionMock));
@@ -87,4 +93,29 @@ public function testIndexAction()
$viewModel = $controller->unloginAction();
$this->assertInstanceOf(\Zend\View\Model\ViewModel::class, $viewModel);
}
+
+ /**
+ * @covers \Magento\Setup\Controller\SystemConfig::prolongAction
+ */
+ public function testProlongActionWithExistingSession()
+ {
+ $this->objectManagerProvider->expects($this->once())->method('get')->will(
+ $this->returnValue($this->objectManager)
+ );
+ $deployConfigMock =
+ $this->createPartialMock(\Magento\Framework\App\DeploymentConfig::class, ['isAvailable']);
+ $deployConfigMock->expects($this->once())->method('isAvailable')->will($this->returnValue(true));
+ $sessionMock = $this->createPartialMock(
+ \Magento\Backend\Model\Auth\Session::class,
+ ['prolong', 'isSessionExists']
+ );
+ $sessionMock->expects($this->once())->method('isSessionExists')->will($this->returnValue(true));
+
+ $this->serviceManager->expects($this->once())->method('get')->will($this->returnValue($deployConfigMock));
+ $this->objectManager->expects($this->once())
+ ->method('get')
+ ->will($this->returnValue($sessionMock));
+ $controller = new Session($this->serviceManager, $this->objectManagerProvider);
+ $this->assertEquals(new \Zend\View\Model\JsonModel(['success' => true]), $controller->prolongAction());
+ }
}
diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsList/LockTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsList/LockTest.php
new file mode 100644
index 0000000000000..1a46bddf5f21a
--- /dev/null
+++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsList/LockTest.php
@@ -0,0 +1,232 @@
+deploymentConfigMock = $this->createMock(DeploymentConfig::class);
+ $this->lockConfigOptionsList = new LockConfigOptionsList();
+ }
+
+ /**
+ * @return void
+ */
+ public function testGetOptions()
+ {
+ $options = $this->lockConfigOptionsList->getOptions();
+ $this->assertSame(5, count($options));
+
+ $this->assertArrayHasKey(0, $options);
+ $this->assertInstanceOf(SelectConfigOption::class, $options[0]);
+ $this->assertEquals(LockConfigOptionsList::INPUT_KEY_LOCK_PROVIDER, $options[0]->getName());
+
+ $this->assertArrayHasKey(1, $options);
+ $this->assertInstanceOf(TextConfigOption::class, $options[1]);
+ $this->assertEquals(LockConfigOptionsList::INPUT_KEY_LOCK_DB_PREFIX, $options[1]->getName());
+
+ $this->assertArrayHasKey(2, $options);
+ $this->assertInstanceOf(TextConfigOption::class, $options[2]);
+ $this->assertEquals(LockConfigOptionsList::INPUT_KEY_LOCK_ZOOKEEPER_HOST, $options[2]->getName());
+
+ $this->assertArrayHasKey(3, $options);
+ $this->assertInstanceOf(TextConfigOption::class, $options[3]);
+ $this->assertEquals(LockConfigOptionsList::INPUT_KEY_LOCK_ZOOKEEPER_PATH, $options[3]->getName());
+
+ $this->assertArrayHasKey(4, $options);
+ $this->assertInstanceOf(TextConfigOption::class, $options[4]);
+ $this->assertEquals(LockConfigOptionsList::INPUT_KEY_LOCK_FILE_PATH, $options[4]->getName());
+ }
+
+ /**
+ * @param array $options
+ * @param array $expectedResult
+ * @dataProvider createConfigDataProvider
+ */
+ public function testCreateConfig(array $options, array $expectedResult)
+ {
+ $this->deploymentConfigMock->expects($this->any())
+ ->method('get')
+ ->willReturnArgument(1);
+ $data = $this->lockConfigOptionsList->createConfig($options, $this->deploymentConfigMock);
+ $this->assertInstanceOf(ConfigData::class, $data);
+ $this->assertTrue($data->isOverrideWhenSave());
+ $this->assertSame($expectedResult, $data->getData());
+ }
+
+ /**
+ * @return array
+ */
+ public function createConfigDataProvider(): array
+ {
+ return [
+ 'Check default values' => [
+ 'options' => [],
+ 'expectedResult' => [
+ 'lock' => [
+ 'provider' => LockBackendFactory::LOCK_DB,
+ 'config' => [
+ 'prefix' => null,
+ ],
+ ],
+ ],
+ ],
+ 'Check default value for cache lock' => [
+ 'options' => [
+ LockConfigOptionsList::INPUT_KEY_LOCK_PROVIDER => LockBackendFactory::LOCK_CACHE,
+ ],
+ 'expectedResult' => [
+ 'lock' => [
+ 'provider' => LockBackendFactory::LOCK_CACHE,
+ ],
+ ],
+ ],
+ 'Check default value for zookeeper lock' => [
+ 'options' => [
+ LockConfigOptionsList::INPUT_KEY_LOCK_PROVIDER => LockBackendFactory::LOCK_ZOOKEEPER,
+ ],
+ 'expectedResult' => [
+ 'lock' => [
+ 'provider' => LockBackendFactory::LOCK_ZOOKEEPER,
+ 'config' => [
+ 'host' => null,
+ 'path' => ZookeeperLock::DEFAULT_PATH,
+ ],
+ ],
+ ],
+ ],
+ 'Check specific db lock options' => [
+ 'options' => [
+ LockConfigOptionsList::INPUT_KEY_LOCK_PROVIDER => LockBackendFactory::LOCK_DB,
+ LockConfigOptionsList::INPUT_KEY_LOCK_DB_PREFIX => 'my_prefix'
+ ],
+ 'expectedResult' => [
+ 'lock' => [
+ 'provider' => LockBackendFactory::LOCK_DB,
+ 'config' => [
+ 'prefix' => 'my_prefix',
+ ],
+ ],
+ ],
+ ],
+ 'Check specific zookeeper lock options' => [
+ 'options' => [
+ LockConfigOptionsList::INPUT_KEY_LOCK_PROVIDER => LockBackendFactory::LOCK_ZOOKEEPER,
+ LockConfigOptionsList::INPUT_KEY_LOCK_ZOOKEEPER_HOST => '123.45.67.89:10',
+ LockConfigOptionsList::INPUT_KEY_LOCK_ZOOKEEPER_PATH => '/some/path',
+ ],
+ 'expectedResult' => [
+ 'lock' => [
+ 'provider' => LockBackendFactory::LOCK_ZOOKEEPER,
+ 'config' => [
+ 'host' => '123.45.67.89:10',
+ 'path' => '/some/path',
+ ],
+ ],
+ ],
+ ],
+ 'Check specific file lock options' => [
+ 'options' => [
+ LockConfigOptionsList::INPUT_KEY_LOCK_PROVIDER => LockBackendFactory::LOCK_FILE,
+ LockConfigOptionsList::INPUT_KEY_LOCK_FILE_PATH => '/my/path'
+ ],
+ 'expectedResult' => [
+ 'lock' => [
+ 'provider' => LockBackendFactory::LOCK_FILE,
+ 'config' => [
+ 'path' => '/my/path',
+ ],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @param array $options
+ * @param array $expectedResult
+ * @dataProvider validateDataProvider
+ */
+ public function testValidate(array $options, array $expectedResult)
+ {
+ $this->deploymentConfigMock->expects($this->any())
+ ->method('get')
+ ->willReturnArgument(1);
+ $this->assertSame(
+ $expectedResult,
+ $this->lockConfigOptionsList->validate($options, $this->deploymentConfigMock)
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function validateDataProvider(): array
+ {
+ return [
+ 'Wrong lock provider' => [
+ 'options' => [
+ LockConfigOptionsList::INPUT_KEY_LOCK_PROVIDER => 'SomeProvider',
+ ],
+ 'expectedResult' => [
+ 'The lock provider SomeProvider does not exist.',
+ ],
+ ],
+ 'Empty host and path for Zookeeper' => [
+ 'options' => [
+ LockConfigOptionsList::INPUT_KEY_LOCK_PROVIDER => LockBackendFactory::LOCK_ZOOKEEPER,
+ LockConfigOptionsList::INPUT_KEY_LOCK_ZOOKEEPER_HOST => '',
+ LockConfigOptionsList::INPUT_KEY_LOCK_ZOOKEEPER_PATH => '',
+ ],
+ 'expectedResult' => extension_loaded('zookeeper')
+ ? [
+ 'Zookeeper path needs to be a non-empty string.',
+ 'Zookeeper host is should be set.',
+ ]
+ : [
+ 'php extension Zookeeper is not installed.',
+ 'Zookeeper path needs to be a non-empty string.',
+ 'Zookeeper host is should be set.',
+ ],
+ ],
+ 'Empty path for File lock' => [
+ 'options' => [
+ LockConfigOptionsList::INPUT_KEY_LOCK_PROVIDER => LockBackendFactory::LOCK_FILE,
+ LockConfigOptionsList::INPUT_KEY_LOCK_FILE_PATH => '',
+ ],
+ 'expectedResult' => [
+ 'The path needs to be a non-empty string.',
+ ],
+ ],
+ ];
+ }
+}
diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php
index d7f680309c9ef..a85b468cebc92 100644
--- a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php
@@ -7,6 +7,7 @@
namespace Magento\Setup\Test\Unit\Model;
use Magento\Framework\Config\ConfigOptionsListConstants;
+use Magento\Setup\Model\ConfigOptionsList\Lock;
use Magento\Setup\Model\ConfigGenerator;
use Magento\Setup\Model\ConfigOptionsList;
use Magento\Setup\Validator\DbValidator;
@@ -82,7 +83,7 @@ public function testCreateOptions()
$this->generator->expects($this->once())->method('createXFrameConfig')->willReturn($configDataMock);
$this->generator->expects($this->once())->method('createCacheHostsConfig')->willReturn($configDataMock);
- $configData = $this->object->createConfig([], $this->deploymentConfig);
+ $configData = $this->object->createConfig([Lock::INPUT_KEY_LOCK_PROVIDER => 'db'], $this->deploymentConfig);
$this->assertGreaterThanOrEqual(6, count($configData));
}
@@ -96,7 +97,7 @@ public function testCreateOptionsWithOptionalNull()
$this->generator->expects($this->once())->method('createXFrameConfig')->willReturn($configDataMock);
$this->generator->expects($this->once())->method('createCacheHostsConfig')->willReturn($configDataMock);
- $configData = $this->object->createConfig([], $this->deploymentConfig);
+ $configData = $this->object->createConfig([Lock::INPUT_KEY_LOCK_PROVIDER => 'db'], $this->deploymentConfig);
$this->assertGreaterThanOrEqual(6, count($configData));
}
@@ -109,7 +110,8 @@ public function testValidateSuccess()
ConfigOptionsListConstants::INPUT_KEY_DB_NAME => 'name',
ConfigOptionsListConstants::INPUT_KEY_DB_HOST => 'host',
ConfigOptionsListConstants::INPUT_KEY_DB_USER => 'user',
- ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD => 'pass'
+ ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD => 'pass',
+ Lock::INPUT_KEY_LOCK_PROVIDER => 'db'
];
$this->prepareValidationMocks();
@@ -127,7 +129,8 @@ public function testValidateInvalidSessionHandler()
ConfigOptionsListConstants::INPUT_KEY_DB_NAME => 'name',
ConfigOptionsListConstants::INPUT_KEY_DB_HOST => 'host',
ConfigOptionsListConstants::INPUT_KEY_DB_USER => 'user',
- ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD => 'pass'
+ ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD => 'pass',
+ Lock::INPUT_KEY_LOCK_PROVIDER => 'db'
];
$this->prepareValidationMocks();
@@ -141,7 +144,8 @@ public function testValidateEmptyEncryptionKey()
{
$options = [
ConfigOptionsListConstants::INPUT_KEY_SKIP_DB_VALIDATION => true,
- ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY => ''
+ ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY => '',
+ Lock::INPUT_KEY_LOCK_PROVIDER => 'db'
];
$this->assertEquals(
['Invalid encryption key. Encryption key must be 32 character string without any white space.'],
@@ -167,7 +171,8 @@ public function testValidateCacheHosts($hosts, $expectedError)
{
$options = [
ConfigOptionsListConstants::INPUT_KEY_SKIP_DB_VALIDATION => true,
- ConfigOptionsListConstants::INPUT_KEY_CACHE_HOSTS => $hosts
+ ConfigOptionsListConstants::INPUT_KEY_CACHE_HOSTS => $hosts,
+ Lock::INPUT_KEY_LOCK_PROVIDER => 'db'
];
$result = $this->object->validate($options, $this->deploymentConfig);
if ($expectedError) {
|