From 5b02c440d7adaeefdbf4d77d8d2f965993af3615 Mon Sep 17 00:00:00 2001 From: Jacob Arriola Date: Mon, 8 Mar 2021 10:38:23 -0800 Subject: [PATCH 1/5] New filter: stock check message Adds a new filter to allow customization of the stock check message when a product is out of stock, but accounting for what's already in the cart. It mimics the existing woocommerce_cart_product_not_enough_stock_message filter. --- includes/class-wc-cart.php | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/includes/class-wc-cart.php b/includes/class-wc-cart.php index 1103ee053e5..966a5bb7fdf 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 = printf( + '%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.0.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 ); } } From 76744da6f94032e960dd0f72cec9930e02738043 Mon Sep 17 00:00:00 2001 From: Jacob Arriola Date: Fri, 26 Mar 2021 08:55:24 -0700 Subject: [PATCH 2/5] Use sprintf, no printf when setting the variable --- includes/class-wc-cart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-cart.php b/includes/class-wc-cart.php index 966a5bb7fdf..ec09143b4c9 100644 --- a/includes/class-wc-cart.php +++ b/includes/class-wc-cart.php @@ -1221,7 +1221,7 @@ class WC_Cart extends WC_Legacy_Cart { $stock_quantity = $product_data->get_stock_quantity(); $stock_quantity_in_cart = $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ]; - $message = printf( + $message = sprintf( '%s %s', wc_get_cart_url(), __( 'View cart', 'woocommerce' ), From eb6572fec0ef459e5db1bffb1bfb99be3cc79307 Mon Sep 17 00:00:00 2001 From: Veljko Date: Thu, 1 Apr 2021 11:10:43 +0200 Subject: [PATCH 3/5] Added new e2e test shopper login checkout --- tests/e2e/core-tests/CHANGELOG.md | 4 + tests/e2e/core-tests/README.md | 1 + tests/e2e/core-tests/specs/index.js | 3 + .../front-end-checkout-create-account.test.js | 4 + .../front-end-checkout-login-account.test.js | 74 +++++++++++++++++++ .../front-end/test-checkout-login-account.js | 6 ++ 6 files changed, 92 insertions(+) create mode 100644 tests/e2e/core-tests/specs/shopper/front-end-checkout-login-account.test.js create mode 100644 tests/e2e/specs/front-end/test-checkout-login-account.js diff --git a/tests/e2e/core-tests/CHANGELOG.md b/tests/e2e/core-tests/CHANGELOG.md index 098aa07caff..09fd7a6e7fd 100644 --- a/tests/e2e/core-tests/CHANGELOG.md +++ b/tests/e2e/core-tests/CHANGELOG.md @@ -2,6 +2,10 @@ # 0.1.3 +## Added + +- Shopper Checkout Login Account + ## Fixed - removed use of ES6 `import` diff --git a/tests/e2e/core-tests/README.md b/tests/e2e/core-tests/README.md index b85cf9d56db..661bfaf0a72 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 ### REST API diff --git a/tests/e2e/core-tests/specs/index.js b/tests/e2e/core-tests/specs/index.js index 3f133ba80ae..c23369945e8 100644 --- a/tests/e2e/core-tests/specs/index.js +++ b/tests/e2e/core-tests/specs/index.js @@ -19,6 +19,7 @@ const runMyAccountPayOrderTest = require( './shopper/front-end-my-account-pay-or 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' ); @@ -63,6 +64,7 @@ const runShopperTests = () => { runSingleProductPageTest(); runVariableProductUpdateTest(); runCheckoutCreateAccountTest(); + runCheckoutLoginAccountTest(); }; const runMerchantTests = () => { @@ -133,4 +135,5 @@ module.exports = { runApiTests, runAnalyticsPageLoadsTest, runCheckoutCreateAccountTest, + runCheckoutLoginAccountTest, }; 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..8fb3f926f5b --- /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(); + expect(page.url()).toMatch('my-account/'); + await expect(page).toMatchElement('h1', {text: 'My account'}); + }); + }); +}; + +module.exports = runCheckoutLoginAccountTest; 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(); From 9d1b3471489b1ba29b1dc039fe9c9be62b234076 Mon Sep 17 00:00:00 2001 From: Veljko Date: Mon, 5 Apr 2021 11:25:15 +0200 Subject: [PATCH 4/5] Add spacing and missing await --- .../shopper/front-end-checkout-login-account.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 index 8fb3f926f5b..db400d5e79d 100644 --- 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 @@ -52,9 +52,9 @@ const runCheckoutLoginAccountTest = () => { await page.type( '#password', config.get('users.customer.password') ); await Promise.all([ - page.waitForNavigation({waitUntil: 'networkidle0'}), - page.click('button[name="login"]'), - ]); + page.waitForNavigation({waitUntil: 'networkidle0'}), + page.click('button[name="login"]'), + ]); // Place an order await shopper.placeOrder(); @@ -65,7 +65,7 @@ const runCheckoutLoginAccountTest = () => { // Verify the user is logged in on my account page await shopper.gotoMyAccount(); - expect(page.url()).toMatch('my-account/'); + await expect(page.url()).toMatch('my-account/'); await expect(page).toMatchElement('h1', {text: 'My account'}); }); }); From 319a45705dcc6fcdfe2d0b09f6b420aef0f05fb3 Mon Sep 17 00:00:00 2001 From: Jacob Arriola Date: Mon, 5 Apr 2021 07:56:05 -0700 Subject: [PATCH 5/5] Update WC version --- includes/class-wc-cart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-cart.php b/includes/class-wc-cart.php index ec09143b4c9..594bb904670 100644 --- a/includes/class-wc-cart.php +++ b/includes/class-wc-cart.php @@ -1237,7 +1237,7 @@ class WC_Cart extends WC_Legacy_Cart { * @param int $stock_quantity Quantity remaining. * @param int $stock_quantity_in_cart * - * @since 5.0.0 + * @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 );