diff --git a/.github/workflows/smoke-test-daily.yml b/.github/workflows/smoke-test-daily.yml new file mode 100644 index 00000000000..ec5c39a9b2d --- /dev/null +++ b/.github/workflows/smoke-test-daily.yml @@ -0,0 +1,38 @@ +name: Smoke test daily +on: + schedule: + - cron: '3 25 * * *' +jobs: + login-run: + name: Log into smoke test site. + runs-on: ubuntu-18.04 + steps: + + - name: Create dirs. + run: | + mkdir -p code/woocommerce + mkdir -p package/woocommerce + mkdir -p tmp/woocommerce + mkdir -p node_modules + + - name: Checkout code. + uses: actions/checkout@v2 + with: + path: package/woocommerce + + - name: Run npm install. + working-directory: package/woocommerce + run: npm install + + - name: Move current directory to code. We will install zip file in this dir later. + run: mv ./package/woocommerce/* ./code/woocommerce + + - name: Run login test. + working-directory: code/woocommerce + env: + SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }} + SMOKE_TEST_ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }} + SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }} + SMOKE_TEST_CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }} + SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }} + run: npx wc-e2e test:e2e ./tests/e2e/specs/activate-and-setup/test-activation.js diff --git a/.github/workflows/stalebot.yml b/.github/workflows/stalebot.yml index b52a926ea49..7281ba580e3 100644 --- a/.github/workflows/stalebot.yml +++ b/.github/workflows/stalebot.yml @@ -1,7 +1,7 @@ name: 'Close stale needs-feedback issues' on: schedule: - - cron: '0 21 * * *' + - cron: '21 0 * * *' jobs: stale: @@ -17,4 +17,5 @@ jobs: days-before-pr-close: -1 only-issue-labels: 'needs feedback' close-issue-label: "category: can't reproduce" + ascending: true debug-only: true diff --git a/.gitignore b/.gitignore index d5584c21452..106818c04f8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ project.properties .settings* .idea .vscode +.eslintcache *.sublime-project *.sublime-workspace .sublimelinterrc diff --git a/bin/composer/mozart/composer.lock b/bin/composer/mozart/composer.lock index 1a6fcb7090b..6e9a52a1179 100644 --- a/bin/composer/mozart/composer.lock +++ b/bin/composer/mozart/composer.lock @@ -33,6 +33,7 @@ "squizlabs/php_codesniffer": "^3.5", "vimeo/psalm": "^4.4" }, + "default-branch": true, "bin": [ "bin/mozart" ], @@ -53,6 +54,10 @@ } ], "description": "Composes all dependencies as a package inside a WordPress plugin", + "support": { + "issues": "https://github.com/coenjacobs/mozart/issues", + "source": "https://github.com/coenjacobs/mozart/tree/master" + }, "funding": [ { "url": "https://github.com/coenjacobs", @@ -144,6 +149,10 @@ "sftp", "storage" ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/1.x" + }, "funding": [ { "url": "https://offset.earth/frankdejonge", @@ -192,6 +201,10 @@ } ], "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.7.0" + }, "funding": [ { "url": "https://github.com/frankdejonge", @@ -246,20 +259,24 @@ "container-interop", "psr" ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" + }, "time": "2021-03-05T17:36:06+00:00" }, { "name": "symfony/console", - "version": "v5.2.4", + "version": "v5.2.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "d6d0cc30d8c0fda4e7b213c20509b0159a8f4556" + "reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/d6d0cc30d8c0fda4e7b213c20509b0159a8f4556", - "reference": "d6d0cc30d8c0fda4e7b213c20509b0159a8f4556", + "url": "https://api.github.com/repos/symfony/console/zipball/35f039df40a3b335ebf310f244cb242b3a83ac8d", + "reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d", "shasum": "" }, "require": { @@ -326,6 +343,9 @@ "console", "terminal" ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.2.6" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -340,7 +360,7 @@ "type": "tidelift" } ], - "time": "2021-02-23T10:08:49+00:00" + "time": "2021-03-28T09:42:18+00:00" }, { "name": "symfony/finder", @@ -384,6 +404,9 @@ ], "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.2.4" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -460,6 +483,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -538,6 +564,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -619,6 +648,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -696,6 +728,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -772,6 +807,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -852,6 +890,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -928,6 +969,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/master" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -946,16 +990,16 @@ }, { "name": "symfony/string", - "version": "v5.2.4", + "version": "v5.2.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "4e78d7d47061fa183639927ec40d607973699609" + "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/4e78d7d47061fa183639927ec40d607973699609", - "reference": "4e78d7d47061fa183639927ec40d607973699609", + "url": "https://api.github.com/repos/symfony/string/zipball/ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", + "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", "shasum": "" }, "require": { @@ -1008,6 +1052,9 @@ "utf-8", "utf8" ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.2.6" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1022,7 +1069,7 @@ "type": "tidelift" } ], - "time": "2021-02-16T10:20:28+00:00" + "time": "2021-03-17T17:12:15+00:00" } ], "aliases": [], @@ -1037,5 +1084,5 @@ "platform-overrides": { "php": "7.3" }, - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/bin/composer/phpcs/composer.lock b/bin/composer/phpcs/composer.lock index 10aedae9334..d784a60a0a0 100644 --- a/bin/composer/phpcs/composer.lock +++ b/bin/composer/phpcs/composer.lock @@ -71,6 +71,10 @@ "stylecheck", "tests" ], + "support": { + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + }, "time": "2020-06-25T14:57:39+00:00" }, { @@ -129,6 +133,10 @@ "phpcs", "standards" ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibility" + }, "time": "2019-12-27T09:44:58+00:00" }, { @@ -181,6 +189,10 @@ "polyfill", "standards" ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" + }, "time": "2021-02-15T10:24:51+00:00" }, { @@ -231,6 +243,10 @@ "standards", "wordpress" ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" + }, "time": "2019-08-28T14:22:28+00:00" }, { @@ -282,6 +298,11 @@ "phpcs", "standards" ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, "time": "2020-10-23T02:01:07+00:00" }, { @@ -322,6 +343,10 @@ "woocommerce", "wordpress" ], + "support": { + "issues": "https://github.com/woocommerce/woocommerce-sniffs/issues", + "source": "https://github.com/woocommerce/woocommerce-sniffs/tree/master" + }, "time": "2020-08-06T18:23:45+00:00" }, { @@ -368,6 +393,11 @@ "standards", "wordpress" ], + "support": { + "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues", + "source": "https://github.com/WordPress/WordPress-Coding-Standards", + "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" + }, "time": "2020-05-13T23:57:56+00:00" } ], @@ -381,5 +411,5 @@ "platform-overrides": { "php": "7.0" }, - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/bin/composer/phpunit/composer.lock b/bin/composer/phpunit/composer.lock index efc67dcf121..b32d4d77b22 100644 --- a/bin/composer/phpunit/composer.lock +++ b/bin/composer/phpunit/composer.lock @@ -59,6 +59,10 @@ "constructor", "instantiate" ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/master" + }, "time": "2015-06-14T21:17:01+00:00" }, { @@ -104,6 +108,10 @@ "object", "object graph" ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.x" + }, "time": "2017-10-19T19:58:43+00:00" }, { @@ -159,6 +167,10 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/master" + }, "time": "2017-03-05T18:14:27+00:00" }, { @@ -206,6 +218,10 @@ } ], "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/master" + }, "time": "2017-03-05T17:38:23+00:00" }, { @@ -260,6 +276,10 @@ "reflection", "static analysis" ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master" + }, "time": "2017-09-11T18:02:19+00:00" }, { @@ -312,6 +332,10 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/4.x" + }, "time": "2019-12-28T18:55:12+00:00" }, { @@ -357,6 +381,10 @@ "email": "me@mikevanriel.com" } ], + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/master" + }, "time": "2017-12-30T13:23:38+00:00" }, { @@ -420,6 +448,10 @@ "spy", "stub" ], + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/v1.10.3" + }, "time": "2020-03-05T15:02:03+00:00" }, { @@ -483,6 +515,10 @@ "testing", "xunit" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/5.3" + }, "time": "2018-04-06T15:36:58+00:00" }, { @@ -530,6 +566,11 @@ "filesystem", "iterator" ], + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5" + }, "time": "2017-11-27T13:52:08+00:00" }, { @@ -571,6 +612,10 @@ "keywords": [ "template" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + }, "time": "2015-06-21T13:50:34+00:00" }, { @@ -620,6 +665,10 @@ "keywords": [ "timer" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/master" + }, "time": "2017-02-26T11:10:40+00:00" }, { @@ -669,6 +718,10 @@ "keywords": [ "tokenizer" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master" + }, "abandoned": true, "time": "2017-11-27T05:48:46+00:00" }, @@ -754,6 +807,10 @@ "testing", "xunit" ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/6.5.14" + }, "time": "2019-02-01T05:22:47+00:00" }, { @@ -813,6 +870,10 @@ "mock", "xunit" ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", + "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/5.0.10" + }, "abandoned": true, "time": "2018-08-09T05:50:03+00:00" }, @@ -859,6 +920,10 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -929,6 +994,10 @@ "compare", "equality" ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/master" + }, "time": "2018-02-01T13:46:46+00:00" }, { @@ -981,6 +1050,10 @@ "keywords": [ "diff" ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/master" + }, "time": "2017-08-03T08:09:46+00:00" }, { @@ -1031,6 +1104,10 @@ "environment", "hhvm" ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/master" + }, "time": "2017-07-01T08:51:00+00:00" }, { @@ -1098,6 +1175,10 @@ "export", "exporter" ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1155,6 +1236,10 @@ "keywords": [ "global state" ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/2.0.0" + }, "time": "2017-04-27T15:39:26+00:00" }, { @@ -1202,6 +1287,10 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1253,6 +1342,10 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1312,6 +1405,10 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1360,6 +1457,10 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/master" + }, "time": "2015-07-28T20:34:47+00:00" }, { @@ -1403,6 +1504,10 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/master" + }, "time": "2016-10-03T07:35:21+00:00" }, { @@ -1465,6 +1570,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1519,6 +1627,10 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/master" + }, "time": "2019-06-13T22:48:21+00:00" }, { @@ -1568,6 +1680,10 @@ "check", "validate" ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.9.1" + }, "time": "2020-07-08T17:02:28+00:00" } ], @@ -1581,5 +1697,5 @@ "platform-overrides": { "php": "7.0" }, - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/bin/composer/wp/composer.lock b/bin/composer/wp/composer.lock index f0f61f98695..8fb33475e13 100644 --- a/bin/composer/wp/composer.lock +++ b/bin/composer/wp/composer.lock @@ -9,16 +9,16 @@ "packages-dev": [ { "name": "gettext/gettext", - "version": "v4.8.3", + "version": "v4.8.4", "source": { "type": "git", "url": "https://github.com/php-gettext/Gettext.git", - "reference": "57ff4fb16647e78e80a5909fe3c190f1c3110321" + "reference": "58bc0f7f37e78efb0f9758f93d4a0f669f0f84a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/57ff4fb16647e78e80a5909fe3c190f1c3110321", - "reference": "57ff4fb16647e78e80a5909fe3c190f1c3110321", + "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/58bc0f7f37e78efb0f9758f93d4a0f669f0f84a1", + "reference": "58bc0f7f37e78efb0f9758f93d4a0f669f0f84a1", "shasum": "" }, "require": { @@ -67,7 +67,26 @@ "po", "translation" ], - "time": "2020-11-18T22:35:49+00:00" + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/oscarotero/Gettext/issues", + "source": "https://github.com/php-gettext/Gettext/tree/v4.8.4" + }, + "funding": [ + { + "url": "https://paypal.me/oscarotero", + "type": "custom" + }, + { + "url": "https://github.com/oscarotero", + "type": "github" + }, + { + "url": "https://www.patreon.com/misteroom", + "type": "patreon" + } + ], + "time": "2021-03-10T19:35:49+00:00" }, { "name": "gettext/languages", @@ -128,6 +147,10 @@ "translations", "unicode" ], + "support": { + "issues": "https://github.com/php-gettext/Languages/issues", + "source": "https://github.com/php-gettext/Languages/tree/2.6.0" + }, "time": "2019-11-13T10:30:21+00:00" }, { @@ -173,6 +196,10 @@ } ], "description": "Peast is PHP library that generates AST for JavaScript code", + "support": { + "issues": "https://github.com/mck89/peast/issues", + "source": "https://github.com/mck89/peast/tree/v1.12.0" + }, "time": "2021-01-08T15:16:19+00:00" }, { @@ -219,6 +246,10 @@ "mustache", "templating" ], + "support": { + "issues": "https://github.com/bobthecow/mustache.php/issues", + "source": "https://github.com/bobthecow/mustache.php/tree/master" + }, "time": "2019-11-23T21:40:31+00:00" }, { @@ -268,6 +299,10 @@ "iri", "sockets" ], + "support": { + "issues": "https://github.com/rmccue/Requests/issues", + "source": "https://github.com/rmccue/Requests/tree/master" + }, "time": "2016-10-13T00:11:37+00:00" }, { @@ -317,6 +352,9 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/3.3" + }, "time": "2017-06-01T21:01:25+00:00" }, { @@ -374,6 +412,10 @@ ], "description": "Provides internationalization tools for WordPress projects.", "homepage": "https://github.com/wp-cli/i18n-command", + "support": { + "issues": "https://github.com/wp-cli/i18n-command/issues", + "source": "https://github.com/wp-cli/i18n-command/tree/v2.2.6" + }, "time": "2020-12-07T19:28:27+00:00" }, { @@ -422,6 +464,9 @@ ], "description": "A simple YAML loader/dumper class for PHP (WP-CLI fork)", "homepage": "https://github.com/mustangostang/spyc/", + "support": { + "source": "https://github.com/wp-cli/spyc/tree/autoload" + }, "time": "2017-04-25T11:26:20+00:00" }, { @@ -472,6 +517,10 @@ "cli", "console" ], + "support": { + "issues": "https://github.com/wp-cli/php-cli-tools/issues", + "source": "https://github.com/wp-cli/php-cli-tools/tree/v0.11.12" + }, "time": "2021-03-03T12:43:49+00:00" }, { @@ -534,6 +583,11 @@ "cli", "wordpress" ], + "support": { + "docs": "https://make.wordpress.org/cli/handbook/", + "issues": "https://github.com/wp-cli/wp-cli/issues", + "source": "https://github.com/wp-cli/wp-cli" + }, "time": "2020-02-18T08:15:37+00:00" } ], @@ -547,5 +601,5 @@ "platform-overrides": { "php": "7.0" }, - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/changelog.txt b/changelog.txt index d2100ece059..d238a589df6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,19 @@ == Changelog == += 5.2.0 RC 2 2021-04-06 = + +**WooCommerce** + +* Update - WooCommerce Admin package 2.1.5. #29577 + +**WooCommerce Admin - 2.1.5** + +* Tweak - Set international country feature flag off + = 5.2.0 RC 2021-03-30 = +**WooCommerce** + * Update - WooCommerce Admin package 2.1.4. #29520 * Fix - Don't remove existing coupons from order when an invalid REST API request for updating coupons is submitted. #29474 * Fix - Wrong logic for including or excluding the payments step in the list of completed tasks in the onboarding wizard. #29518 diff --git a/composer.json b/composer.json index 385182966bc..50eb52913c2 100644 --- a/composer.json +++ b/composer.json @@ -21,8 +21,8 @@ "pelago/emogrifier": "3.1.0", "psr/container": "1.0.0", "woocommerce/action-scheduler": "3.1.6", - "woocommerce/woocommerce-admin": "2.1.4", - "woocommerce/woocommerce-blocks": "4.7.0" + "woocommerce/woocommerce-admin": "2.1.5", + "woocommerce/woocommerce-blocks": "4.7.1" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.4" diff --git a/composer.lock b/composer.lock index 2eb76ff282e..d2dbbdd4169 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": "b1d6d94c8cfae572ab27c288c6865787", + "content-hash": "5005eed74baf10300e2895e9b6a4f344", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -530,16 +530,16 @@ }, { "name": "woocommerce/woocommerce-admin", - "version": "2.1.4", + "version": "2.1.5", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-admin.git", - "reference": "f992b8c8664e72b00ee7283ba1d34e74e4b67ab0" + "reference": "71c233d8463f551430edbe1877e51d19a4bb2df6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/f992b8c8664e72b00ee7283ba1d34e74e4b67ab0", - "reference": "f992b8c8664e72b00ee7283ba1d34e74e4b67ab0", + "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/71c233d8463f551430edbe1877e51d19a4bb2df6", + "reference": "71c233d8463f551430edbe1877e51d19a4bb2df6", "shasum": "" }, "require": { @@ -573,22 +573,22 @@ "homepage": "https://github.com/woocommerce/woocommerce-admin", "support": { "issues": "https://github.com/woocommerce/woocommerce-admin/issues", - "source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.1.4" + "source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.1.5" }, - "time": "2021-03-29T11:59:33+00:00" + "time": "2021-04-02T16:48:38+00:00" }, { "name": "woocommerce/woocommerce-blocks", - "version": "v4.7.0", + "version": "v4.7.1", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git", - "reference": "bf9f70607e718c5f83785cad29b33746db0282d3" + "reference": "841c49b8626f4eb717056a2d1e3eba6140f45e2c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/bf9f70607e718c5f83785cad29b33746db0282d3", - "reference": "bf9f70607e718c5f83785cad29b33746db0282d3", + "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/841c49b8626f4eb717056a2d1e3eba6140f45e2c", + "reference": "841c49b8626f4eb717056a2d1e3eba6140f45e2c", "shasum": "" }, "require": { @@ -624,9 +624,9 @@ ], "support": { "issues": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues", - "source": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/tree/v4.7.0" + "source": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/tree/v4.7.1" }, - "time": "2021-03-16T16:09:55+00:00" + "time": "2021-04-02T11:18:50+00:00" } ], "packages-dev": [ diff --git a/includes/class-wc-cart.php b/includes/class-wc-cart.php index 1103ee053e5..594bb904670 100644 --- a/includes/class-wc-cart.php +++ b/includes/class-wc-cart.php @@ -1218,15 +1218,30 @@ class WC_Cart extends WC_Legacy_Cart { $products_qty_in_cart = $this->get_cart_item_quantities(); if ( isset( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ] ) && ! $product_data->has_enough_stock( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ] + $quantity ) ) { - throw new Exception( - sprintf( - '%s %s', - wc_get_cart_url(), - __( 'View cart', 'woocommerce' ), - /* translators: 1: quantity in stock 2: current quantity */ - sprintf( __( 'You cannot add that amount to the cart — we have %1$s in stock and you already have %2$s in your cart.', 'woocommerce' ), wc_format_stock_quantity_for_display( $product_data->get_stock_quantity(), $product_data ), wc_format_stock_quantity_for_display( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ], $product_data ) ) - ) + $stock_quantity = $product_data->get_stock_quantity(); + $stock_quantity_in_cart = $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ]; + + $message = sprintf( + '%s %s', + wc_get_cart_url(), + __( 'View cart', 'woocommerce' ), + /* translators: 1: quantity in stock 2: current quantity */ + sprintf( __( 'You cannot add that amount to the cart — we have %1$s in stock and you already have %2$s in your cart.', 'woocommerce' ), wc_format_stock_quantity_for_display( $stock_quantity, $product_data ), wc_format_stock_quantity_for_display( $stock_quantity_in_cart, $product_data ) ) ); + + /** + * Filters message about product not having enough stock accounting for what's already in the cart. + * + * @param string $message Message. + * @param WC_Product $product_data Product data. + * @param int $stock_quantity Quantity remaining. + * @param int $stock_quantity_in_cart + * + * @since 5.3.0 + */ + $message = apply_filters( 'woocommerce_cart_product_not_enough_stock_already_in_cart_message', $message, $product_data, $stock_quantity, $stock_quantity_in_cart ); + + throw new Exception( $message ); } } diff --git a/includes/class-wc-template-loader.php b/includes/class-wc-template-loader.php index 5a3233756fa..bdb728da65d 100644 --- a/includes/class-wc-template-loader.php +++ b/includes/class-wc-template-loader.php @@ -139,7 +139,7 @@ class WC_Template_Loader { if ( 0 === $validated_file ) { $templates[] = $page_template; } else { - error_log( "WooCommerce: Unable to validate template path: \"$page_template\". Error Code: $validated_file." ); + error_log( "WooCommerce: Unable to validate template path: \"$page_template\". Error Code: $validated_file." ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log } } } @@ -294,8 +294,8 @@ class WC_Template_Loader { } // Description handling. - if ( ! empty( $queried_object->description ) && ( empty( $_GET['product-page'] ) || 1 === absint( $_GET['product-page'] ) ) ) { // WPCS: input var ok, CSRF ok. - $prefix = '
' . wc_format_content( $queried_object->description ) . '
'; // WPCS: XSS ok. + if ( ! empty( $queried_object->description ) && ( empty( $_GET['product-page'] ) || 1 === absint( $_GET['product-page'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $prefix = '
' . wc_format_content( wp_kses_post( $queried_object->description ) ) . '
'; } else { $prefix = ''; } diff --git a/includes/wc-template-functions.php b/includes/wc-template-functions.php index 43597440f1c..cc77488ebe8 100644 --- a/includes/wc-template-functions.php +++ b/includes/wc-template-functions.php @@ -887,7 +887,7 @@ function wc_terms_and_conditions_page_content() { $page = get_post( $terms_page_id ); if ( $page && 'publish' === $page->post_status && $page->post_content && ! has_shortcode( $page->post_content, 'woocommerce_checkout' ) ) { - echo ''; + echo ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } @@ -1240,8 +1240,7 @@ if ( ! function_exists( 'woocommerce_taxonomy_archive_description' ) ) { $term = get_queried_object(); if ( $term && ! empty( $term->description ) ) { - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - echo '
' . wc_format_content( $term->description ) . '
'; + echo '
' . wc_format_content( wp_kses_post( $term->description ) ) . '
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } } @@ -1260,10 +1259,9 @@ if ( ! function_exists( 'woocommerce_product_archive_description' ) ) { if ( is_post_type_archive( 'product' ) && in_array( absint( get_query_var( 'paged' ) ), array( 0, 1 ), true ) ) { $shop_page = get_post( wc_get_page_id( 'shop' ) ); if ( $shop_page ) { - $description = wc_format_content( $shop_page->post_content ); + $description = wc_format_content( wp_kses_post( $shop_page->post_content ) ); if ( $description ) { - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - echo '
' . $description . '
'; + echo '
' . $description . '
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } } diff --git a/readme.txt b/readme.txt index b230c7250c7..36501242837 100644 --- a/readme.txt +++ b/readme.txt @@ -160,8 +160,20 @@ WooCommerce comes with some sample data you can use to see how products look; im == Changelog == += 5.2.0 RC 2 2021-04-06 = + +**WooCommerce** + +* Update - WooCommerce Admin package 2.1.5. #29577 + +**WooCommerce Admin - 2.1.5** + +* Tweak - Set international country feature flag off + = 5.2.0 RC 2021-03-30 = +**WooCommerce** + * Update - WooCommerce Admin package 2.1.4. #29520 * Fix - Don't remove existing coupons from order when an invalid REST API request for updating coupons is submitted. #29474 * Fix - Wrong logic for including or excluding the payments step in the list of completed tasks in the onboarding wizard. #29518 diff --git a/tests/e2e/config/jest.setup.js b/tests/e2e/config/jest.setup.js index 60262d99ea9..16b57a8168e 100644 --- a/tests/e2e/config/jest.setup.js +++ b/tests/e2e/config/jest.setup.js @@ -1,4 +1,4 @@ -import { SimpleProduct } from '@woocommerce/api'; +import { SimpleProduct, Coupon } from '@woocommerce/api'; import { visitAdminPage, switchUserToTest, @@ -56,12 +56,32 @@ async function deleteAllProducts() { } } +/** + * Use api package to delete coupons. + * + * @return {Promise} Promise resolving once coupons have been trashed. + */ +async function deleteAllCoupons() { + const repository = Coupon.restRepository( factories.api.withDefaultPermalinks ); + let coupons; + + coupons = await repository.list(); + + while ( coupons.length > 0 ) { + for (let c = 0; c < coupons.length; c++ ) { + await repository.delete( coupons[ c ].id ); + } + coupons = await repository.list(); + } +} + // Before every test suite run, delete all content created by the test. This ensures // other posts/comments/etc. aren't dirtying tests and tests don't depend on // each other's side-effects. beforeAll( async () => { await trashExistingPosts(); await deleteAllProducts(); + await deleteAllCoupons(); await clearLocalStorage(); await setBrowserViewport( 'large' ); } ); diff --git a/tests/e2e/core-tests/CHANGELOG.md b/tests/e2e/core-tests/CHANGELOG.md index 614f8691dde..bf220a9d338 100644 --- a/tests/e2e/core-tests/CHANGELOG.md +++ b/tests/e2e/core-tests/CHANGELOG.md @@ -4,6 +4,7 @@ ## Added +- Shopper Checkout Login Account - Shopper My Account Create Account ## Fixed diff --git a/tests/e2e/core-tests/README.md b/tests/e2e/core-tests/README.md index c6b162afa1f..26f58a36c67 100644 --- a/tests/e2e/core-tests/README.md +++ b/tests/e2e/core-tests/README.md @@ -77,6 +77,7 @@ The functions to access the core tests are: - `runSingleProductPageTest` - Shopper can view single product page in many variations (simple, variable, grouped) - `runVariableProductUpdateTest` - Shopper can view and update variations on a variable product - `runCheckoutCreateAccountTest` - Shopper can create an account during checkout + - `runCheckoutLoginAccountTest` - Shopper can login to an account during checkout - `runMyAccountCreateAccountTest` - Shopper can create an account via my account page ### REST API diff --git a/tests/e2e/core-tests/specs/index.js b/tests/e2e/core-tests/specs/index.js index 110a80079fd..0f150981c1d 100644 --- a/tests/e2e/core-tests/specs/index.js +++ b/tests/e2e/core-tests/specs/index.js @@ -20,6 +20,7 @@ const runMyAccountCreateAccountTest = require( './shopper/front-end-my-account-c const runSingleProductPageTest = require( './shopper/front-end-single-product.test' ); const runVariableProductUpdateTest = require( './shopper/front-end-variable-product-updates.test' ); const runCheckoutCreateAccountTest = require( './shopper/front-end-checkout-create-account.test' ); +const runCheckoutLoginAccountTest = require( './shopper/front-end-checkout-login-account.test' ); // Merchant tests const runAddNewShippingZoneTest = require ( './merchant/wp-admin-settings-shipping-zones.test' ); @@ -66,6 +67,7 @@ const runShopperTests = () => { runSingleProductPageTest(); runVariableProductUpdateTest(); runCheckoutCreateAccountTest(); + runCheckoutLoginAccountTest(); }; const runMerchantTests = () => { @@ -138,5 +140,6 @@ module.exports = { runAddShippingClassesTest, runAnalyticsPageLoadsTest, runCheckoutCreateAccountTest, + runCheckoutLoginAccountTest, runMyAccountCreateAccountTest }; diff --git a/tests/e2e/core-tests/specs/shopper/front-end-cart-coupons.test.js b/tests/e2e/core-tests/specs/shopper/front-end-cart-coupons.test.js index b2b3f4888a3..3e07011d800 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-cart-coupons.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-cart-coupons.test.js @@ -34,6 +34,7 @@ const runCartApplyCouponsTest = () => { couponPercentage = await createCoupon('50', 'Percentage discount'); couponFixedProduct = await createCoupon('5', 'Fixed product discount'); await merchant.logout(); + await shopper.emptyCart(); await shopper.goToShop(); await shopper.addToCartFromShopPage('Simple product'); await uiUnblocked(); diff --git a/tests/e2e/core-tests/specs/shopper/front-end-checkout-coupons.test.js b/tests/e2e/core-tests/specs/shopper/front-end-checkout-coupons.test.js index 34135e5ada0..9b009823b96 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-checkout-coupons.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-checkout-coupons.test.js @@ -34,6 +34,7 @@ const runCheckoutApplyCouponsTest = () => { couponPercentage = await createCoupon('50', 'Percentage discount'); couponFixedProduct = await createCoupon('5', 'Fixed product discount'); await merchant.logout(); + await shopper.emptyCart(); await shopper.goToShop(); await shopper.addToCartFromShopPage('Simple product'); await uiUnblocked(); diff --git a/tests/e2e/core-tests/specs/shopper/front-end-checkout-create-account.test.js b/tests/e2e/core-tests/specs/shopper/front-end-checkout-create-account.test.js index 4ccaab02e06..f26e57fad85 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-checkout-create-account.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-checkout-create-account.test.js @@ -28,10 +28,14 @@ const runCheckoutCreateAccountTest = () => { beforeAll(async () => { await merchant.login(); await createSimpleProduct(); + + // Set checkbox for creating an account during checkout await merchant.openSettings('account'); await setCheckbox('#woocommerce_enable_signup_and_login_from_checkout'); await settingsPageSaveChanges(); await merchant.logout(); + + // Add simple product to cart and proceed to checkout await shopper.goToShop(); await shopper.addToCartFromShopPage(simpleProductName); await uiUnblocked(); diff --git a/tests/e2e/core-tests/specs/shopper/front-end-checkout-login-account.test.js b/tests/e2e/core-tests/specs/shopper/front-end-checkout-login-account.test.js new file mode 100644 index 00000000000..db400d5e79d --- /dev/null +++ b/tests/e2e/core-tests/specs/shopper/front-end-checkout-login-account.test.js @@ -0,0 +1,74 @@ +/* eslint-disable jest/no-export, jest/no-disabled-tests, jest/expect-expect */ +/** + * Internal dependencies + */ + const { + shopper, + merchant, + createSimpleProduct, + uiUnblocked, + setCheckbox, + settingsPageSaveChanges, +} = require( '@woocommerce/e2e-utils' ); + +/** + * External dependencies + */ +const { + it, + describe, + beforeAll, +} = require( '@jest/globals' ); + +const config = require('config'); +const simpleProductName = config.get('products.simple.name'); + +const runCheckoutLoginAccountTest = () => { + describe('Shopper Checkout Login Account', () => { + beforeAll(async () => { + await merchant.login(); + await createSimpleProduct(); + + // Set checkbox for logging to account during checkout + await merchant.openSettings('account'); + await setCheckbox('#woocommerce_enable_checkout_login_reminder'); + await settingsPageSaveChanges(); + await merchant.logout(); + + // Add simple product to cart and proceed to checkout + await shopper.goToShop(); + await shopper.addToCartFromShopPage(simpleProductName); + await uiUnblocked(); + await shopper.goToCheckout(); + }); + + it('can login to an existing account during checkout', async () => { + // Click to login during checkout + await page.waitForSelector('.woocommerce-form-login-toggle'); + await expect(page).toClick('.woocommerce-info > a.showlogin'); + + // Fill shopper's login credentials and proceed further + await page.type( '#username', config.get('users.customer.username') ); + await page.type( '#password', config.get('users.customer.password') ); + + await Promise.all([ + page.waitForNavigation({waitUntil: 'networkidle0'}), + page.click('button[name="login"]'), + ]); + + // Place an order + await shopper.placeOrder(); + await expect(page).toMatchElement('h1.entry-title', {text: 'Order received'}); + + // Verify the email of a logged in user + await expect(page).toMatchElement('ul > li.email', {text: 'Email: john.doe@example.com'}); + + // Verify the user is logged in on my account page + await shopper.gotoMyAccount(); + await expect(page.url()).toMatch('my-account/'); + await expect(page).toMatchElement('h1', {text: 'My account'}); + }); + }); +}; + +module.exports = runCheckoutLoginAccountTest; diff --git a/tests/e2e/env/config/custom-environment-variables.json b/tests/e2e/env/config/custom-environment-variables.json new file mode 100644 index 00000000000..5961ecb534c --- /dev/null +++ b/tests/e2e/env/config/custom-environment-variables.json @@ -0,0 +1,13 @@ +{ + "url": "SMOKE_TEST_URL", + "users": { + "admin": { + "username": "SMOKE_TEST_ADMIN_USER", + "password": "SMOKE_TEST_ADMIN_PASSWORD" + }, + "customer": { + "username": "SMOKE_TEST_CUSTOMER_USER", + "password": "SMOKE_TEST_CUSTOMER_PASSWORD" + } + } +} diff --git a/tests/e2e/env/utils/test-config.js b/tests/e2e/env/utils/test-config.js index 652e30f3a68..8b1d419f3eb 100644 --- a/tests/e2e/env/utils/test-config.js +++ b/tests/e2e/env/utils/test-config.js @@ -19,10 +19,30 @@ if ( fs.existsSync( localTestConfigFile ) ) { ); } +/** + * Get test container configuration. + * @returns {any} + */ const getTestConfig = () => { const rawTestConfig = fs.readFileSync( testConfigFile ); + const config = require( 'config' ); + const url = config.get( 'url' ); + const users = config.get( 'users' ); + // Support for environment variable overrides. let testConfig = JSON.parse( rawTestConfig ); + if ( url ) { + testConfig.url = url; + } + if ( users ) { + if ( users.admin ) { + testConfig.users.admin = users.admin; + } + if ( users.customer ) { + testConfig.users.customer = users.customer; + } + } + let testPort = testConfig.url.match( /[0-9]+/ ); testConfig.baseUrl = testConfig.url.substr( 0, testConfig.url.length - 1 ); if ( Array.isArray( testPort ) ) { diff --git a/tests/e2e/specs/front-end/test-checkout-login-account.js b/tests/e2e/specs/front-end/test-checkout-login-account.js new file mode 100644 index 00000000000..1bf304e04ad --- /dev/null +++ b/tests/e2e/specs/front-end/test-checkout-login-account.js @@ -0,0 +1,6 @@ +/* + * Internal dependencies + */ +const { runCheckoutLoginAccountTest } = require( '@woocommerce/e2e-core-tests' ); + +runCheckoutLoginAccountTest(); diff --git a/tests/e2e/utils/CHANGELOG.md b/tests/e2e/utils/CHANGELOG.md index e430ce8df00..07e70e130fe 100644 --- a/tests/e2e/utils/CHANGELOG.md +++ b/tests/e2e/utils/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased +- `emptyCart()` Shopper flow helper that empties the cart + # 0.1.4 ## Fixed diff --git a/tests/e2e/utils/README.md b/tests/e2e/utils/README.md index 95830e44f59..f6b5c662e4f 100644 --- a/tests/e2e/utils/README.md +++ b/tests/e2e/utils/README.md @@ -78,7 +78,8 @@ describe( 'Cart page', () => { | `productIsInCheckout` | `productTitle, quantity, total, cartSubtotal` | Verify product is in cart on checkout page | | `removeFromCart` | `productTitle` | Remove a product from the cart on the cart page | | `setCartQuantity` | `productTitle, quantityValue` | Change the quantity of a product on the cart page | -| `searchForProduct` | Searching for a product name and landing on its detail page | +| `searchForProduct` | | Searching for a product name and landing on its detail page | +| `emptyCart` | | Removes any products and coupons that are in the cart | ### Page Utilities diff --git a/tests/e2e/utils/src/flows/shopper.js b/tests/e2e/utils/src/flows/shopper.js index 8e4acad61f2..1e2b7cd9d13 100644 --- a/tests/e2e/utils/src/flows/shopper.js +++ b/tests/e2e/utils/src/flows/shopper.js @@ -24,6 +24,8 @@ const { SHOP_PRODUCT_PAGE } = require( './constants' ); +const { uiUnblocked } = require( '../page-utils' ); + const gotoMyAccount = async () => { await page.goto( SHOP_MY_ACCOUNT_PAGE, { waitUntil: 'networkidle0', @@ -127,6 +129,33 @@ const shopper = { await removeButton.click(); }, + emptyCart: async () => { + await page.goto( SHOP_CART_PAGE, { + waitUntil: 'networkidle0', + } ); + + // Remove products if they exist + if ( await page.$( '.remove' ) !== null ) { + products = await page.$( '.remove' ); + while ( products.length > 0 ) { + for (let p = 0; p < products.length; p++ ) { + await page.click( p ); + await uiUnblocked(); + } + products = await page.$( '.remove' ); + } + } + + // Remove coupons if they exist + if ( await page.$( '.woocommerce-remove-coupon' ) !== null ) { + await page.click( '.woocommerce-remove-coupon' ); + await uiUnblocked(); + } + + await page.waitForSelector('.woocommerce-info'); + await expect( page ).toMatchElement( '.woocommerce-info', { text: 'Your cart is currently empty.' } ); + }, + setCartQuantity: async ( productTitle, quantityValue ) => { const cartItemXPath = getCartItemExpression( productTitle ); const quantityInputXPath = cartItemXPath + '//' + getQtyInputExpression();