From ec18d580c2b4d5fcb064bbd5eb767d1f3cb38850 Mon Sep 17 00:00:00 2001 From: Adam Heckler <5512652+aheckler@users.noreply.github.com> Date: Thu, 9 Jan 2025 05:10:05 -0500 Subject: [PATCH 1/5] Update WordPress.org readme.txt file (#10096) --- changelog/fix-10033-wporg-readme-updates | 4 ++++ readme.txt | 25 +++++++++--------------- 2 files changed, 13 insertions(+), 16 deletions(-) create mode 100644 changelog/fix-10033-wporg-readme-updates diff --git a/changelog/fix-10033-wporg-readme-updates b/changelog/fix-10033-wporg-readme-updates new file mode 100644 index 00000000000..0ac18787db0 --- /dev/null +++ b/changelog/fix-10033-wporg-readme-updates @@ -0,0 +1,4 @@ +Significance: minor +Type: fix + +Update WordPress.org readme.txt file diff --git a/readme.txt b/readme.txt index cf22809f3b1..e9679c21243 100644 --- a/readme.txt +++ b/readme.txt @@ -28,11 +28,11 @@ Features previously only available on your payment provider’s website are now **Pay as you go** -WooPayments is **free to install**, with **no setup fees or monthly fees**. Pay-as-you-go fees start at 2.9% + $0.30 per transaction for U.S.-issued cards. [Read more about transaction fees](https://woocommerce.com/document/woopayments/fees-and-debits/fees/). +WooPayments is **free to install**, with **no setup fees or monthly fees**. Our pay-as-you-go pricing model means we're incentivized to help you succeed! [Read more about transaction fees](https://woocommerce.com/document/woopayments/fees-and-debits/fees/). **Supported by the WooCommerce team** -Our global support team is available to answer questions you may have about WooPayments installation, setup, or use. For assistance, [open a ticket on woocommerce.com](https://woocommerce.com/my-account/create-a-ticket/?select=5278104). +Our global support team is available to answer questions you may have about WooPayments installation, setup, or use. For assistance, [open a ticket on woocommerce.com](https://woocommerce.com/my-account/contact-support/?select=5278104). == Getting Started == @@ -40,14 +40,12 @@ Our global support team is available to answer questions you may have about WooP * WordPress 6.0 or newer. * WooCommerce 7.6 or newer. -* PHP 7.3 or newer is recommended. +* PHP 7.3 or newer. = Try it now = To try WooPayments (previously WooCommerce Payments) on your store, simply [install it](https://wordpress.org/plugins/woocommerce-payments/#installation) and follow the prompts. Please see our [Startup Guide](https://woocommerce.com/document/woopayments/startup-guide/) for a full walkthrough of the process. -WooPayments has experimental support for the Checkout block from [WooCommerce Blocks](https://wordpress.org/plugins/woo-gutenberg-products-block/). Please check the [FAQ section](#faq) for more information. - == Installation == Install and activate the WooCommerce and WooPayments plugins, if you haven't already done so, then go to "Payments" in the WordPress admin menu and follow the instructions there. @@ -56,13 +54,17 @@ Install and activate the WooCommerce and WooPayments plugins, if you haven't alr = What countries and currencies are supported? = -If you are an individual or business based in [one of these countries](https://woocommerce.com/document/woopayments/compatibility/countries/#supported-countries), you can sign-up with WooPayments. After completing sign up, you can accept payments from customers anywhere in the world. +If you are an individual or business based in [one of these countries](https://woocommerce.com/document/woopayments/compatibility/countries/#supported-countries), you can sign-up with WooPayments. After completing sign up, you can accept payments from customers anywhere in the world, as long as they are paying with [a supported currency](https://woocommerce.com/document/woopayments/currencies/available-currencies/). We are actively planning to expand into additional countries based on your interest. Let us know where you would like to [see WooPayments launch next](https://woocommerce.com/payments/#request-invite). = Why is a WordPress.com account and connection required? = -WooPayments uses the WordPress.com connection to authenticate each request, connecting your store with our payments partner. +WooPayments uses the WordPress.com connection to securely communicate with our payments server. This is necessary for WooPayments to function correctly, so it's not possible to use WooPayments without connecting. Please see [this document](https://woocommerce.com/document/woopayments/our-policies/connection/) for more information. + +Note that you do not need to host your site itself on WordPress.com, nor do you need to host *any* site on WordPress.com at all. You only need an account. + +Note that you do not need to host your site itself on WordPress.com. You only need an account on WordPress.com to establish the connection. You can create a WordPress.com account [at this link](https://wordpress.com/start/account/user-social). = How do I set up a store for a client? = @@ -76,15 +78,6 @@ WooPayments is built in partnership with Stripe [Stripe](https://stripe.com/). W You can read our Terms of Service and other policies [here](https://woocommerce.com/document/woopayments/our-policies/). -= How does the Checkout block work? = - -You need the [WooCommerce Blocks](https://wordpress.org/plugins/woo-gutenberg-products-block/) plugin to be installed and active to use the Checkout block. Once you add the block to a page, WooPayments will automatically appear as an option. - -Please note that our support for the checkout block is still experimental and the following features of the gateway will probably not work: - -* Using saved cards and saving cards. -* Integration with WooCommerce Subscriptions. - == Screenshots == 1. View Transactions From c3a7f1b8a265802482eb827d93a3513e392c9f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ismael=20Mart=C3=ADn=20Alabarce?= Date: Thu, 9 Jan 2025 22:21:46 +0800 Subject: [PATCH 2/5] Convert the Payment Settings Manual Capture spec to Playwright (#10118) --- ...chant-payment-settings-manual-capture-spec | 5 ++ ...nt-payment-settings-manual-capture.spec.ts | 57 ++++++++++++++++ ...nt-payment-settings-manual-capture.spec.js | 66 ------------------- 3 files changed, 62 insertions(+), 66 deletions(-) create mode 100644 changelog/dev-9967-convert-merchant-payment-settings-manual-capture-spec create mode 100644 tests/e2e-pw/specs/merchant/merchant-payment-settings-manual-capture.spec.ts delete mode 100644 tests/e2e/specs/wcpay/merchant/merchant-payment-settings-manual-capture.spec.js diff --git a/changelog/dev-9967-convert-merchant-payment-settings-manual-capture-spec b/changelog/dev-9967-convert-merchant-payment-settings-manual-capture-spec new file mode 100644 index 00000000000..1217ac47cf8 --- /dev/null +++ b/changelog/dev-9967-convert-merchant-payment-settings-manual-capture-spec @@ -0,0 +1,5 @@ +Significance: patch +Type: dev +Comment: Converted a puppeteer spec to playwright + + diff --git a/tests/e2e-pw/specs/merchant/merchant-payment-settings-manual-capture.spec.ts b/tests/e2e-pw/specs/merchant/merchant-payment-settings-manual-capture.spec.ts new file mode 100644 index 00000000000..54456e23e34 --- /dev/null +++ b/tests/e2e-pw/specs/merchant/merchant-payment-settings-manual-capture.spec.ts @@ -0,0 +1,57 @@ +/** + * External dependencies + */ +import { test, expect } from '@playwright/test'; +/** + * Internal dependencies + */ +import { useMerchant } from '../../utils/helpers'; +import { goToWooPaymentsSettings } from '../../utils/merchant-navigation'; + +test.describe( + 'As a merchant, I should be prompted a confirmation modal when I try to activate the manual capture', + () => { + useMerchant(); + + test.beforeEach( async ( { page } ) => { + await goToWooPaymentsSettings( page ); + await page.getByTestId( 'capture-later-checkbox' ).click(); + } ); + + test( 'should show the confirmation dialog when enabling the manual capture', async ( { + page, + } ) => { + await expect( + page.getByText( + 'Payments must be captured within 7 days or the authorization will expire and money will be returned to the shopper' + ) + ).toBeVisible( { + timeout: 10000, + } ); + } ); + + test( 'should not show the confirmation dialog when disabling the manual capture', async ( { + page, + } ) => { + await page + .getByRole( 'button', { name: 'Enable manual capture' } ) + .click(); + await page.getByTestId( 'capture-later-checkbox' ).click(); + await expect( page.locator( '.wcpay-modal' ) ).not.toBeVisible(); + } ); + + test( 'should show the non-card methods disabled when manual capture is enabled', async ( { + page, + } ) => { + await page + .getByRole( 'button', { name: 'Enable manual capture' } ) + .click(); + const paymentMethodWarningIconElement = await page + .getByTestId( 'loadable-checkbox-icon-warning' ) + .first(); + await expect( paymentMethodWarningIconElement ).toHaveText( + /cannot be enabled at checkout/ + ); + } ); + } +); diff --git a/tests/e2e/specs/wcpay/merchant/merchant-payment-settings-manual-capture.spec.js b/tests/e2e/specs/wcpay/merchant/merchant-payment-settings-manual-capture.spec.js deleted file mode 100644 index ed041138157..00000000000 --- a/tests/e2e/specs/wcpay/merchant/merchant-payment-settings-manual-capture.spec.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * External dependencies - */ -import { merchantWCP } from '../../../utils'; - -const { merchant } = require( '@woocommerce/e2e-utils' ); - -const checkboxCaptureLaterOption = 'capture-later-checkbox'; -const paymentMethodWarningIconId = 'loadable-checkbox-icon-warning'; -const confirmationModalClass = '.wcpay-confirmation-modal'; - -describe( 'As a merchant, I should be prompted a confirmation modal when I try to activate the manual capture', () => { - beforeAll( async () => { - await merchant.login(); - await merchantWCP.openWCPSettings(); - await merchantWCP.skipFraudProtectionTour(); - } ); - - afterAll( async () => { - await merchant.logout(); - } ); - - afterEach( async () => { - await merchantWCP.unsetCheckboxByTestId( checkboxCaptureLaterOption ); - } ); - - it( 'should show the confirmation dialog when enabling the manual capture', async () => { - await merchantWCP.setCheckboxByTestId( checkboxCaptureLaterOption ); - const confirmationModal = await expect( page ).toMatchElement( - confirmationModalClass - ); - await expect( confirmationModal ).toMatchTextContent( - 'Payments must be captured within 7 days or the authorization will expire and money will be returned to the shopper' - ); - } ); - - it( 'should not show the confirmation dialog when disabling the manual capture', async () => { - await merchantWCP.setCheckboxByTestId( checkboxCaptureLaterOption ); - const confirmationModal = await expect( page ).toMatchElement( - confirmationModalClass - ); - await expect( confirmationModal ).toClick( 'button', { - text: 'Enable', - } ); - - await merchantWCP.unsetCheckboxByTestId( checkboxCaptureLaterOption ); - await expect( page ).not.toMatchElement( '.wcpay-confirmation-modal' ); - } ); - - it( 'should show the non-card methods disabled when manual capture is enabled', async () => { - await merchantWCP.setCheckboxByTestId( checkboxCaptureLaterOption ); - const confirmationModal = await expect( page ).toMatchElement( - confirmationModalClass - ); - await expect( confirmationModal ).toClick( 'button', { - text: 'Enable', - } ); - - const paymentMethodWarningIconElement = await page.$( - `[data-testid="${ paymentMethodWarningIconId }"]` - ); - await expect( paymentMethodWarningIconElement ).toMatchTextContent( - 'cannot be enabled at checkout. Click to expand.' - ); - } ); -} ); From f00666ff70b94d5fc6a3c7075895c47a0ab3de45 Mon Sep 17 00:00:00 2001 From: Francesco Date: Thu, 9 Jan 2025 17:22:56 +0100 Subject: [PATCH 3/5] fix: ECE add-to-cart race condition (#10119) --- changelog/fix-tokenized-ece-applepay-delay | 5 +++++ client/express-checkout/index.js | 17 +++++++++++++---- client/tokenized-express-checkout/index.js | 17 +++++++++++++---- 3 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 changelog/fix-tokenized-ece-applepay-delay diff --git a/changelog/fix-tokenized-ece-applepay-delay b/changelog/fix-tokenized-ece-applepay-delay new file mode 100644 index 00000000000..30409da99e8 --- /dev/null +++ b/changelog/fix-tokenized-ece-applepay-delay @@ -0,0 +1,5 @@ +Significance: patch +Type: fix +Comment: fix: ensure the "add to cart" ECE call is completed before other calls are made. + + diff --git a/client/express-checkout/index.js b/client/express-checkout/index.js index 4cbb279b1c7..f1cbdc5ebb0 100644 --- a/client/express-checkout/index.js +++ b/client/express-checkout/index.js @@ -235,6 +235,7 @@ jQuery( ( $ ) => { return; } + let addToCartPromise = Promise.resolve(); const stripe = await api.getStripe(); const elements = stripe.elements( { @@ -301,7 +302,14 @@ jQuery( ( $ ) => { } // Add products to the cart if everything is right. - wcpayECE.addToCart(); + // we are storing the promise to ensure that the "add to cart" call is completed, + // before the `shippingaddresschange` is triggered when the dialog is opened. + // Otherwise, it might happen that the `shippingaddresschange` is triggered before the "add to cart" call is done, + // which can cause errors. + addToCartPromise = wcpayECE.addToCart(); + addToCartPromise.finally( () => { + addToCartPromise = Promise.resolve(); + } ); } const clickOptions = { @@ -319,9 +327,10 @@ jQuery( ( $ ) => { event.resolve( clickOptions ); } ); - eceButton.on( 'shippingaddresschange', async ( event ) => - shippingAddressChangeHandler( api, event, elements ) - ); + eceButton.on( 'shippingaddresschange', async ( event ) => { + await addToCartPromise; + return shippingAddressChangeHandler( api, event, elements ); + } ); eceButton.on( 'shippingratechange', async ( event ) => shippingRateChangeHandler( api, event, elements ) diff --git a/client/tokenized-express-checkout/index.js b/client/tokenized-express-checkout/index.js index 0ab1ea230f6..924fdc79482 100644 --- a/client/tokenized-express-checkout/index.js +++ b/client/tokenized-express-checkout/index.js @@ -187,6 +187,7 @@ jQuery( ( $ ) => { * @param {Object} options ECE options. */ startExpressCheckoutElement: async ( options ) => { + let addToCartPromise = Promise.resolve(); const stripe = await api.getStripe(); const elements = stripe.elements( { mode: 'payment', @@ -247,7 +248,14 @@ jQuery( ( $ ) => { } // Add products to the cart if everything is right. - getCartApiHandler().addProductToCart(); + // we are storing the promise to ensure that the "add to cart" call is completed, + // before the `shippingaddresschange` is triggered when the dialog is opened. + // Otherwise, it might happen that the `shippingaddresschange` is triggered before the "add to cart" call is done, + // which can cause errors. + addToCartPromise = getCartApiHandler().addProductToCart(); + addToCartPromise.finally( () => { + addToCartPromise = Promise.resolve(); + } ); } const clickOptions = { @@ -270,9 +278,10 @@ jQuery( ( $ ) => { event.resolve( clickOptions ); } ); - eceButton.on( 'shippingaddresschange', async ( event ) => - shippingAddressChangeHandler( event, elements ) - ); + eceButton.on( 'shippingaddresschange', async ( event ) => { + await addToCartPromise; + return shippingAddressChangeHandler( event, elements ); + } ); eceButton.on( 'shippingratechange', async ( event ) => shippingRateChangeHandler( event, elements ) From 700b287dabe3044376160198fdb7602847363e80 Mon Sep 17 00:00:00 2001 From: Allie Mims <60988591+allie500@users.noreply.github.com> Date: Thu, 9 Jan 2025 15:01:36 -0500 Subject: [PATCH 4/5] Update PHP and Xdebug in E2E Dockerfile (#10114) --- changelog/dev-10113-bump-e2e-dockerfile-php-xdebug-versions | 4 ++++ tests/e2e/env/wordpress-xdebug/Dockerfile | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 changelog/dev-10113-bump-e2e-dockerfile-php-xdebug-versions diff --git a/changelog/dev-10113-bump-e2e-dockerfile-php-xdebug-versions b/changelog/dev-10113-bump-e2e-dockerfile-php-xdebug-versions new file mode 100644 index 00000000000..08d6ae0059d --- /dev/null +++ b/changelog/dev-10113-bump-e2e-dockerfile-php-xdebug-versions @@ -0,0 +1,4 @@ +Significance: patch +Type: dev + +Update the PHP version and the Xdebug version used in the E2E testing environment. diff --git a/tests/e2e/env/wordpress-xdebug/Dockerfile b/tests/e2e/env/wordpress-xdebug/Dockerfile index c6dd80eb07d..4019dad8194 100644 --- a/tests/e2e/env/wordpress-xdebug/Dockerfile +++ b/tests/e2e/env/wordpress-xdebug/Dockerfile @@ -1,5 +1,5 @@ -FROM wordpress:6.0.2-php7.4 -RUN pecl install xdebug-2.9.8 \ +FROM wordpress:php8.1 +RUN pecl install xdebug \ && echo 'xdebug.remote_enable=1' >> $PHP_INI_DIR/php.ini \ && echo 'xdebug.remote_port=9000' >> $PHP_INI_DIR/php.ini \ && echo 'xdebug.remote_host=host.docker.internal' >> $PHP_INI_DIR/php.ini \ From 82ac1b9a9aff0643fb6384a3f245993b2596272b Mon Sep 17 00:00:00 2001 From: Eduardo Umpierre Date: Fri, 10 Jan 2025 07:40:25 -0300 Subject: [PATCH 5/5] Convert the Shopper Pay for Order spec to Playwright (#10104) --- ...071-convert-shopper-pay-for-order-e2e-spec | 4 + .../shopper/shopper-pay-for-order.spec.ts | 91 +++++++++++++++++++ tests/e2e-pw/utils/devtools.ts | 40 ++++++++ .../shopper/shopper-pay-for-order.spec.js | 84 ----------------- 4 files changed, 135 insertions(+), 84 deletions(-) create mode 100644 changelog/dev-10071-convert-shopper-pay-for-order-e2e-spec create mode 100644 tests/e2e-pw/specs/shopper/shopper-pay-for-order.spec.ts create mode 100644 tests/e2e-pw/utils/devtools.ts delete mode 100644 tests/e2e/specs/wcpay/shopper/shopper-pay-for-order.spec.js diff --git a/changelog/dev-10071-convert-shopper-pay-for-order-e2e-spec b/changelog/dev-10071-convert-shopper-pay-for-order-e2e-spec new file mode 100644 index 00000000000..b6a0d24707a --- /dev/null +++ b/changelog/dev-10071-convert-shopper-pay-for-order-e2e-spec @@ -0,0 +1,4 @@ +Significance: patch +Type: dev + +Add the Playwright Pay for Order spec and remove the equivalent Puppeteer spec. diff --git a/tests/e2e-pw/specs/shopper/shopper-pay-for-order.spec.ts b/tests/e2e-pw/specs/shopper/shopper-pay-for-order.spec.ts new file mode 100644 index 00000000000..843fad52478 --- /dev/null +++ b/tests/e2e-pw/specs/shopper/shopper-pay-for-order.spec.ts @@ -0,0 +1,91 @@ +/** + * External dependencies + */ +import { test, expect } from '@playwright/test'; + +/** + * Internal dependencies + */ +import { config } from '../../config/default'; +import * as shopper from '../../utils/shopper'; +import * as shopperNavigation from '../../utils/shopper-navigation'; +import * as devtools from '../../utils/devtools'; +import { getMerchant, getShopper } from '../../utils/helpers'; + +const cardTestingPreventionStates = [ + { cardTestingPreventionEnabled: false }, + { cardTestingPreventionEnabled: true }, +]; + +test.describe( 'Shopper > Pay for Order', () => { + cardTestingPreventionStates.forEach( + ( { cardTestingPreventionEnabled } ) => { + test( `should be able to pay for a failed order with card testing protection ${ cardTestingPreventionEnabled }`, async ( { + browser, + } ) => { + const { merchantPage } = await getMerchant( browser ); + const { shopperPage } = await getShopper( browser ); + + // Enable or disable card testing protection. + if ( ! cardTestingPreventionEnabled ) { + await devtools.disableCardTestingProtection( merchantPage ); + } else { + await devtools.enableCardTestingProtection( merchantPage ); + } + + // Attempt to pay with a declined card. + await shopper.addCartProduct( shopperPage ); + await shopper.setupCheckout( + shopperPage, + config.addresses.customer.billing + ); + await shopper.fillCardDetails( + shopperPage, + config.cards.declined + ); + await shopper.placeOrder( shopperPage ); + + await expect( + shopperPage.getByText( 'Your card was declined' ).first() + ).toBeVisible(); + + // Go to the orders page and pay with a basic card. + await shopperNavigation.goToOrders( shopperPage ); + + const payForOrderButton = shopperPage + .locator( '.woocommerce-button.button.pay', { + hasText: 'Pay', + } ) + .first(); + await payForOrderButton.click(); + await shopper.fillCardDetails( + shopperPage, + config.cards.basic + ); + + // Check for the fraud prevenction token presence. + const token = await shopperPage.evaluate( () => { + return ( window as any ).wcpayFraudPreventionToken; + } ); + + if ( cardTestingPreventionEnabled ) { + expect( token ).not.toBeUndefined(); + } else { + expect( token ).toBeUndefined(); + } + + // Click the pay for order button. + await shopper.placeOrder( shopperPage ); + + await expect( + shopperPage.getByText( 'Order received' ).first() + ).toBeVisible(); + + // Disable card testing protection if necessary. + if ( cardTestingPreventionEnabled ) { + await devtools.disableCardTestingProtection( merchantPage ); + } + } ); + } + ); +} ); diff --git a/tests/e2e-pw/utils/devtools.ts b/tests/e2e-pw/utils/devtools.ts new file mode 100644 index 00000000000..0ad37df9b3e --- /dev/null +++ b/tests/e2e-pw/utils/devtools.ts @@ -0,0 +1,40 @@ +/** + * External dependencies + */ +import { Page, expect } from '@playwright/test'; + +const goToDevToolsSettings = ( page: Page ) => + page.goto( 'wp-admin/admin.php?page=wcpaydev', { + waitUntil: 'load', + } ); + +const saveDevToolsSettings = async ( page: Page ) => { + await page.getByRole( 'button', { name: 'Save Changes' } ).click(); + expect( page.getByText( /Settings saved/ ) ).toBeVisible(); +}; + +const getIsCardTestingProtectionEnabled = ( page: Page ) => + page.getByLabel( 'Card testing mitigations enabled' ).isChecked(); + +const toggleCardTestingProtection = ( page: Page ) => + page + .locator( 'label[for="wcpaydev_force_card_testing_protection_on"]' ) + .click(); + +export const enableCardTestingProtection = async ( page: Page ) => { + await goToDevToolsSettings( page ); + + if ( ! ( await getIsCardTestingProtectionEnabled( page ) ) ) { + await toggleCardTestingProtection( page ); + await saveDevToolsSettings( page ); + } +}; + +export const disableCardTestingProtection = async ( page: Page ) => { + await goToDevToolsSettings( page ); + + if ( await getIsCardTestingProtectionEnabled( page ) ) { + await toggleCardTestingProtection( page ); + await saveDevToolsSettings( page ); + } +}; diff --git a/tests/e2e/specs/wcpay/shopper/shopper-pay-for-order.spec.js b/tests/e2e/specs/wcpay/shopper/shopper-pay-for-order.spec.js deleted file mode 100644 index b0ebc0b8696..00000000000 --- a/tests/e2e/specs/wcpay/shopper/shopper-pay-for-order.spec.js +++ /dev/null @@ -1,84 +0,0 @@ -const { uiUnblocked, shopper, merchant } = require( '@woocommerce/e2e-utils' ); -const { - setupProductCheckout, - fillCardDetails, - fillCardDetailsPayForOrder, -} = require( '../../../utils/payments' ); -const config = require( 'config' ); -const { shopperWCP, merchantWCP } = require( '../../../utils' ); - -const cardTestingPreventionStates = [ - { cardTestingPreventionEnabled: false }, - { cardTestingPreventionEnabled: true }, -]; - -describe.each( cardTestingPreventionStates )( - 'Shopper > Pay for Order', - ( { cardTestingPreventionEnabled } ) => { - beforeAll( async () => { - if ( cardTestingPreventionEnabled ) { - await merchant.login(); - await merchantWCP.enableCardTestingProtection(); - await merchant.logout(); - } - await shopper.login(); - await setupProductCheckout( - config.get( 'addresses.customer.billing' ) - ); - } ); - - afterAll( async () => { - await shopper.logout(); - if ( cardTestingPreventionEnabled ) { - await merchant.login(); - await merchantWCP.disableCardTestingProtection(); - await merchant.logout(); - } - } ); - - it( `should be able to pay for a failed order, carding protection ${ cardTestingPreventionEnabled }`, async () => { - // try to pay with a declined card - const declinedCard = config.get( 'cards.declined' ); - await shopperWCP.selectNewPaymentMethod(); - await fillCardDetails( page, declinedCard ); - await expect( page ).toClick( '#place_order' ); - await uiUnblocked(); - await shopperWCP.waitForErrorBanner( - 'Error: Your card was declined.', - 'div.wc-block-components-notice-banner', - 'div.woocommerce-NoticeGroup > ul.woocommerce-error > li' - ); - - // after the card has been declined, go to the order page and pay with a basic card - await shopperWCP.goToOrders(); - - const payButtons = await page.$$( - '.woocommerce-button.button.pay' - ); - const payButton = payButtons.find( - async ( button ) => - ( await page.evaluate( - ( elem ) => elem.innerText, - button - ) ) === 'Pay' - ); - await payButton.click(); - const card = config.get( 'cards.basic' ); - await fillCardDetailsPayForOrder( page, card ); - - // Check the token presence when card testing prevention is enabled. - if ( cardTestingPreventionEnabled ) { - const token = await page.evaluate( () => { - return window.wcpayFraudPreventionToken; - } ); - expect( token ).not.toBeUndefined(); - } - - await expect( page ).toClick( 'button', { text: 'Pay for order' } ); - await page.waitForNavigation( { - waitUntil: 'networkidle0', - } ); - await expect( page ).toMatchTextContent( 'Order received' ); - } ); - } -);