From 23f45612832d33bb36d916644f771887b3a4c216 Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Fri, 19 Sep 2025 10:57:20 -0300 Subject: [PATCH 01/11] Removing PRBs frontend code --- client/blocks/index.js | 9 +- .../payment-request/apple-pay-preview.js | 2 - .../blocks/payment-request/branded-buttons.js | 76 ----- client/blocks/payment-request/constants.js | 1 - .../blocks/payment-request/custom-button.js | 23 -- .../blocks/payment-request/event-handlers.js | 215 ------------- client/blocks/payment-request/hooks.js | 218 ------------- client/blocks/payment-request/index.js | 77 ----- .../payment-request/login-confirmation.js | 32 -- .../payment-request-express.js | 188 ----------- client/blocks/upe/index.js | 33 +- .../amazon-pay-settings/amazon-pay-page.js | 2 +- .../payment-request-button-preview.test.js | 115 ------- ...payment-request-settings-locations.test.js | 163 ---------- .../payment-request-settings.test.js | 146 --------- .../express-checkout-button-preview.js | 129 -------- .../payment-request-settings/index.js | 11 - .../payment-request-button-preview.js | 139 -------- .../payment-request-enable-section.js | 31 -- .../payment-request-page.js | 62 ---- .../payment-request-settings-section.js | 304 ------------------ .../payment-request-settings/style.scss | 72 ----- .../payment-request-settings/utils/utils.js | 15 - webpack.config.js | 2 - 24 files changed, 15 insertions(+), 2050 deletions(-) delete mode 100644 client/blocks/payment-request/apple-pay-preview.js delete mode 100644 client/blocks/payment-request/branded-buttons.js delete mode 100644 client/blocks/payment-request/constants.js delete mode 100644 client/blocks/payment-request/custom-button.js delete mode 100644 client/blocks/payment-request/event-handlers.js delete mode 100644 client/blocks/payment-request/hooks.js delete mode 100644 client/blocks/payment-request/index.js delete mode 100644 client/blocks/payment-request/login-confirmation.js delete mode 100644 client/blocks/payment-request/payment-request-express.js delete mode 100644 client/entrypoints/payment-request-settings/__tests__/payment-request-button-preview.test.js delete mode 100644 client/entrypoints/payment-request-settings/__tests__/payment-request-settings-locations.test.js delete mode 100644 client/entrypoints/payment-request-settings/__tests__/payment-request-settings.test.js delete mode 100644 client/entrypoints/payment-request-settings/express-checkout-button-preview.js delete mode 100644 client/entrypoints/payment-request-settings/index.js delete mode 100644 client/entrypoints/payment-request-settings/payment-request-button-preview.js delete mode 100644 client/entrypoints/payment-request-settings/payment-request-enable-section.js delete mode 100644 client/entrypoints/payment-request-settings/payment-request-page.js delete mode 100644 client/entrypoints/payment-request-settings/payment-request-settings-section.js delete mode 100644 client/entrypoints/payment-request-settings/style.scss delete mode 100644 client/entrypoints/payment-request-settings/utils/utils.js diff --git a/client/blocks/index.js b/client/blocks/index.js index 68a9e1ee9d..e2cb496450 100644 --- a/client/blocks/index.js +++ b/client/blocks/index.js @@ -1,12 +1,5 @@ -import { - registerPaymentMethod, - registerExpressPaymentMethod, -} from '@woocommerce/blocks-registry'; +import { registerPaymentMethod } from '@woocommerce/blocks-registry'; import stripeCcPaymentMethod from './credit-card'; -import paymentRequestPaymentMethod from './payment-request'; // Register Stripe Credit Card. registerPaymentMethod( stripeCcPaymentMethod ); - -// Register Stripe Payment Request. -registerExpressPaymentMethod( paymentRequestPaymentMethod ); diff --git a/client/blocks/payment-request/apple-pay-preview.js b/client/blocks/payment-request/apple-pay-preview.js deleted file mode 100644 index cc740802ca..0000000000 --- a/client/blocks/payment-request/apple-pay-preview.js +++ /dev/null @@ -1,2 +0,0 @@ -export const applePayImage = - "data:image/svg+xml,%3Csvg width='264' height='48' viewBox='0 0 264 48' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='264' height='48' rx='3' fill='black'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M125.114 16.6407C125.682 15.93 126.067 14.9756 125.966 14C125.135 14.0415 124.121 14.549 123.533 15.2602C123.006 15.8693 122.539 16.8641 122.661 17.7983C123.594 17.8797 124.526 17.3317 125.114 16.6407Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M125.955 17.982C124.601 17.9011 123.448 18.7518 122.801 18.7518C122.154 18.7518 121.163 18.0224 120.092 18.0421C118.696 18.0629 117.402 18.8524 116.694 20.1079C115.238 22.6196 116.31 26.3453 117.726 28.3909C118.414 29.4028 119.242 30.5174 120.334 30.4769C121.366 30.4365 121.77 29.8087 123.024 29.8087C124.277 29.8087 124.641 30.4769 125.733 30.4567C126.865 30.4365 127.573 29.4443 128.261 28.4313C129.049 27.2779 129.373 26.1639 129.393 26.1027C129.373 26.0825 127.209 25.2515 127.189 22.7606C127.169 20.6751 128.888 19.6834 128.969 19.6217C127.998 18.1847 126.481 18.0224 125.955 17.982Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M136.131 23.1804H138.834C140.886 23.1804 142.053 22.0752 142.053 20.1592C142.053 18.2432 140.886 17.1478 138.845 17.1478H136.131V23.1804ZM139.466 15.1582C142.411 15.1582 144.461 17.1903 144.461 20.1483C144.461 23.1172 142.369 25.1596 139.392 25.1596H136.131V30.3498H133.775V15.1582H139.466Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M152.198 26.224V25.3712L149.579 25.5397C148.106 25.6341 147.339 26.182 147.339 27.14C147.339 28.0664 148.138 28.6667 149.39 28.6667C150.988 28.6667 152.198 27.6449 152.198 26.224ZM145.046 27.2032C145.046 25.2551 146.529 24.1395 149.263 23.971L152.198 23.7922V22.9498C152.198 21.7181 151.388 21.0442 149.947 21.0442C148.758 21.0442 147.896 21.6548 147.717 22.5916H145.592C145.656 20.6232 147.507 19.1914 150.01 19.1914C152.703 19.1914 154.459 20.602 154.459 22.7917V30.351H152.282V28.5298H152.229C151.609 29.719 150.241 30.4666 148.758 30.4666C146.571 30.4666 145.046 29.1612 145.046 27.2032Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M156.461 34.4145V32.5934C156.608 32.6141 156.965 32.6354 157.155 32.6354C158.196 32.6354 158.785 32.1932 159.142 31.0564L159.353 30.3824L155.366 19.3281H157.827L160.604 28.298H160.657L163.434 19.3281H165.832L161.698 30.9402C160.752 33.6038 159.668 34.4778 157.376 34.4778C157.197 34.4778 156.618 34.4565 156.461 34.4145Z' fill='white'/%3E%3C/svg%3E%0A"; diff --git a/client/blocks/payment-request/branded-buttons.js b/client/blocks/payment-request/branded-buttons.js deleted file mode 100644 index eb637f150c..0000000000 --- a/client/blocks/payment-request/branded-buttons.js +++ /dev/null @@ -1,76 +0,0 @@ -import { useState, useEffect } from '@wordpress/element'; -import { getBlocksConfiguration } from 'wcstripe/blocks/utils'; - -export const shouldUseGooglePayBrand = () => { - const ua = window.navigator.userAgent.toLowerCase(); - const isChrome = - /chrome/.test( ua ) && - ! /edge|edg|opr|brave\//.test( ua ) && - window.navigator.vendor === 'Google Inc.'; - // newer versions of Brave do not have the userAgent string - const isBrave = isChrome && window.navigator.brave; - return isChrome && ! isBrave; -}; - -const useLocalizedGoogleSvg = ( type, theme, locale ) => { - // If we're using the short button type (i.e. logo only) make sure we get the logo only SVG. - const googlePlaySvg = - type === 'long' - ? `https://www.gstatic.com/instantbuy/svg/${ theme }/${ locale }.svg` - : `https://www.gstatic.com/instantbuy/svg/${ theme }_gpay.svg`; - - const [ url, setUrl ] = useState( googlePlaySvg ); - - useEffect( () => { - const im = document.createElement( 'img' ); - im.addEventListener( 'error', () => { - setUrl( - `https://www.gstatic.com/instantbuy/svg/${ theme }/en.svg` - ); - } ); - im.src = url; - }, [ url, theme ] ); - - return url; -}; - -export const GooglePayButton = ( { onButtonClicked } ) => { - const { - theme = 'dark', - locale = 'en', - height = '44', - } = getBlocksConfiguration()?.button; - - const allowedTypes = [ 'short', 'long' ]; - const { branded_type } = getBlocksConfiguration()?.button; // eslint-disable-line camelcase - const type = allowedTypes.includes( branded_type ) ? branded_type : 'long'; // eslint-disable-line camelcase - - // Allowed themes for Google Pay button image are 'dark' and 'light'. - // We may include 'light-outline' as a theme, so we ensure only 'dark' or 'light' are possible - // here. - const gpayButtonTheme = theme === 'dark' ? 'dark' : 'light'; - - // Let's make sure the localized Google Pay button exists, otherwise we fall back to the - // english version. This test element is not used on purpose. - const backgroundUrl = useLocalizedGoogleSvg( - type, - gpayButtonTheme, - locale - ); - - return ( - - ); -}; diff --git a/client/blocks/payment-request/event-handlers.js b/client/blocks/payment-request/event-handlers.js deleted file mode 100644 index 7eaf310941..0000000000 --- a/client/blocks/payment-request/event-handlers.js +++ /dev/null @@ -1,215 +0,0 @@ -import $ from 'jquery'; -import { - updateShippingOptions, - updateShippingDetails, - createOrder, -} from 'wcstripe/api/blocks'; -import { getBlocksConfiguration } from 'wcstripe/blocks/utils'; -import { - PAYMENT_INTENT_STATUS_REQUIRES_CAPTURE, - PAYMENT_INTENT_STATUS_SUCCEEDED, -} from 'wcstripe/stripe-utils/constants'; - -const shippingAddressChangeHandler = ( paymentRequestType ) => ( evt ) => { - const { shippingAddress } = evt; - - // Update the payment request shipping information address. - updateShippingOptions( shippingAddress, paymentRequestType ).then( - ( response ) => { - evt.updateWith( { - status: response.result, - shippingOptions: response.shipping_options, - total: response.total, - displayItems: response.displayItems, - } ); - } - ); -}; - -const shippingOptionChangeHandler = ( evt ) => { - const { shippingOption } = evt; - - // Update the shipping rates for the order. - updateShippingDetails( shippingOption ).then( ( response ) => { - if ( response.result === 'success' ) { - evt.updateWith( { - status: 'success', - total: response.total, - displayItems: response.displayItems, - } ); - } - - if ( response.result === 'fail' ) { - evt.updateWith( { status: 'fail' } ); - } - } ); -}; - -/** - * Helper function. Returns payment intent information from the provided URL. - * If no information is embedded in the URL this function returns `undefined`. - * - * @param {string} url - The url to check for partials. - * - * @return {Object|undefined} The object containing `type`, `clientSecret`, and - * `redirectUrl`. Undefined if no partails embedded in the url. - */ -const getRedirectUrlPartials = ( url ) => { - const partials = url.match( /^#?confirm-(pi|si)-([^:]+):(.+)$/ ); - - if ( ! partials || partials.length < 4 ) { - return undefined; - } - - const type = partials[ 1 ]; - const clientSecret = partials[ 2 ]; - const redirectUrl = decodeURIComponent( partials[ 3 ] ); - - return { - type, - clientSecret, - redirectUrl, - }; -}; - -/** - * Helper function. Requests that the provided intent (identified by the secret) is be - * handled by Stripe. Returns a promise from Stripe. - * - * @param {Object} stripe - The stripe object. - * @param {string} intentType - The type of intent. Either `pi` or `si`. - * @param {string} clientSecret - Client secret returned from Stripe. - * - * @return {Promise} A promise from Stripe with the confirmed intent or an error. - */ -const requestIntentConfirmation = ( stripe, intentType, clientSecret ) => { - const isSetupIntent = intentType === 'si'; - - if ( isSetupIntent ) { - return stripe.handleCardSetup( clientSecret ); - } - return stripe.handleCardPayment( clientSecret ); -}; - -/** - * Helper function. Returns the payment or setup intent from a given confirmed intent. - * - * @param {Object} intent - The confirmed intent. - * @param {string} intentType - The payment intent's type. Either `pi` or `si`. - * - * @return {Object} The Stripe payment or setup intent. - */ -const getIntentFromConfirmation = ( intent, intentType ) => { - const isSetupIntent = intentType === 'si'; - - if ( isSetupIntent ) { - return intent.setupIntent; - } - return intent.paymentIntent; -}; - -const doesIntentRequireCapture = ( intent ) => { - return intent.status === PAYMENT_INTENT_STATUS_REQUIRES_CAPTURE; -}; - -const didIntentSucceed = ( intent ) => { - return intent.status === PAYMENT_INTENT_STATUS_SUCCEEDED; -}; - -/** - * Helper function; part of a promise chain. - * Receives a possibly confirmed payment intent from Stripe and proceeds to charge the - * payment method of the intent was confirmed successfully. - * - * @param {string} redirectUrl - The URL to redirect to after a successful payment. - * @param {string} intentType - The type of the payment intent. Either `pi` or `si`. - */ -const handleIntentConfirmation = - ( redirectUrl, intentType ) => ( confirmation ) => { - if ( confirmation.error ) { - throw confirmation.error; - } - - const intent = getIntentFromConfirmation( confirmation, intentType ); - if ( - doesIntentRequireCapture( intent ) || - didIntentSucceed( intent ) - ) { - // If the 3DS verification was successful we can proceed with checkout as usual. - window.location = redirectUrl; - } - }; - -/** - * Helper function; part of a promise chain. - * Receives the response from our server after we attempt to create an order through - * our AJAX API, proceeds with payment if possible, otherwise attempts to confirm the - * payment (i.e. 3DS verification) through Stripe. - * - * @param {Object} stripe - The Stripe JS object. - * @param {Object} evt - The `source` event from the Stripe payment request button. - * @param {Function} setExpressPaymentError - Used to show error messages to the customer. - */ -const performPayment = - ( stripe, evt, setExpressPaymentError ) => ( createOrderResponse ) => { - if ( createOrderResponse.result === 'success' ) { - evt.complete( 'success' ); - - const partials = getRedirectUrlPartials( - createOrderResponse.redirect - ); - - // If no information is embedded in the URL that means the payment doesn't need - // verification and we can proceed as usual. - if ( ! partials || partials.length < 4 ) { - window.location = createOrderResponse.redirect; - return; - } - - const { type, clientSecret, redirectUrl } = partials; - - // The payment requires 3DS verification, so we try to take care of that here. - requestIntentConfirmation( stripe, type, clientSecret ) - .then( handleIntentConfirmation( redirectUrl, type ) ) - .catch( ( error ) => { - setExpressPaymentError( error.message ); - - // Report back to the server. - $.get( redirectUrl + '&is_ajax' ); - } ); - } else { - evt.complete( 'fail' ); - - // WooCommerce returns a message embedded in a notice via HTML here, so we need - // to extract the actual message from the notice. - const div = document.createElement( 'div' ); - div.innerHTML = createOrderResponse.messages; - const errorMessage = div?.firstElementChild?.textContent ?? ''; - - setExpressPaymentError( errorMessage ); - } - }; - -const paymentProcessingHandler = - ( stripe, paymentRequestType, setExpressPaymentError ) => ( evt ) => { - const allowPrepaidCards = - getBlocksConfiguration()?.stripe?.allow_prepaid_card === 'yes'; - - // Check if we allow prepaid cards. - if ( ! allowPrepaidCards && evt?.source?.card?.funding === 'prepaid' ) { - setExpressPaymentError( - getBlocksConfiguration()?.i18n?.no_prepaid_card - ); - } else { - // Create the order and attempt to pay. - createOrder( evt, paymentRequestType ).then( - performPayment( stripe, evt, setExpressPaymentError ) - ); - } - }; - -export { - shippingAddressChangeHandler, - shippingOptionChangeHandler, - paymentProcessingHandler, -}; diff --git a/client/blocks/payment-request/hooks.js b/client/blocks/payment-request/hooks.js deleted file mode 100644 index 3b74f3d787..0000000000 --- a/client/blocks/payment-request/hooks.js +++ /dev/null @@ -1,218 +0,0 @@ -import { - shippingAddressChangeHandler, - shippingOptionChangeHandler, - paymentProcessingHandler, -} from './event-handlers'; -import { displayLoginConfirmation } from './login-confirmation'; -import { useState, useEffect, useCallback } from '@wordpress/element'; -import { - getBlocksConfiguration, - createPaymentRequestUsingCart, - updatePaymentRequestUsingCart, -} from 'wcstripe/blocks/utils'; -import { getCartDetails } from 'wcstripe/api/blocks'; - -/** - * This hook takes care of creating a payment request and making sure - * you can pay through said payment request. - * - * @param {Object} stripe The stripe object used to create the payment request. - * @param {boolean} needsShipping A value from the Block checkout that indicates whether shipping - * is required or not. - * @param {Object} billing - The billing data from the checkout or cart block. - * - * @return {Array} An array; first element is the payment request; second element is the payment - * requests type. - */ -export const usePaymentRequest = ( stripe, needsShipping, billing ) => { - const [ paymentRequest, setPaymentRequest ] = useState( null ); - const [ paymentRequestType, setPaymentRequestType ] = useState( null ); - const [ isUpdatingPaymentRequest, setIsUpdatingPaymentRequest ] = - useState( false ); - - // Create a payment request if: - // a) Stripe object is loaded; and - // b) There is no payment request created already. - useEffect( () => { - if ( ! stripe ) { - return; - } - const createPaymentRequest = async () => { - const cart = await getCartDetails(); - const pr = createPaymentRequestUsingCart( stripe, cart ); - const result = await pr.canMakePayment(); - - if ( result ) { - setPaymentRequest( pr ); - setPaymentRequestType( () => { - if ( result.applePay ) { - return 'apple_pay'; - } - if ( result.googlePay ) { - return 'google_pay'; - } - return 'payment_request_api'; - } ); - } else { - setPaymentRequest( null ); - } - }; - createPaymentRequest(); - }, [ stripe, needsShipping ] ); - - useEffect( () => { - if ( ! paymentRequest ) { - return; - } - - const updatePaymentRequest = async () => { - setIsUpdatingPaymentRequest( true ); - const cart = await getCartDetails(); - updatePaymentRequestUsingCart( paymentRequest, cart ); - setIsUpdatingPaymentRequest( false ); - }; - updatePaymentRequest(); - }, [ - paymentRequest, - billing.cartTotal, - billing.cartTotalItems, - billing.currency.code, - ] ); - - return [ paymentRequest, paymentRequestType, isUpdatingPaymentRequest ]; -}; - -/** - * Returns an onClick handler for payment request buttons. Checks if login is required, resets - * the error state, syncs the payment request with the block, and calls the provided click handler. - * - * @param {string} paymentRequestType - The payment request type. - * @param {Function} setExpressPaymentError - Used to set the error state. - * @param {Function} onClick - The onClick function that should be called on click. - * - * @return {Function} An onClick handler for the payment request buttons. - */ -export const useOnClickHandler = ( - paymentRequestType, - setExpressPaymentError, - onClick -) => { - return useCallback( - ( evt, pr ) => { - // If login is required, display redirect confirmation dialog. - if ( getBlocksConfiguration()?.login_confirmation ) { - evt.preventDefault(); - displayLoginConfirmation( paymentRequestType ); - return; - } - - // Reset any Payment Request errors. - setExpressPaymentError( '' ); - - // Call the Blocks API `onClick` handler. - onClick(); - - // We must manually call payment request `show()` for custom buttons. - if ( pr ) { - pr.show(); - } - }, - [ paymentRequestType, setExpressPaymentError, onClick ] - ); -}; - -/** - * Adds a shipping address change event handler to the provided payment request. Updates the - * order's shipping address when necessary. - * - * @param {Object} paymentRequest - The payment request object. - * @param {string} paymentRequestType - The payment request type. - */ -export const useShippingAddressUpdateHandler = ( - paymentRequest, - paymentRequestType -) => { - useEffect( () => { - const handler = paymentRequest?.on( - 'shippingaddresschange', - shippingAddressChangeHandler( paymentRequestType ) - ); - - return () => { - // Need to use `?.` here in case paymentRequest is null. - handler?.removeEventListener( 'shippingaddresschange' ); - }; - }, [ paymentRequest, paymentRequestType ] ); -}; - -/** - * Adds a shipping option change event handler to the provided payment request. - * - * @param {Object} paymentRequest - The payment request object. - * @param {string} paymentRequestType - The payment request type. - */ -export const useShippingOptionChangeHandler = ( - paymentRequest, - paymentRequestType -) => { - useEffect( () => { - const handler = paymentRequest?.on( - 'shippingoptionchange', - shippingOptionChangeHandler - ); - - return () => { - // Need to use `?.` here in case paymentRequest is null. - handler?.removeEventListener( 'shippingoptionchange' ); - }; - }, [ paymentRequest, paymentRequestType ] ); -}; - -/** - * Adds a payment event handler to the provided payment request. - * - * @param {Object} stripe - The stripe object used to confirm and create a payment intent. - * @param {Object} paymentRequest - The payment request object. - * @param {string} paymentRequestType - The payment request type. - * @param {Function} setExpressPaymentError - A function used to expose an error message to show - * the customer. - */ -export const useProcessPaymentHandler = ( - stripe, - paymentRequest, - paymentRequestType, - setExpressPaymentError -) => { - useEffect( () => { - const handler = paymentRequest?.on( - 'paymentmethod', - paymentProcessingHandler( - stripe, - paymentRequestType, - setExpressPaymentError - ) - ); - - return () => { - // Need to use `?.` here in case paymentRequest is null. - handler?.removeEventListener( 'paymentmethod' ); - }; - }, [ stripe, paymentRequest, paymentRequestType, setExpressPaymentError ] ); -}; - -/** - * Adds a cancellation handler to the provided payment request. - * - * @param {Object} paymentRequest - The payment request object. - * @param {Function} onClose - A function from the Blocks API. - */ -export const useCancelHandler = ( paymentRequest, onClose ) => { - useEffect( () => { - const handler = paymentRequest?.on( 'cancel', onClose ); - - return () => { - // Need to use `?.` here in case paymentRequest is null. - handler?.removeEventListener( 'cancel' ); - }; - }, [ paymentRequest, onClose ] ); -}; diff --git a/client/blocks/payment-request/index.js b/client/blocks/payment-request/index.js deleted file mode 100644 index cc94731afd..0000000000 --- a/client/blocks/payment-request/index.js +++ /dev/null @@ -1,77 +0,0 @@ -import { PAYMENT_METHOD_NAME } from './constants'; -import { PaymentRequestExpress } from './payment-request-express'; -import { applePayImage } from './apple-pay-preview'; -import { __ } from '@wordpress/i18n'; -import { loadStripe } from 'wcstripe/blocks/load-stripe'; -import { - getBlocksConfiguration, - createPaymentRequestUsingCart, -} from 'wcstripe/blocks/utils'; - -const ApplePayPreview = () => ; - -const componentStripePromise = loadStripe(); - -const supports = { - features: getBlocksConfiguration()?.supports ?? [], -}; -if ( getBlocksConfiguration().isAdmin ?? false ) { - supports.style = getBlocksConfiguration()?.style ?? []; -} - -const paymentRequestPaymentMethod = { - name: PAYMENT_METHOD_NAME, - title: 'Stripe', - description: __( - 'This will show users the ApplePay, GooglePay, or Stripe Link button depending on their browser and logged in status.', - 'woocommerce-gateway-stripe' - ), - gatewayId: 'stripe', - content: , - edit: , - canMakePayment: ( cartData ) => { - // If in the editor context, always return true to display the `edit` prop preview. - // https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues/4101. - if ( getBlocksConfiguration()?.isAdmin ?? false ) { - return true; - } - - if ( ! getBlocksConfiguration()?.shouldShowPaymentRequestButton ) { - return false; - } - - return loadStripe().then( ( stripe ) => { - // Create a payment request and check if we can make a payment to determine whether to - // show the Payment Request Button or not. This is necessary because a browser might be - // able to load the Stripe JS object, but not support Payment Requests. - const fakeCart = { - order_data: { - total: { - label: 'Total', - amount: parseInt( - cartData?.cartTotals?.total_price ?? 0, - 10 - ), - pending: true, - }, - currency: - cartData?.cartTotals?.currency_code?.toLowerCase(), - country_code: - getBlocksConfiguration()?.baseLocation?.country, - displayItems: [], - }, - shipping_required: false, - }; - const paymentRequest = createPaymentRequestUsingCart( - stripe, - fakeCart - ); - - return paymentRequest.canMakePayment(); - } ); - }, - paymentMethodId: 'stripe', - supports, -}; - -export default paymentRequestPaymentMethod; diff --git a/client/blocks/payment-request/login-confirmation.js b/client/blocks/payment-request/login-confirmation.js deleted file mode 100644 index bb670cfb81..0000000000 --- a/client/blocks/payment-request/login-confirmation.js +++ /dev/null @@ -1,32 +0,0 @@ -import { getBlocksConfiguration } from 'wcstripe/blocks/utils'; - -/** - * Displays a `confirm` dialog which leads to a redirect. - * - * @param {string} paymentRequestType Can be either apple_pay, google_pay or payment_request_api. - */ -export const displayLoginConfirmation = ( paymentRequestType ) => { - if ( ! getBlocksConfiguration()?.login_confirmation ) { - return; - } - - let message = getBlocksConfiguration()?.login_confirmation?.message; - - // Replace dialog text with specific payment request type "Apple Pay" or "Google Pay". - if ( paymentRequestType !== 'payment_request_api' ) { - message = message.replace( - /\*\*.*?\*\*/, - paymentRequestType === 'apple_pay' ? 'Apple Pay' : 'Google Pay' - ); - } - - // Remove asterisks from string. - message = message.replace( /\*\*/g, '' ); - - // eslint-disable-next-line no-alert, no-undef - if ( confirm( message ) ) { - // Redirect to my account page. - window.location.href = - getBlocksConfiguration()?.login_confirmation?.redirect_url; - } -}; diff --git a/client/blocks/payment-request/payment-request-express.js b/client/blocks/payment-request/payment-request-express.js deleted file mode 100644 index 28f49a5047..0000000000 --- a/client/blocks/payment-request/payment-request-express.js +++ /dev/null @@ -1,188 +0,0 @@ -import { - Elements, - PaymentRequestButtonElement, - useStripe, -} from '@stripe/react-stripe-js'; -import { GooglePayButton, shouldUseGooglePayBrand } from './branded-buttons'; -import { CustomButton } from './custom-button'; -import { - usePaymentRequest, - useProcessPaymentHandler, - useShippingAddressUpdateHandler, - useShippingOptionChangeHandler, - useOnClickHandler, - useCancelHandler, -} from './hooks'; -import { __ } from '@wordpress/i18n'; -import { useEffect } from '@wordpress/element'; -import { getBlocksConfiguration } from 'wcstripe/blocks/utils'; - -/** - * @typedef {import('../stripe-utils/type-defs').Stripe} Stripe - * @typedef {import('../stripe-utils/type-defs').StripePaymentRequest} StripePaymentRequest - * @typedef {import('@woocommerce/type-defs/registered-payment-method-props').RegisteredPaymentMethodProps} RegisteredPaymentMethodProps - */ - -/** - * @typedef {Object} WithStripe - * - * @property {Stripe} [stripe] Stripe api (might not be present) - */ - -/** - * @typedef {RegisteredPaymentMethodProps & WithStripe} StripeRegisteredPaymentMethodProps - */ - -/** - * PaymentRequestExpressComponent - * - * @param {StripeRegisteredPaymentMethodProps} props Incoming props - */ -const PaymentRequestExpressComponent = ( { - billing, - components, - shippingData, - onClick, - onClose, - setExpressPaymentError, - buttonAttributes, -} ) => { - const stripe = useStripe(); - const { needsShipping } = shippingData; - - /* Set up payment request and its event handlers. */ - const [ paymentRequest, paymentRequestType, isUpdatingPaymentRequest ] = - usePaymentRequest( stripe, needsShipping, billing ); - useShippingAddressUpdateHandler( paymentRequest, paymentRequestType ); - useShippingOptionChangeHandler( paymentRequest, paymentRequestType ); - useProcessPaymentHandler( - stripe, - paymentRequest, - paymentRequestType, - setExpressPaymentError - ); - const onPaymentRequestButtonClick = useOnClickHandler( - paymentRequestType, - setExpressPaymentError, - onClick - ); - useCancelHandler( paymentRequest, onClose ); - - useEffect( () => { - if ( paymentRequest ) { - const orderAttribution = window?.wc_order_attribution; - if ( orderAttribution ) { - orderAttribution.setOrderTracking( - orderAttribution.params.allowTracking - ); - } - } - }, [ paymentRequest ] ); - - // locale is not a valid value for the paymentRequestButton style. - // Make sure `theme` defaults to 'dark' if it's not found in the server provided configuration. - let { - type = 'default', - theme = 'dark', - height = '48', - } = getBlocksConfiguration()?.button; - - // If we are on the checkout block, we receive button attributes which overwrite the extension specific settings - if ( typeof buttonAttributes !== 'undefined' ) { - height = buttonAttributes.height || height; - } - - const paymentRequestButtonStyle = { - paymentRequestButton: { - type, - theme, - height: `${ height }px`, - }, - }; - const isBranded = getBlocksConfiguration()?.button?.is_branded; - const brandedType = getBlocksConfiguration()?.button?.branded_type; - const isCustom = getBlocksConfiguration()?.button?.is_custom; - - if ( ! paymentRequest ) { - return null; - } - - const { LoadingMask } = components; - - if ( isCustom ) { - return ( - - { - onPaymentRequestButtonClick( evt, paymentRequest ); - } } - /> - - ); - } - - if ( isBranded && shouldUseGooglePayBrand() ) { - return ( - - { - onPaymentRequestButtonClick( evt, paymentRequest ); - } } - /> - - ); - } - - if ( isBranded ) { - // Not implemented branded buttons default to Stripe's button. - // Apple Pay buttons can also fall back to Stripe's button, as it's already branded. - // Set button type to default or buy, depending on branded type, to avoid issues with Stripe. - paymentRequestButtonStyle.paymentRequestButton.type = - brandedType === 'long' ? 'buy' : 'default'; - } - - return ( - - - - ); -}; - -/** - * PaymentRequestExpress with stripe provider - * - * @param {StripeRegisteredPaymentMethodProps} props - */ -export const PaymentRequestExpress = ( props ) => { - const { stripe } = props; - return ( - - - - - ); -}; diff --git a/client/blocks/upe/index.js b/client/blocks/upe/index.js index 96936280d7..955cb76563 100644 --- a/client/blocks/upe/index.js +++ b/client/blocks/upe/index.js @@ -10,7 +10,6 @@ import { PAYMENT_METHOD_LINK, } from '../../stripe-utils/constants'; import { updateTokenLabelsWhenLoaded } from './token-label-updater.js'; -import paymentRequestPaymentMethod from 'wcstripe/blocks/payment-request'; import { expressCheckoutElementAmazonPay, expressCheckoutElementApplePay, @@ -59,25 +58,19 @@ Object.entries( paymentMethodsConfig ) registerPaymentMethod( upeElement( method, api, config ) ); } ); -if ( getBlocksConfiguration()?.isECEEnabled ) { - // Register Express Checkout Elements. - if ( - getBlocksConfiguration()?.isAmazonPayAvailable && // Hide behind feature flag so the editor does not show the button. - getBlocksConfiguration()?.isAmazonPayEnabled - ) { - registerExpressPaymentMethod( expressCheckoutElementAmazonPay( api ) ); - } - if ( getBlocksConfiguration()?.isPaymentRequestEnabled ) { - registerExpressPaymentMethod( expressCheckoutElementApplePay( api ) ); - registerExpressPaymentMethod( expressCheckoutElementGooglePay( api ) ); - } - if ( getBlocksConfiguration()?.isLinkEnabled ) { - registerExpressPaymentMethod( expressCheckoutElementStripeLink( api ) ); - } -} else { - // Register Stripe Payment Request. - // TODO: We can remove this once we're sure everyone on the new checkout (UPE) has been migrated to ECE. - registerExpressPaymentMethod( paymentRequestPaymentMethod ); +// Register Express Checkout Elements. +if ( + getBlocksConfiguration()?.isAmazonPayAvailable && // Hide behind feature flag so the editor does not show the button. + getBlocksConfiguration()?.isAmazonPayEnabled +) { + registerExpressPaymentMethod( expressCheckoutElementAmazonPay( api ) ); +} +if ( getBlocksConfiguration()?.isPaymentRequestEnabled ) { + registerExpressPaymentMethod( expressCheckoutElementApplePay( api ) ); + registerExpressPaymentMethod( expressCheckoutElementGooglePay( api ) ); +} +if ( getBlocksConfiguration()?.isLinkEnabled ) { + registerExpressPaymentMethod( expressCheckoutElementStripeLink( api ) ); } // Update token labels when the checkout form is loaded. diff --git a/client/entrypoints/amazon-pay-settings/amazon-pay-page.js b/client/entrypoints/amazon-pay-settings/amazon-pay-page.js index b6a99a309d..affcd78999 100644 --- a/client/entrypoints/amazon-pay-settings/amazon-pay-page.js +++ b/client/entrypoints/amazon-pay-settings/amazon-pay-page.js @@ -7,7 +7,7 @@ import SettingsSection from 'wcstripe/settings/settings-section'; import SettingsLayout from 'wcstripe/settings/settings-layout'; import LoadableSettingsSection from 'wcstripe/settings/loadable-settings-section'; import SaveSettingsSection from 'wcstripe/settings/save-settings-section'; -import '../payment-request-settings/style.scss'; +import '../express-checkout/styles.scss'; const EnableDescription = () => ( <> diff --git a/client/entrypoints/payment-request-settings/__tests__/payment-request-button-preview.test.js b/client/entrypoints/payment-request-settings/__tests__/payment-request-button-preview.test.js deleted file mode 100644 index 36268bad7a..0000000000 --- a/client/entrypoints/payment-request-settings/__tests__/payment-request-button-preview.test.js +++ /dev/null @@ -1,115 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import { useStripe } from '@stripe/react-stripe-js'; -import PaymentRequestsButtonPreview from '../payment-request-button-preview'; -import { shouldUseGooglePayBrand } from '../utils/utils'; - -// We need to mock the actual module being used by `` in the `@wordpress/components` module -const realPathToA11yModule = - '@wordpress/components/node_modules/@wordpress/a11y'; - -jest.mock( realPathToA11yModule, () => ( { - ...jest.requireActual( realPathToA11yModule ), - speak: jest.fn(), -} ) ); - -jest.mock( '../utils/utils', () => ( { - shouldUseGooglePayBrand: jest.fn(), -} ) ); - -jest.mock( '@stripe/react-stripe-js', () => ( { - PaymentRequestButtonElement: jest - .fn() - .mockReturnValue( ), - useStripe: jest.fn(), -} ) ); - -jest.mock( 'wcstripe/data', () => ( { - usePaymentRequestButtonType: jest.fn().mockReturnValue( [ 'buy' ] ), - usePaymentRequestButtonSize: jest.fn().mockReturnValue( [ 'default' ] ), - usePaymentRequestButtonTheme: jest.fn().mockReturnValue( [ 'dark' ] ), -} ) ); - -describe( 'PaymentRequestsButtonPreview', () => { - const canMakePaymentMock = jest.fn(); - - beforeEach( () => { - shouldUseGooglePayBrand.mockReturnValue( true ); - useStripe.mockReturnValue( { - paymentRequest: () => ( { - canMakePayment: canMakePaymentMock, - } ), - } ); - canMakePaymentMock.mockResolvedValue( {} ); - } ); - - afterEach( () => { - jest.clearAllMocks(); - } ); - - it( 'displays Google Chrome and Google Pay when page is in Safari', async () => { - shouldUseGooglePayBrand.mockReturnValue( false ); - - render( ); - - expect( - await screen.findByText( - 'To preview the Google Pay button, view this page in the Google Chrome browser.' - ) - ).toBeInTheDocument(); - expect( screen.queryByText( /Safari/ ) ).not.toBeInTheDocument(); - } ); - - it( 'displays Safari Apple Pay when page is in Google Chrome', async () => { - shouldUseGooglePayBrand.mockReturnValue( true ); - - render( ); - - expect( - await screen.findByText( - 'To preview the Apple Pay button, view this page in the Safari browser.' - ) - ).toBeInTheDocument(); - expect( screen.queryByText( /Google Chrome/ ) ).not.toBeInTheDocument(); - } ); - - it( 'displays an info notice if stripe is falsy', async () => { - useStripe.mockReturnValue( null ); - - render( ); - - expect( - screen.queryByText( 'Stripe button mock' ) - ).not.toBeInTheDocument(); - expect( - await screen.findByText( - /To preview the buttons, ensure your device is configured/ - ) - ).toBeInTheDocument(); - } ); - - it( 'displays an info notice if stripe fails to load', async () => { - canMakePaymentMock.mockResolvedValue( null ); - render( ); - - expect( - await screen.findByText( - /To preview the buttons, ensure your device is configured/ - ) - ).toBeInTheDocument(); - expect( - screen.queryByText( 'Stripe button mock' ) - ).not.toBeInTheDocument(); - } ); - - it( 'displays the payment button when stripe is loaded', async () => { - render( ); - - expect( - await screen.findByText( 'Stripe button mock' ) - ).toBeInTheDocument(); - expect( - screen.queryByText( /ensure your device is configured/ ) - ).not.toBeInTheDocument(); - } ); -} ); diff --git a/client/entrypoints/payment-request-settings/__tests__/payment-request-settings-locations.test.js b/client/entrypoints/payment-request-settings/__tests__/payment-request-settings-locations.test.js deleted file mode 100644 index 7548543b88..0000000000 --- a/client/entrypoints/payment-request-settings/__tests__/payment-request-settings-locations.test.js +++ /dev/null @@ -1,163 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import PaymentRequestsSettingsSection from '../payment-request-settings-section'; -import PaymentRequestButtonPreview from '../payment-request-button-preview'; -import { - usePaymentRequestEnabledSettings, - usePaymentRequestLocations, -} from 'wcstripe/data'; - -jest.mock( 'wcstripe/data', () => ( { - usePaymentRequestEnabledSettings: jest.fn(), - usePaymentRequestLocations: jest.fn(), - usePaymentRequestButtonType: jest.fn().mockReturnValue( [ 'buy' ] ), - usePaymentRequestButtonSize: jest.fn().mockReturnValue( [ 'default' ] ), - usePaymentRequestButtonTheme: jest.fn().mockReturnValue( [ 'dark' ] ), -} ) ); - -jest.mock( 'wcstripe/data/account/hooks', () => ( { - useAccount: jest.fn().mockReturnValue( { data: {} } ), -} ) ); -jest.mock( 'wcstripe/data/account-keys/hooks', () => ( { - useAccountKeys: jest.fn().mockReturnValue( {} ), - useAccountKeysPublishableKey: jest.fn().mockReturnValue( [ '' ] ), - useAccountKeysTestPublishableKey: jest.fn().mockReturnValue( [ '' ] ), -} ) ); - -jest.mock( '../payment-request-button-preview' ); -PaymentRequestButtonPreview.mockImplementation( () => '<>' ); - -jest.mock( '../utils/utils', () => ( { - getPaymentRequestData: jest.fn().mockReturnValue( { - publishableKey: 'pk_test_123', - accountId: '0001', - locale: 'en', - } ), -} ) ); -jest.mock( '@woocommerce/blocks-checkout', () => {}, { virtual: true } ); - -const getMockPaymentRequestEnabledSettings = ( - isEnabled, - updateIsPaymentRequestEnabledHandler -) => [ isEnabled, updateIsPaymentRequestEnabledHandler ]; - -const getMockPaymentRequestLocations = ( - isCheckoutEnabled, - isProductPageEnabled, - isCartEnabled, - updatePaymentRequestLocationsHandler -) => [ - [ - isCheckoutEnabled && 'checkout', - isProductPageEnabled && 'product', - isCartEnabled && 'cart', - ].filter( Boolean ), - updatePaymentRequestLocationsHandler, -]; - -describe( 'PaymentRequestsSettingsSection', () => { - const globalValues = global.wc_stripe_payment_request_settings_params; - - beforeEach( () => { - usePaymentRequestEnabledSettings.mockReturnValue( - getMockPaymentRequestEnabledSettings( true, jest.fn() ) - ); - - usePaymentRequestLocations.mockReturnValue( - getMockPaymentRequestLocations( true, true, true, jest.fn() ) - ); - - global.wc_stripe_payment_request_settings_params = { - ...globalValues, - key: 'pk_test_123', - locale: 'en', - is_ece_enabled: true, - }; - } ); - - afterEach( () => { - jest.clearAllMocks(); - global.wc_stripe_payment_request_settings_params = globalValues; - } ); - - it( 'should enable express checkout locations when express checkout is enabled', () => { - render( ); - - const [ checkoutCheckbox, productPageCheckbox, cartCheckbox ] = - screen.getAllByRole( 'checkbox' ); - - expect( checkoutCheckbox ).not.toBeDisabled(); - expect( checkoutCheckbox ).toBeChecked(); - expect( productPageCheckbox ).not.toBeDisabled(); - expect( productPageCheckbox ).toBeChecked(); - expect( cartCheckbox ).not.toBeDisabled(); - expect( cartCheckbox ).toBeChecked(); - } ); - - it( 'should trigger an action to save the checked locations when un-checking the location checkboxes', async () => { - const updatePaymentRequestLocationsHandler = jest.fn(); - usePaymentRequestEnabledSettings.mockReturnValue( [ true, jest.fn() ] ); - usePaymentRequestLocations.mockReturnValue( - getMockPaymentRequestLocations( - true, - true, - true, - updatePaymentRequestLocationsHandler - ) - ); - - render( ); - - // Uncheck each checkbox, and verify them what kind of action should have been called - await userEvent.click( screen.getByText( 'Product page' ) ); - - expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( - [ 'checkout', 'cart' ] - ); - - await userEvent.click( screen.getByText( 'Checkout' ) ); - - expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( - [ 'product', 'cart' ] - ); - - await userEvent.click( screen.getByText( 'Cart' ) ); - - expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( - [ 'checkout', 'product' ] - ); - } ); - - it( 'should trigger an action to save the checked locations when checking the location checkboxes', async () => { - const updatePaymentRequestLocationsHandler = jest.fn(); - usePaymentRequestEnabledSettings.mockReturnValue( [ true, jest.fn() ] ); - usePaymentRequestLocations.mockReturnValue( - getMockPaymentRequestLocations( - false, - false, - false, - updatePaymentRequestLocationsHandler - ) - ); - - render( ); - - await userEvent.click( screen.getByText( 'Cart' ) ); - - expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( - [ 'cart' ] - ); - - await userEvent.click( screen.getByText( 'Product page' ) ); - - expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( - [ 'product' ] - ); - - await userEvent.click( screen.getByText( 'Checkout' ) ); - - expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( - [ 'checkout' ] - ); - } ); -} ); diff --git a/client/entrypoints/payment-request-settings/__tests__/payment-request-settings.test.js b/client/entrypoints/payment-request-settings/__tests__/payment-request-settings.test.js deleted file mode 100644 index 126e1d6a79..0000000000 --- a/client/entrypoints/payment-request-settings/__tests__/payment-request-settings.test.js +++ /dev/null @@ -1,146 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import PaymentRequestsSettingsSection from '../payment-request-settings-section'; -import PaymentRequestButtonPreview from '../payment-request-button-preview'; -import { - usePaymentRequestEnabledSettings, - usePaymentRequestLocations, - usePaymentRequestButtonType, - usePaymentRequestButtonSize, - usePaymentRequestButtonTheme, -} from 'wcstripe/data'; - -jest.mock( 'wcstripe/data', () => ( { - usePaymentRequestEnabledSettings: jest.fn(), - usePaymentRequestLocations: jest.fn(), - usePaymentRequestButtonType: jest.fn().mockReturnValue( [ 'buy' ] ), - usePaymentRequestButtonSize: jest.fn().mockReturnValue( [ 'default' ] ), - usePaymentRequestButtonTheme: jest.fn().mockReturnValue( [ 'dark' ] ), -} ) ); -jest.mock( 'wcstripe/data/account/hooks', () => ( { - useAccount: jest.fn().mockReturnValue( { data: {} } ), -} ) ); -jest.mock( 'wcstripe/data/account-keys/hooks', () => ( { - useAccountKeys: jest.fn().mockReturnValue( {} ), - useAccountKeysPublishableKey: jest.fn().mockReturnValue( [ '' ] ), - useAccountKeysTestPublishableKey: jest.fn().mockReturnValue( [ '' ] ), -} ) ); -jest.mock( '@woocommerce/blocks-checkout', () => {}, { virtual: true } ); - -jest.mock( '../payment-request-button-preview' ); -PaymentRequestButtonPreview.mockImplementation( () => '<>' ); - -jest.mock( '../utils/utils', () => ( { - getPaymentRequestData: jest.fn().mockReturnValue( { - publishableKey: 'pk_test_123', - accountId: '0001', - locale: 'en', - } ), -} ) ); - -const getMockPaymentRequestEnabledSettings = ( - isEnabled, - updateIsPaymentRequestEnabledHandler -) => [ isEnabled, updateIsPaymentRequestEnabledHandler ]; - -const getMockPaymentRequestLocations = ( - isCheckoutEnabled, - isProductPageEnabled, - isCartEnabled, - updatePaymentRequestLocationsHandler -) => [ - [ - isCheckoutEnabled && 'checkout', - isProductPageEnabled && 'product', - isCartEnabled && 'cart', - ].filter( Boolean ), - updatePaymentRequestLocationsHandler, -]; - -describe( 'PaymentRequestsSettingsSection', () => { - const globalValues = global.wc_stripe_payment_request_settings_params; - beforeEach( () => { - usePaymentRequestEnabledSettings.mockReturnValue( - getMockPaymentRequestEnabledSettings( true, jest.fn() ) - ); - - usePaymentRequestLocations.mockReturnValue( - getMockPaymentRequestLocations( true, true, true, jest.fn() ) - ); - - global.wc_stripe_payment_request_settings_params = { - ...globalValues, - key: 'pk_test_123', - locale: 'en', - is_ece_enabled: true, - }; - } ); - - afterEach( () => { - jest.clearAllMocks(); - global.wc_stripe_payment_request_settings_params = globalValues; - } ); - - it( 'renders settings with defaults', () => { - render( ); - - // confirm settings headings. - expect( - screen.queryByRole( 'heading', { name: 'Call to action' } ) - ).toBeInTheDocument(); - expect( - screen.queryByRole( 'heading', { name: 'Appearance' } ) - ).toBeInTheDocument(); - - // confirm radio button groups displayed. - const [ ctaRadio, sizeRadio, themeRadio ] = - screen.queryAllByRole( 'radio' ); - - expect( ctaRadio ).toBeInTheDocument(); - expect( sizeRadio ).toBeInTheDocument(); - expect( themeRadio ).toBeInTheDocument(); - - // confirm default values. - expect( screen.getByLabelText( 'Buy' ) ).toBeChecked(); - expect( screen.getByLabelText( 'Default (48 px)' ) ).toBeChecked(); - expect( screen.getByLabelText( /Dark/ ) ).toBeChecked(); - } ); - - it( 'triggers the hooks when the settings are being interacted with', async () => { - const setButtonTypeMock = jest.fn(); - const setButtonSizeMock = jest.fn(); - const setButtonThemeMock = jest.fn(); - - usePaymentRequestButtonType.mockReturnValue( [ - 'buy', - setButtonTypeMock, - ] ); - usePaymentRequestButtonSize.mockReturnValue( [ - 'default', - setButtonSizeMock, - ] ); - usePaymentRequestButtonTheme.mockReturnValue( [ - 'dark', - setButtonThemeMock, - ] ); - usePaymentRequestEnabledSettings.mockReturnValue( [ true, jest.fn() ] ); - - render( ); - - expect( setButtonTypeMock ).not.toHaveBeenCalled(); - expect( setButtonSizeMock ).not.toHaveBeenCalled(); - expect( setButtonThemeMock ).not.toHaveBeenCalled(); - - await userEvent.click( screen.getByLabelText( /Light/ ) ); - - expect( setButtonThemeMock ).toHaveBeenCalledWith( 'light' ); - - await userEvent.click( screen.getByLabelText( 'Book' ) ); - - expect( setButtonTypeMock ).toHaveBeenCalledWith( 'book' ); - - await userEvent.click( screen.getByLabelText( 'Large (56 px)' ) ); - - expect( setButtonSizeMock ).toHaveBeenCalledWith( 'large' ); - } ); -} ); diff --git a/client/entrypoints/payment-request-settings/express-checkout-button-preview.js b/client/entrypoints/payment-request-settings/express-checkout-button-preview.js deleted file mode 100644 index d657e25099..0000000000 --- a/client/entrypoints/payment-request-settings/express-checkout-button-preview.js +++ /dev/null @@ -1,129 +0,0 @@ -/* global wc_stripe_payment_request_settings_params */ - -import { useState, useMemo } from 'react'; -import { Elements, ExpressCheckoutElement } from '@stripe/react-stripe-js'; -import { loadStripe } from '@stripe/stripe-js'; -import { __ } from '@wordpress/i18n'; -import { getDefaultBorderRadius } from 'wcstripe/express-checkout/utils'; -import InlineNotice from 'components/inline-notice'; -import { - EXPRESS_PAYMENT_METHOD_SETTING_APPLE_PAY, - EXPRESS_PAYMENT_METHOD_SETTING_GOOGLE_PAY, - PAYMENT_METHOD_CARD, -} from 'wcstripe/stripe-utils/constants'; - -const buttonSizeToPxMap = { - small: 40, - default: 48, - large: 56, -}; - -const ExpressCheckoutPreviewComponent = ( { buttonType, theme, size } ) => { - const [ canRenderButtons, setCanRenderButtons ] = useState( true ); - - /* eslint-disable camelcase */ - const stripePromise = useMemo( () => { - return loadStripe( wc_stripe_payment_request_settings_params.key, { - locale: wc_stripe_payment_request_settings_params.locale, - } ); - }, [] ); - /* eslint-enable camelcase */ - - const options = { - mode: 'payment', - amount: 1000, - currency: 'usd', - appearance: { - variables: { - borderRadius: `${ getDefaultBorderRadius() }px`, - spacingUnit: '6px', - }, - }, - paymentMethodTypes: [ PAYMENT_METHOD_CARD ], - }; - - const height = buttonSizeToPxMap[ size ] || buttonSizeToPxMap.medium; - - const mapThemeConfigToButtonTheme = ( paymentMethod, buttonTheme ) => { - switch ( buttonTheme ) { - case 'dark': - return 'black'; - case 'light': - return 'white'; - case 'light-outline': - if ( - paymentMethod === EXPRESS_PAYMENT_METHOD_SETTING_GOOGLE_PAY - ) { - return 'white'; - } - return 'white-outline'; - default: - return 'black'; - } - }; - - const type = buttonType === 'default' ? 'plain' : buttonType; - - const buttonOptions = { - buttonHeight: Math.min( Math.max( height, 40 ), 55 ), - buttonTheme: { - googlePay: mapThemeConfigToButtonTheme( - EXPRESS_PAYMENT_METHOD_SETTING_GOOGLE_PAY, - theme - ), - applePay: mapThemeConfigToButtonTheme( - EXPRESS_PAYMENT_METHOD_SETTING_APPLE_PAY, - theme - ), - }, - buttonType: { - googlePay: type, - applePay: type, - }, - paymentMethods: { - link: 'never', - googlePay: 'always', - applePay: 'always', - }, - layout: { overflow: 'never' }, - }; - - const onReady = ( { availablePaymentMethods } ) => { - if ( availablePaymentMethods ) { - setCanRenderButtons( true ); - } else { - setCanRenderButtons( false ); - } - }; - - if ( canRenderButtons ) { - return ( -
- - {} } - onReady={ onReady } - /> - -
- ); - } - - return ( - - { __( - 'Failed to preview the Apple Pay or Google Pay button. ' + - 'Ensure your store uses HTTPS on a publicly available domain ' + - "and you're viewing this page in a Safari or Chrome browser. " + - 'Your device must be configured to use Apple Pay or Google Pay.', - 'woocommerce-gateway-stripe' - ) } - - ); -}; - -export default ExpressCheckoutPreviewComponent; diff --git a/client/entrypoints/payment-request-settings/index.js b/client/entrypoints/payment-request-settings/index.js deleted file mode 100644 index 23f325c8f2..0000000000 --- a/client/entrypoints/payment-request-settings/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import { createRoot } from 'react-dom/client'; -import PaymentRequestsPage from './payment-request-page'; - -const container = document.getElementById( - 'wc-stripe-payment-request-settings-container' -); - -if ( container ) { - createRoot( container ).render( ); -} diff --git a/client/entrypoints/payment-request-settings/payment-request-button-preview.js b/client/entrypoints/payment-request-settings/payment-request-button-preview.js deleted file mode 100644 index 963114068d..0000000000 --- a/client/entrypoints/payment-request-settings/payment-request-button-preview.js +++ /dev/null @@ -1,139 +0,0 @@ -import { React, useState, useEffect } from 'react'; -import { - PaymentRequestButtonElement, - useStripe, -} from '@stripe/react-stripe-js'; -import { shouldUseGooglePayBrand } from './utils/utils'; -import { __, sprintf } from '@wordpress/i18n'; -import InlineNotice from 'wcstripe/components/inline-notice'; -import { - usePaymentRequestButtonType, - usePaymentRequestButtonSize, - usePaymentRequestButtonTheme, -} from 'wcstripe/data'; - -/** - * stripePromise is used to pass into 's stripe props. - * The stripe prop in can't be change once passed in. - * Keeping this outside of so that - * re-rendering does not change it. - */ - -const BrowserHelpText = () => { - let browser = 'Google Chrome'; - let paymentMethodName = 'Google Pay'; - - if ( shouldUseGooglePayBrand() ) { - browser = 'Safari'; - paymentMethodName = 'Apple Pay'; - } - - return ( -

- { sprintf( - /* translators: %1: Payment method name %2: Browser name. */ - __( - 'To preview the %1$s button, view this page in the %2$s browser.', - 'woocommerce-gateway-stripe' - ), - paymentMethodName, - browser - ) } -

- ); -}; - -const buttonSizeToPxMap = { - small: 40, - default: 48, - large: 56, -}; - -const PaymentRequestsButtonPreview = () => { - const stripe = useStripe(); - const [ paymentRequest, setPaymentRequest ] = useState(); - const [ isLoading, setIsLoading ] = useState( true ); - const [ buttonType ] = usePaymentRequestButtonType(); - const [ size ] = usePaymentRequestButtonSize(); - const [ theme ] = usePaymentRequestButtonTheme(); - - useEffect( () => { - // when `stripe` is falsy, it means that it didn't load because of some error (like: the website wasn't loaded with HTTPS). - if ( ! stripe ) { - setIsLoading( false ); - return; - } - - setIsLoading( true ); - // Create a preview for payment button. The label and its total are placeholders. - const stripePaymentRequest = stripe.paymentRequest( { - country: 'US', - currency: 'usd', - total: { - label: __( 'Total', 'woocommerce-gateway-stripe' ), - amount: 99, - }, - requestPayerName: true, - requestPayerEmail: true, - } ); - - // Check the availability of the Payment Request API. - stripePaymentRequest.canMakePayment().then( ( result ) => { - if ( result ) { - setPaymentRequest( stripePaymentRequest ); - } - setIsLoading( false ); - } ); - }, [ stripe, setPaymentRequest, setIsLoading ] ); - - /** - * If stripe is loading, then display nothing. - * If stripe finished loading but payment request button failed to load (null), display info section. - * If stripe finished loading and payment request button loads, display the button. - */ - if ( isLoading ) { - return null; - } - - if ( ! paymentRequest ) { - return ( - - { __( - 'To preview the buttons, ' + - 'ensure your device is configured to accept Apple Pay or Google Pay, ' + - 'and view this page using the Safari or Chrome browsers.', - 'woocommerce-gateway-stripe' - ) } - - ); - } - - return ( - <> -
- { - e.preventDefault(); - } } - options={ { - paymentRequest, - style: { - paymentRequestButton: { - type: buttonType, - theme, - height: `${ - buttonSizeToPxMap[ size ] || - buttonSizeToPxMap.default - }px`, - }, - }, - } } - /> -
- - - ); -}; - -export default PaymentRequestsButtonPreview; diff --git a/client/entrypoints/payment-request-settings/payment-request-enable-section.js b/client/entrypoints/payment-request-settings/payment-request-enable-section.js deleted file mode 100644 index d82f71042e..0000000000 --- a/client/entrypoints/payment-request-settings/payment-request-enable-section.js +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import { __ } from '@wordpress/i18n'; -import { Card, CheckboxControl } from '@wordpress/components'; -import { usePaymentRequestEnabledSettings } from 'wcstripe/data'; -import CardBody from 'wcstripe/settings/card-body'; -const PaymentRequestsEnableSection = () => { - const [ isPaymentRequestEnabled, updateIsPaymentRequestEnabled ] = - usePaymentRequestEnabledSettings(); - - return ( - - - - - - ); -}; - -export default PaymentRequestsEnableSection; diff --git a/client/entrypoints/payment-request-settings/payment-request-page.js b/client/entrypoints/payment-request-settings/payment-request-page.js deleted file mode 100644 index 092fff43fd..0000000000 --- a/client/entrypoints/payment-request-settings/payment-request-page.js +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; -import PaymentRequestIcon from '../../payment-method-icons/payment-request'; -import PaymentRequestsEnableSection from './payment-request-enable-section'; -import PaymentRequestsSettingsSection from './payment-request-settings-section'; -import { __ } from '@wordpress/i18n'; -import SettingsSection from 'wcstripe/settings/settings-section'; -import SettingsLayout from 'wcstripe/settings/settings-layout'; -import LoadableSettingsSection from 'wcstripe/settings/loadable-settings-section'; -import SaveSettingsSection from 'wcstripe/settings/save-settings-section'; -import './style.scss'; - -const EnableDescription = () => ( - <> -
- -
-

- { __( - 'Decide how buttons for digital wallets Apple Pay and ' + - 'Google Pay are displayed in your store. Depending on ' + - 'their web browser and their wallet configurations, ' + - 'your customers will see either Apple Pay or Google Pay, ' + - 'but not both.', - 'woocommerce-gateway-stripe' - ) } -

- -); - -const SettingsDescription = () => ( - <> -

{ __( 'Settings', 'woocommerce-gateway-stripe' ) }

-

- { __( - 'Configure the display of Apple Pay and Google Pay buttons on your store.', - 'woocommerce-gateway-stripe' - ) } -

- -); - -const PaymentRequestsPage = () => { - return ( - - - - - - - - - - - - - - - - ); -}; - -export default PaymentRequestsPage; diff --git a/client/entrypoints/payment-request-settings/payment-request-settings-section.js b/client/entrypoints/payment-request-settings/payment-request-settings-section.js deleted file mode 100644 index d7513e2e96..0000000000 --- a/client/entrypoints/payment-request-settings/payment-request-settings-section.js +++ /dev/null @@ -1,304 +0,0 @@ -/* global wc_stripe_payment_request_settings_params */ - -import { ADMIN_URL, getSetting } from '@woocommerce/settings'; -import React, { useMemo } from 'react'; -import interpolateComponents from 'interpolate-components'; -import { Elements } from '@stripe/react-stripe-js'; -import { loadStripe } from '@stripe/stripe-js'; -import styled from '@emotion/styled'; -import PaymentRequestButtonPreview from './payment-request-button-preview'; -import ExpressCheckoutPreviewComponent from './express-checkout-button-preview'; -import { - Card, - RadioControl, - CheckboxControl, - Notice, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { - usePaymentRequestEnabledSettings, - usePaymentRequestLocations, - usePaymentRequestButtonType, - usePaymentRequestButtonSize, - usePaymentRequestButtonTheme, -} from 'wcstripe/data'; -import CardBody from 'wcstripe/settings/card-body'; -import LoadableAccountSection from 'wcstripe/settings/loadable-account-section'; -import { useAccount } from 'wcstripe/data/account/hooks'; -import { - useAccountKeysPublishableKey, - useAccountKeysTestPublishableKey, -} from 'wcstripe/data/account-keys/hooks'; - -const makeButtonSizeText = ( string ) => - interpolateComponents( { - mixedString: string, - components: { - helpText: ( - - ), - }, - } ); -const buttonSizeOptions = [ - { - label: makeButtonSizeText( - __( - 'Small {{helpText}}(40 px){{/helpText}}', - 'woocommerce-gateway-stripe' - ) - ), - value: 'small', - }, - { - label: makeButtonSizeText( - __( - 'Default {{helpText}}(48 px){{/helpText}}', - 'woocommerce-gateway-stripe' - ) - ), - value: 'default', - }, - { - label: makeButtonSizeText( - __( - 'Large {{helpText}}(56 px){{/helpText}}', - 'woocommerce-gateway-stripe' - ) - ), - value: 'large', - }, -]; -const buttonActionOptions = [ - { - label: __( 'Only icon', 'woocommerce-gateway-stripe' ), - value: 'default', - }, - { - label: __( 'Buy', 'woocommerce-gateway-stripe' ), - value: 'buy', - }, - { - label: __( 'Donate', 'woocommerce-gateway-stripe' ), - value: 'donate', - }, - { - label: __( 'Book', 'woocommerce-gateway-stripe' ), - value: 'book', - }, -]; - -const makeButtonThemeText = ( string ) => - interpolateComponents( { - mixedString: string, - components: { - br:
, - helpText: ( - - ), - }, - } ); -const buttonThemeOptions = [ - { - label: makeButtonThemeText( - __( - 'Dark {{br/}}{{helpText}}Recommended for white or light-colored backgrounds with high contrast.{{/helpText}}', - 'woocommerce-gateway-stripe' - ) - ), - value: 'dark', - }, - { - label: makeButtonThemeText( - __( - 'Light {{br/}}{{helpText}}Recommended for dark or colored backgrounds with high contrast.{{/helpText}}', - 'woocommerce-gateway-stripe' - ) - ), - value: 'light', - }, - { - label: makeButtonThemeText( - __( - 'Outline {{br/}}{{helpText}}Recommended for white or light-colored backgrounds with insufficient contrast.{{/helpText}}', - 'woocommerce-gateway-stripe' - ) - ), - value: 'light-outline', - }, -]; - -const PaymentRequestsSettingsSection = () => { - const [ buttonType, setButtonType ] = usePaymentRequestButtonType(); - const [ size, setSize ] = usePaymentRequestButtonSize(); - const [ theme, setTheme ] = usePaymentRequestButtonTheme(); - const accountId = useAccount().data?.account?.id; - const [ publishableKey ] = useAccountKeysPublishableKey(); - const [ testPublishableKey ] = useAccountKeysTestPublishableKey(); - const isECEEnabled = - wc_stripe_payment_request_settings_params.is_ece_enabled; // eslint-disable-line camelcase - - const stripePromise = useMemo( () => { - return loadStripe( - publishableKey || testPublishableKey || 'pk_test_123', - { - stripeAccount: accountId || '0001', - locale: 'en', - } - ); - }, [ testPublishableKey, publishableKey, accountId ] ); - - const [ isPaymentRequestEnabled ] = usePaymentRequestEnabledSettings(); - - const [ paymentRequestLocations, updatePaymentRequestLocations ] = - usePaymentRequestLocations(); - - const makeLocationChangeHandler = ( location ) => ( isChecked ) => { - if ( isChecked ) { - updatePaymentRequestLocations( [ - ...paymentRequestLocations, - location, - ] ); - } else { - updatePaymentRequestLocations( - paymentRequestLocations.filter( ( name ) => name !== location ) - ); - } - }; - - const StyledLink = styled.a` - &:focus, - &:visited { - box-shadow: none; - } - `; - - return ( - - - - { interpolateComponents( { - mixedString: __( - 'Some appearance settings may be overridden by the express payment section of the ' + - '{{checkoutPageLink}}Cart & Checkout blocks{{/checkoutPageLink}}.', - 'woocommerce-gateway-stripe' - ), - components: { - checkoutPageLink: ( - { - // Stop propagation is necessary so it doesn't trigger the tooltip click event. - ev.stopPropagation(); - } } - /> - ), - }, - } ) } - -

- { __( - 'Show express checkouts on', - 'woocommerce-gateway-stripe' - ) } -

-
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
-

- { __( 'Call to action', 'woocommerce-gateway-stripe' ) } -

- -

{ __( 'Appearance', 'woocommerce-gateway-stripe' ) }

- - -

{ __( 'Preview', 'woocommerce-gateway-stripe' ) }

- - { isECEEnabled ? ( - - ) : ( - - - - ) } - -
-
- ); -}; - -export default PaymentRequestsSettingsSection; diff --git a/client/entrypoints/payment-request-settings/style.scss b/client/entrypoints/payment-request-settings/style.scss deleted file mode 100644 index 8aeb235705..0000000000 --- a/client/entrypoints/payment-request-settings/style.scss +++ /dev/null @@ -1,72 +0,0 @@ -@use '../../styles/abstracts/styles'; - -.payment-method-settings { - &__breadcrumbs { - margin-bottom: 40px; - } - - &__option-muted-text { - color: styles.$gray-700; - } - - &__option-help-text { - color: styles.$gray-700; - padding-left: 30px; - - @media ( min-width: 600px ) { - padding-left: 26px; - } - } - - &__cta-selection { - .components-base-control__label { - // hack until the `hideLabelFromVision` is fixed for radio controls in Gutenberg - display: none; - } - } - - &__preview { - border: 1px dashed styles.$gray-300; - box-sizing: border-box; - border-radius: 3px; - background-color: styles.$gray-100; - padding: 16px; - } - - &__preview-help-text { - font-style: italic; - } -} - -.components-radio-control__input[type='radio']:checked::before { - box-sizing: border-box; -} - -.payment-request-settings { - &__location { - margin-bottom: 26px !important; - } -} - -.express-checkout-settings { - .components-card-body { - padding: calc(16px) calc(24px); - - @include styles.breakpoint( '>660px' ) { - padding: 24px 24px 24px 24px; - } - } - - &__icon { - border-radius: 2px; - display: none; - height: 40px; - margin: 1px 17px 1px 1px; // 1px to accommodate for box-shadow - box-shadow: 0 0 0 1px styles.$gray-300; - background: styles.$white; - - @include styles.breakpoint( '>660px' ) { - display: inline-block; - } - } -} \ No newline at end of file diff --git a/client/entrypoints/payment-request-settings/utils/utils.js b/client/entrypoints/payment-request-settings/utils/utils.js deleted file mode 100644 index 8262c3450b..0000000000 --- a/client/entrypoints/payment-request-settings/utils/utils.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Whether or not to use Google Pay branded button in Chrome. - * - * @return {boolean} Use Google Pay button in Chrome. - */ -export const shouldUseGooglePayBrand = () => { - const ua = window.navigator.userAgent.toLowerCase(); - const isChrome = - /chrome/.test( ua ) && - ! /edge|edg|opr|brave\//.test( ua ) && - window.navigator.vendor === 'Google Inc.'; - // newer versions of Brave do not have the userAgent string - const isBrave = isChrome && window.navigator.brave; - return isChrome && ! isBrave; -}; diff --git a/webpack.config.js b/webpack.config.js index 0e300b9649..21da041207 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -113,8 +113,6 @@ module.exports = { }, entry: { index: './client/blocks/index.js', - 'payment-requests-settings': - './client/entrypoints/payment-request-settings/index.js', 'upe-classic': './client/classic/upe/index.js', 'upe-blocks': './client/blocks/upe/index.js', 'upe-settings': './client/settings/index.js', From ee6ba1086978a9c246a40898d721ee9cde337e59 Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Fri, 26 Sep 2025 15:24:57 -0300 Subject: [PATCH 02/11] Readme and changelog entries --- changelog.txt | 1 + readme.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/changelog.txt b/changelog.txt index 8547d810d7..16b4138b70 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,7 @@ *** Changelog *** = 9.10.0 - xxxx-xx-xx = +* Dev - Removes all the frontend code related to Payment Request Buttons * Dev - Fixes some possible warnings shown in the browser console when the Optimized Checkout payment element is instantiated with invalid parameters * Dev - Renaming the Klarna payment token class to WC_Stripe_Klarna_Payment_Token * Fix - Minor fixes and code improvements for the saved payment methods comparison logic diff --git a/readme.txt b/readme.txt index 31241dd953..290d7c47c4 100644 --- a/readme.txt +++ b/readme.txt @@ -111,6 +111,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o == Changelog == = 9.10.0 - xxxx-xx-xx = +* Dev - Removes all the frontend code related to Payment Request Buttons * Dev - Fixes some possible warnings shown in the browser console when the Optimized Checkout payment element is instantiated with invalid parameters * Dev - Renaming the Klarna payment token class to WC_Stripe_Klarna_Payment_Token * Fix - Minor fixes and code improvements for the saved payment methods comparison logic From 18f36c2361348fe8c00a629ebe1f1bac5a83e7cb Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Tue, 30 Sep 2025 16:50:35 -0300 Subject: [PATCH 03/11] Reverting removal of PRBs settings files + renaming them to express-checkout --- .../amazon-pay-settings/amazon-pay-page.js | 2 +- .../express-checkout-button-preview.test.js | 115 +++++++ ...xpress-checkout-settings-locations.test.js | 163 ++++++++++ .../express-checkout-settings.test.js | 146 +++++++++ .../express-checkout-button-preview.js | 139 ++++++++ .../express-checkout-enable-section.js | 31 ++ .../express-checkout-page.js | 62 ++++ .../express-checkout-preview-component.js | 129 ++++++++ .../express-checkout-settings-section.js | 304 ++++++++++++++++++ .../express-checkout-settings/index.js | 11 + .../express-checkout-settings/style.scss | 70 ++++ .../express-checkout-settings/utils/utils.js | 15 + webpack.config.js | 2 + 13 files changed, 1188 insertions(+), 1 deletion(-) create mode 100644 client/entrypoints/express-checkout-settings/__tests__/express-checkout-button-preview.test.js create mode 100644 client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings-locations.test.js create mode 100644 client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings.test.js create mode 100644 client/entrypoints/express-checkout-settings/express-checkout-button-preview.js create mode 100644 client/entrypoints/express-checkout-settings/express-checkout-enable-section.js create mode 100644 client/entrypoints/express-checkout-settings/express-checkout-page.js create mode 100644 client/entrypoints/express-checkout-settings/express-checkout-preview-component.js create mode 100644 client/entrypoints/express-checkout-settings/express-checkout-settings-section.js create mode 100644 client/entrypoints/express-checkout-settings/index.js create mode 100644 client/entrypoints/express-checkout-settings/style.scss create mode 100644 client/entrypoints/express-checkout-settings/utils/utils.js diff --git a/client/entrypoints/amazon-pay-settings/amazon-pay-page.js b/client/entrypoints/amazon-pay-settings/amazon-pay-page.js index affcd78999..9df3c14c07 100644 --- a/client/entrypoints/amazon-pay-settings/amazon-pay-page.js +++ b/client/entrypoints/amazon-pay-settings/amazon-pay-page.js @@ -7,7 +7,7 @@ import SettingsSection from 'wcstripe/settings/settings-section'; import SettingsLayout from 'wcstripe/settings/settings-layout'; import LoadableSettingsSection from 'wcstripe/settings/loadable-settings-section'; import SaveSettingsSection from 'wcstripe/settings/save-settings-section'; -import '../express-checkout/styles.scss'; +import '../express-checkout-settings/style.scss'; const EnableDescription = () => ( <> diff --git a/client/entrypoints/express-checkout-settings/__tests__/express-checkout-button-preview.test.js b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-button-preview.test.js new file mode 100644 index 0000000000..8a3558934d --- /dev/null +++ b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-button-preview.test.js @@ -0,0 +1,115 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { useStripe } from '@stripe/react-stripe-js'; +import ExpressCheckoutButtonPreview from '../express-checkout-button-preview'; +import { shouldUseGooglePayBrand } from '../utils/utils'; + +// We need to mock the actual module being used by `` in the `@wordpress/components` module +const realPathToA11yModule = + '@wordpress/components/node_modules/@wordpress/a11y'; + +jest.mock( realPathToA11yModule, () => ( { + ...jest.requireActual( realPathToA11yModule ), + speak: jest.fn(), +} ) ); + +jest.mock( '../utils/utils', () => ( { + shouldUseGooglePayBrand: jest.fn(), +} ) ); + +jest.mock( '@stripe/react-stripe-js', () => ( { + PaymentRequestButtonElement: jest + .fn() + .mockReturnValue( ), + useStripe: jest.fn(), +} ) ); + +jest.mock( 'wcstripe/data', () => ( { + usePaymentRequestButtonType: jest.fn().mockReturnValue( [ 'buy' ] ), + usePaymentRequestButtonSize: jest.fn().mockReturnValue( [ 'default' ] ), + usePaymentRequestButtonTheme: jest.fn().mockReturnValue( [ 'dark' ] ), +} ) ); + +describe( 'ExpressCheckoutButtonPreview', () => { + const canMakePaymentMock = jest.fn(); + + beforeEach( () => { + shouldUseGooglePayBrand.mockReturnValue( true ); + useStripe.mockReturnValue( { + paymentRequest: () => ( { + canMakePayment: canMakePaymentMock, + } ), + } ); + canMakePaymentMock.mockResolvedValue( {} ); + } ); + + afterEach( () => { + jest.clearAllMocks(); + } ); + + it( 'displays Google Chrome and Google Pay when page is in Safari', async () => { + shouldUseGooglePayBrand.mockReturnValue( false ); + + render( ); + + expect( + await screen.findByText( + 'To preview the Google Pay button, view this page in the Google Chrome browser.' + ) + ).toBeInTheDocument(); + expect( screen.queryByText( /Safari/ ) ).not.toBeInTheDocument(); + } ); + + it( 'displays Safari Apple Pay when page is in Google Chrome', async () => { + shouldUseGooglePayBrand.mockReturnValue( true ); + + render( ); + + expect( + await screen.findByText( + 'To preview the Apple Pay button, view this page in the Safari browser.' + ) + ).toBeInTheDocument(); + expect( screen.queryByText( /Google Chrome/ ) ).not.toBeInTheDocument(); + } ); + + it( 'displays an info notice if stripe is falsy', async () => { + useStripe.mockReturnValue( null ); + + render( ); + + expect( + screen.queryByText( 'Stripe button mock' ) + ).not.toBeInTheDocument(); + expect( + await screen.findByText( + /To preview the buttons, ensure your device is configured/ + ) + ).toBeInTheDocument(); + } ); + + it( 'displays an info notice if stripe fails to load', async () => { + canMakePaymentMock.mockResolvedValue( null ); + render( ); + + expect( + await screen.findByText( + /To preview the buttons, ensure your device is configured/ + ) + ).toBeInTheDocument(); + expect( + screen.queryByText( 'Stripe button mock' ) + ).not.toBeInTheDocument(); + } ); + + it( 'displays the payment button when stripe is loaded', async () => { + render( ); + + expect( + await screen.findByText( 'Stripe button mock' ) + ).toBeInTheDocument(); + expect( + screen.queryByText( /ensure your device is configured/ ) + ).not.toBeInTheDocument(); + } ); +} ); diff --git a/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings-locations.test.js b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings-locations.test.js new file mode 100644 index 0000000000..88c8ad23f2 --- /dev/null +++ b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings-locations.test.js @@ -0,0 +1,163 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import ExpressCheckoutSettingsSection from '../express-checkout-settings-section'; +import ExpressCheckoutButtonPreview from '../express-checkout-button-preview'; +import { + usePaymentRequestEnabledSettings, + usePaymentRequestLocations, +} from 'wcstripe/data'; + +jest.mock( 'wcstripe/data', () => ( { + usePaymentRequestEnabledSettings: jest.fn(), + usePaymentRequestLocations: jest.fn(), + usePaymentRequestButtonType: jest.fn().mockReturnValue( [ 'buy' ] ), + usePaymentRequestButtonSize: jest.fn().mockReturnValue( [ 'default' ] ), + usePaymentRequestButtonTheme: jest.fn().mockReturnValue( [ 'dark' ] ), +} ) ); + +jest.mock( 'wcstripe/data/account/hooks', () => ( { + useAccount: jest.fn().mockReturnValue( { data: {} } ), +} ) ); +jest.mock( 'wcstripe/data/account-keys/hooks', () => ( { + useAccountKeys: jest.fn().mockReturnValue( {} ), + useAccountKeysPublishableKey: jest.fn().mockReturnValue( [ '' ] ), + useAccountKeysTestPublishableKey: jest.fn().mockReturnValue( [ '' ] ), +} ) ); + +jest.mock( '../express-checkout-button-preview' ); +ExpressCheckoutButtonPreview.mockImplementation( () => '<>' ); + +jest.mock( '../utils/utils', () => ( { + getPaymentRequestData: jest.fn().mockReturnValue( { + publishableKey: 'pk_test_123', + accountId: '0001', + locale: 'en', + } ), +} ) ); +jest.mock( '@woocommerce/blocks-checkout', () => {}, { virtual: true } ); + +const getMockPaymentRequestEnabledSettings = ( + isEnabled, + updateIsPaymentRequestEnabledHandler +) => [ isEnabled, updateIsPaymentRequestEnabledHandler ]; + +const getMockPaymentRequestLocations = ( + isCheckoutEnabled, + isProductPageEnabled, + isCartEnabled, + updatePaymentRequestLocationsHandler +) => [ + [ + isCheckoutEnabled && 'checkout', + isProductPageEnabled && 'product', + isCartEnabled && 'cart', + ].filter( Boolean ), + updatePaymentRequestLocationsHandler, +]; + +describe( 'PaymentRequestsSettingsSection', () => { + const globalValues = global.wc_stripe_payment_request_settings_params; + + beforeEach( () => { + usePaymentRequestEnabledSettings.mockReturnValue( + getMockPaymentRequestEnabledSettings( true, jest.fn() ) + ); + + usePaymentRequestLocations.mockReturnValue( + getMockPaymentRequestLocations( true, true, true, jest.fn() ) + ); + + global.wc_stripe_payment_request_settings_params = { + ...globalValues, + key: 'pk_test_123', + locale: 'en', + is_ece_enabled: true, + }; + } ); + + afterEach( () => { + jest.clearAllMocks(); + global.wc_stripe_payment_request_settings_params = globalValues; + } ); + + it( 'should enable express checkout locations when express checkout is enabled', () => { + render( ); + + const [ checkoutCheckbox, productPageCheckbox, cartCheckbox ] = + screen.getAllByRole( 'checkbox' ); + + expect( checkoutCheckbox ).not.toBeDisabled(); + expect( checkoutCheckbox ).toBeChecked(); + expect( productPageCheckbox ).not.toBeDisabled(); + expect( productPageCheckbox ).toBeChecked(); + expect( cartCheckbox ).not.toBeDisabled(); + expect( cartCheckbox ).toBeChecked(); + } ); + + it( 'should trigger an action to save the checked locations when un-checking the location checkboxes', async () => { + const updatePaymentRequestLocationsHandler = jest.fn(); + usePaymentRequestEnabledSettings.mockReturnValue( [ true, jest.fn() ] ); + usePaymentRequestLocations.mockReturnValue( + getMockPaymentRequestLocations( + true, + true, + true, + updatePaymentRequestLocationsHandler + ) + ); + + render( ); + + // Uncheck each checkbox, and verify them what kind of action should have been called + await userEvent.click( screen.getByText( 'Product page' ) ); + + expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( + [ 'checkout', 'cart' ] + ); + + await userEvent.click( screen.getByText( 'Checkout' ) ); + + expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( + [ 'product', 'cart' ] + ); + + await userEvent.click( screen.getByText( 'Cart' ) ); + + expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( + [ 'checkout', 'product' ] + ); + } ); + + it( 'should trigger an action to save the checked locations when checking the location checkboxes', async () => { + const updatePaymentRequestLocationsHandler = jest.fn(); + usePaymentRequestEnabledSettings.mockReturnValue( [ true, jest.fn() ] ); + usePaymentRequestLocations.mockReturnValue( + getMockPaymentRequestLocations( + false, + false, + false, + updatePaymentRequestLocationsHandler + ) + ); + + render( ); + + await userEvent.click( screen.getByText( 'Cart' ) ); + + expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( + [ 'cart' ] + ); + + await userEvent.click( screen.getByText( 'Product page' ) ); + + expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( + [ 'product' ] + ); + + await userEvent.click( screen.getByText( 'Checkout' ) ); + + expect( updatePaymentRequestLocationsHandler ).toHaveBeenLastCalledWith( + [ 'checkout' ] + ); + } ); +} ); diff --git a/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings.test.js b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings.test.js new file mode 100644 index 0000000000..37d7af7fab --- /dev/null +++ b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings.test.js @@ -0,0 +1,146 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import ExpressCheckoutSettingsSection from '../express-checkout-settings-section'; +import ExpressCheckoutButtonPreview from '../express-checkout-button-preview'; +import { + usePaymentRequestEnabledSettings, + usePaymentRequestLocations, + usePaymentRequestButtonType, + usePaymentRequestButtonSize, + usePaymentRequestButtonTheme, +} from 'wcstripe/data'; + +jest.mock( 'wcstripe/data', () => ( { + usePaymentRequestEnabledSettings: jest.fn(), + usePaymentRequestLocations: jest.fn(), + usePaymentRequestButtonType: jest.fn().mockReturnValue( [ 'buy' ] ), + usePaymentRequestButtonSize: jest.fn().mockReturnValue( [ 'default' ] ), + usePaymentRequestButtonTheme: jest.fn().mockReturnValue( [ 'dark' ] ), +} ) ); +jest.mock( 'wcstripe/data/account/hooks', () => ( { + useAccount: jest.fn().mockReturnValue( { data: {} } ), +} ) ); +jest.mock( 'wcstripe/data/account-keys/hooks', () => ( { + useAccountKeys: jest.fn().mockReturnValue( {} ), + useAccountKeysPublishableKey: jest.fn().mockReturnValue( [ '' ] ), + useAccountKeysTestPublishableKey: jest.fn().mockReturnValue( [ '' ] ), +} ) ); +jest.mock( '@woocommerce/blocks-checkout', () => {}, { virtual: true } ); + +jest.mock( '../express-checkout-button-preview' ); +ExpressCheckoutButtonPreview.mockImplementation( () => '<>' ); + +jest.mock( '../utils/utils', () => ( { + getPaymentRequestData: jest.fn().mockReturnValue( { + publishableKey: 'pk_test_123', + accountId: '0001', + locale: 'en', + } ), +} ) ); + +const getMockPaymentRequestEnabledSettings = ( + isEnabled, + updateIsPaymentRequestEnabledHandler +) => [ isEnabled, updateIsPaymentRequestEnabledHandler ]; + +const getMockPaymentRequestLocations = ( + isCheckoutEnabled, + isProductPageEnabled, + isCartEnabled, + updatePaymentRequestLocationsHandler +) => [ + [ + isCheckoutEnabled && 'checkout', + isProductPageEnabled && 'product', + isCartEnabled && 'cart', + ].filter( Boolean ), + updatePaymentRequestLocationsHandler, +]; + +describe( 'PaymentRequestsSettingsSection', () => { + const globalValues = global.wc_stripe_payment_request_settings_params; + beforeEach( () => { + usePaymentRequestEnabledSettings.mockReturnValue( + getMockPaymentRequestEnabledSettings( true, jest.fn() ) + ); + + usePaymentRequestLocations.mockReturnValue( + getMockPaymentRequestLocations( true, true, true, jest.fn() ) + ); + + global.wc_stripe_payment_request_settings_params = { + ...globalValues, + key: 'pk_test_123', + locale: 'en', + is_ece_enabled: true, + }; + } ); + + afterEach( () => { + jest.clearAllMocks(); + global.wc_stripe_payment_request_settings_params = globalValues; + } ); + + it( 'renders settings with defaults', () => { + render( ); + + // confirm settings headings. + expect( + screen.queryByRole( 'heading', { name: 'Call to action' } ) + ).toBeInTheDocument(); + expect( + screen.queryByRole( 'heading', { name: 'Appearance' } ) + ).toBeInTheDocument(); + + // confirm radio button groups displayed. + const [ ctaRadio, sizeRadio, themeRadio ] = + screen.queryAllByRole( 'radio' ); + + expect( ctaRadio ).toBeInTheDocument(); + expect( sizeRadio ).toBeInTheDocument(); + expect( themeRadio ).toBeInTheDocument(); + + // confirm default values. + expect( screen.getByLabelText( 'Buy' ) ).toBeChecked(); + expect( screen.getByLabelText( 'Default (48 px)' ) ).toBeChecked(); + expect( screen.getByLabelText( /Dark/ ) ).toBeChecked(); + } ); + + it( 'triggers the hooks when the settings are being interacted with', async () => { + const setButtonTypeMock = jest.fn(); + const setButtonSizeMock = jest.fn(); + const setButtonThemeMock = jest.fn(); + + usePaymentRequestButtonType.mockReturnValue( [ + 'buy', + setButtonTypeMock, + ] ); + usePaymentRequestButtonSize.mockReturnValue( [ + 'default', + setButtonSizeMock, + ] ); + usePaymentRequestButtonTheme.mockReturnValue( [ + 'dark', + setButtonThemeMock, + ] ); + usePaymentRequestEnabledSettings.mockReturnValue( [ true, jest.fn() ] ); + + render( ); + + expect( setButtonTypeMock ).not.toHaveBeenCalled(); + expect( setButtonSizeMock ).not.toHaveBeenCalled(); + expect( setButtonThemeMock ).not.toHaveBeenCalled(); + + await userEvent.click( screen.getByLabelText( /Light/ ) ); + + expect( setButtonThemeMock ).toHaveBeenCalledWith( 'light' ); + + await userEvent.click( screen.getByLabelText( 'Book' ) ); + + expect( setButtonTypeMock ).toHaveBeenCalledWith( 'book' ); + + await userEvent.click( screen.getByLabelText( 'Large (56 px)' ) ); + + expect( setButtonSizeMock ).toHaveBeenCalledWith( 'large' ); + } ); +} ); diff --git a/client/entrypoints/express-checkout-settings/express-checkout-button-preview.js b/client/entrypoints/express-checkout-settings/express-checkout-button-preview.js new file mode 100644 index 0000000000..7b3adcc4eb --- /dev/null +++ b/client/entrypoints/express-checkout-settings/express-checkout-button-preview.js @@ -0,0 +1,139 @@ +import { React, useState, useEffect } from 'react'; +import { + PaymentRequestButtonElement, + useStripe, +} from '@stripe/react-stripe-js'; +import { shouldUseGooglePayBrand } from './utils/utils'; +import { __, sprintf } from '@wordpress/i18n'; +import InlineNotice from 'wcstripe/components/inline-notice'; +import { + usePaymentRequestButtonType, + usePaymentRequestButtonSize, + usePaymentRequestButtonTheme, +} from 'wcstripe/data'; + +/** + * stripePromise is used to pass into 's stripe props. + * The stripe prop in can't be change once passed in. + * Keeping this outside of so that + * re-rendering does not change it. + */ + +const BrowserHelpText = () => { + let browser = 'Google Chrome'; + let paymentMethodName = 'Google Pay'; + + if ( shouldUseGooglePayBrand() ) { + browser = 'Safari'; + paymentMethodName = 'Apple Pay'; + } + + return ( +

+ { sprintf( + /* translators: %1: Payment method name %2: Browser name. */ + __( + 'To preview the %1$s button, view this page in the %2$s browser.', + 'woocommerce-gateway-stripe' + ), + paymentMethodName, + browser + ) } +

+ ); +}; + +const buttonSizeToPxMap = { + small: 40, + default: 48, + large: 56, +}; + +const ExpressCheckoutButtonPreview = () => { + const stripe = useStripe(); + const [ paymentRequest, setPaymentRequest ] = useState(); + const [ isLoading, setIsLoading ] = useState( true ); + const [ buttonType ] = usePaymentRequestButtonType(); + const [ size ] = usePaymentRequestButtonSize(); + const [ theme ] = usePaymentRequestButtonTheme(); + + useEffect( () => { + // when `stripe` is falsy, it means that it didn't load because of some error (like: the website wasn't loaded with HTTPS). + if ( ! stripe ) { + setIsLoading( false ); + return; + } + + setIsLoading( true ); + // Create a preview for payment button. The label and its total are placeholders. + const stripePaymentRequest = stripe.paymentRequest( { + country: 'US', + currency: 'usd', + total: { + label: __( 'Total', 'woocommerce-gateway-stripe' ), + amount: 99, + }, + requestPayerName: true, + requestPayerEmail: true, + } ); + + // Check the availability of the Payment Request API. + stripePaymentRequest.canMakePayment().then( ( result ) => { + if ( result ) { + setPaymentRequest( stripePaymentRequest ); + } + setIsLoading( false ); + } ); + }, [ stripe, setPaymentRequest, setIsLoading ] ); + + /** + * If stripe is loading, then display nothing. + * If stripe finished loading but payment request button failed to load (null), display info section. + * If stripe finished loading and payment request button loads, display the button. + */ + if ( isLoading ) { + return null; + } + + if ( ! paymentRequest ) { + return ( + + { __( + 'To preview the buttons, ' + + 'ensure your device is configured to accept Apple Pay or Google Pay, ' + + 'and view this page using the Safari or Chrome browsers.', + 'woocommerce-gateway-stripe' + ) } + + ); + } + + return ( + <> +
+ { + e.preventDefault(); + } } + options={ { + paymentRequest, + style: { + paymentRequestButton: { + type: buttonType, + theme, + height: `${ + buttonSizeToPxMap[ size ] || + buttonSizeToPxMap.default + }px`, + }, + }, + } } + /> +
+ + + ); +}; + +export default ExpressCheckoutButtonPreview; diff --git a/client/entrypoints/express-checkout-settings/express-checkout-enable-section.js b/client/entrypoints/express-checkout-settings/express-checkout-enable-section.js new file mode 100644 index 0000000000..0b104fd593 --- /dev/null +++ b/client/entrypoints/express-checkout-settings/express-checkout-enable-section.js @@ -0,0 +1,31 @@ +import React from 'react'; +import { __ } from '@wordpress/i18n'; +import { Card, CheckboxControl } from '@wordpress/components'; +import { usePaymentRequestEnabledSettings } from 'wcstripe/data'; +import CardBody from 'wcstripe/settings/card-body'; +const ExpressCheckoutEnableSection = () => { + const [ isPaymentRequestEnabled, updateIsPaymentRequestEnabled ] = + usePaymentRequestEnabledSettings(); + + return ( + + + + + + ); +}; + +export default ExpressCheckoutEnableSection; diff --git a/client/entrypoints/express-checkout-settings/express-checkout-page.js b/client/entrypoints/express-checkout-settings/express-checkout-page.js new file mode 100644 index 0000000000..87640cff0c --- /dev/null +++ b/client/entrypoints/express-checkout-settings/express-checkout-page.js @@ -0,0 +1,62 @@ +import React from 'react'; +import PaymentRequestIcon from '../../payment-method-icons/payment-request'; +import ExpressCheckoutEnableSection from './express-checkout-enable-section'; +import ExpressCheckoutSettingsSection from './express-checkout-settings-section'; +import { __ } from '@wordpress/i18n'; +import SettingsSection from 'wcstripe/settings/settings-section'; +import SettingsLayout from 'wcstripe/settings/settings-layout'; +import LoadableSettingsSection from 'wcstripe/settings/loadable-settings-section'; +import SaveSettingsSection from 'wcstripe/settings/save-settings-section'; +import './style.scss'; + +const EnableDescription = () => ( + <> +
+ +
+

+ { __( + 'Decide how buttons for digital wallets Apple Pay and ' + + 'Google Pay are displayed in your store. Depending on ' + + 'their web browser and their wallet configurations, ' + + 'your customers will see either Apple Pay or Google Pay, ' + + 'but not both.', + 'woocommerce-gateway-stripe' + ) } +

+ +); + +const SettingsDescription = () => ( + <> +

{ __( 'Settings', 'woocommerce-gateway-stripe' ) }

+

+ { __( + 'Configure the display of Apple Pay and Google Pay buttons on your store.', + 'woocommerce-gateway-stripe' + ) } +

+ +); + +const ExpressCheckoutPage = () => { + return ( + + + + + + + + + + + + + + + + ); +}; + +export default ExpressCheckoutPage; diff --git a/client/entrypoints/express-checkout-settings/express-checkout-preview-component.js b/client/entrypoints/express-checkout-settings/express-checkout-preview-component.js new file mode 100644 index 0000000000..d657e25099 --- /dev/null +++ b/client/entrypoints/express-checkout-settings/express-checkout-preview-component.js @@ -0,0 +1,129 @@ +/* global wc_stripe_payment_request_settings_params */ + +import { useState, useMemo } from 'react'; +import { Elements, ExpressCheckoutElement } from '@stripe/react-stripe-js'; +import { loadStripe } from '@stripe/stripe-js'; +import { __ } from '@wordpress/i18n'; +import { getDefaultBorderRadius } from 'wcstripe/express-checkout/utils'; +import InlineNotice from 'components/inline-notice'; +import { + EXPRESS_PAYMENT_METHOD_SETTING_APPLE_PAY, + EXPRESS_PAYMENT_METHOD_SETTING_GOOGLE_PAY, + PAYMENT_METHOD_CARD, +} from 'wcstripe/stripe-utils/constants'; + +const buttonSizeToPxMap = { + small: 40, + default: 48, + large: 56, +}; + +const ExpressCheckoutPreviewComponent = ( { buttonType, theme, size } ) => { + const [ canRenderButtons, setCanRenderButtons ] = useState( true ); + + /* eslint-disable camelcase */ + const stripePromise = useMemo( () => { + return loadStripe( wc_stripe_payment_request_settings_params.key, { + locale: wc_stripe_payment_request_settings_params.locale, + } ); + }, [] ); + /* eslint-enable camelcase */ + + const options = { + mode: 'payment', + amount: 1000, + currency: 'usd', + appearance: { + variables: { + borderRadius: `${ getDefaultBorderRadius() }px`, + spacingUnit: '6px', + }, + }, + paymentMethodTypes: [ PAYMENT_METHOD_CARD ], + }; + + const height = buttonSizeToPxMap[ size ] || buttonSizeToPxMap.medium; + + const mapThemeConfigToButtonTheme = ( paymentMethod, buttonTheme ) => { + switch ( buttonTheme ) { + case 'dark': + return 'black'; + case 'light': + return 'white'; + case 'light-outline': + if ( + paymentMethod === EXPRESS_PAYMENT_METHOD_SETTING_GOOGLE_PAY + ) { + return 'white'; + } + return 'white-outline'; + default: + return 'black'; + } + }; + + const type = buttonType === 'default' ? 'plain' : buttonType; + + const buttonOptions = { + buttonHeight: Math.min( Math.max( height, 40 ), 55 ), + buttonTheme: { + googlePay: mapThemeConfigToButtonTheme( + EXPRESS_PAYMENT_METHOD_SETTING_GOOGLE_PAY, + theme + ), + applePay: mapThemeConfigToButtonTheme( + EXPRESS_PAYMENT_METHOD_SETTING_APPLE_PAY, + theme + ), + }, + buttonType: { + googlePay: type, + applePay: type, + }, + paymentMethods: { + link: 'never', + googlePay: 'always', + applePay: 'always', + }, + layout: { overflow: 'never' }, + }; + + const onReady = ( { availablePaymentMethods } ) => { + if ( availablePaymentMethods ) { + setCanRenderButtons( true ); + } else { + setCanRenderButtons( false ); + } + }; + + if ( canRenderButtons ) { + return ( +
+ + {} } + onReady={ onReady } + /> + +
+ ); + } + + return ( + + { __( + 'Failed to preview the Apple Pay or Google Pay button. ' + + 'Ensure your store uses HTTPS on a publicly available domain ' + + "and you're viewing this page in a Safari or Chrome browser. " + + 'Your device must be configured to use Apple Pay or Google Pay.', + 'woocommerce-gateway-stripe' + ) } + + ); +}; + +export default ExpressCheckoutPreviewComponent; diff --git a/client/entrypoints/express-checkout-settings/express-checkout-settings-section.js b/client/entrypoints/express-checkout-settings/express-checkout-settings-section.js new file mode 100644 index 0000000000..846b824b2c --- /dev/null +++ b/client/entrypoints/express-checkout-settings/express-checkout-settings-section.js @@ -0,0 +1,304 @@ +/* global wc_stripe_payment_request_settings_params */ + +import { ADMIN_URL, getSetting } from '@woocommerce/settings'; +import React, { useMemo } from 'react'; +import interpolateComponents from 'interpolate-components'; +import { Elements } from '@stripe/react-stripe-js'; +import { loadStripe } from '@stripe/stripe-js'; +import styled from '@emotion/styled'; +import ExpressCheckoutButtonPreview from './express-checkout-button-preview'; +import ExpressCheckoutPreviewComponent from './express-checkout-preview-component'; +import { + Card, + RadioControl, + CheckboxControl, + Notice, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { + usePaymentRequestEnabledSettings, + usePaymentRequestLocations, + usePaymentRequestButtonType, + usePaymentRequestButtonSize, + usePaymentRequestButtonTheme, +} from 'wcstripe/data'; +import CardBody from 'wcstripe/settings/card-body'; +import LoadableAccountSection from 'wcstripe/settings/loadable-account-section'; +import { useAccount } from 'wcstripe/data/account/hooks'; +import { + useAccountKeysPublishableKey, + useAccountKeysTestPublishableKey, +} from 'wcstripe/data/account-keys/hooks'; + +const makeButtonSizeText = ( string ) => + interpolateComponents( { + mixedString: string, + components: { + helpText: ( + + ), + }, + } ); +const buttonSizeOptions = [ + { + label: makeButtonSizeText( + __( + 'Small {{helpText}}(40 px){{/helpText}}', + 'woocommerce-gateway-stripe' + ) + ), + value: 'small', + }, + { + label: makeButtonSizeText( + __( + 'Default {{helpText}}(48 px){{/helpText}}', + 'woocommerce-gateway-stripe' + ) + ), + value: 'default', + }, + { + label: makeButtonSizeText( + __( + 'Large {{helpText}}(56 px){{/helpText}}', + 'woocommerce-gateway-stripe' + ) + ), + value: 'large', + }, +]; +const buttonActionOptions = [ + { + label: __( 'Only icon', 'woocommerce-gateway-stripe' ), + value: 'default', + }, + { + label: __( 'Buy', 'woocommerce-gateway-stripe' ), + value: 'buy', + }, + { + label: __( 'Donate', 'woocommerce-gateway-stripe' ), + value: 'donate', + }, + { + label: __( 'Book', 'woocommerce-gateway-stripe' ), + value: 'book', + }, +]; + +const makeButtonThemeText = ( string ) => + interpolateComponents( { + mixedString: string, + components: { + br:
, + helpText: ( + + ), + }, + } ); +const buttonThemeOptions = [ + { + label: makeButtonThemeText( + __( + 'Dark {{br/}}{{helpText}}Recommended for white or light-colored backgrounds with high contrast.{{/helpText}}', + 'woocommerce-gateway-stripe' + ) + ), + value: 'dark', + }, + { + label: makeButtonThemeText( + __( + 'Light {{br/}}{{helpText}}Recommended for dark or colored backgrounds with high contrast.{{/helpText}}', + 'woocommerce-gateway-stripe' + ) + ), + value: 'light', + }, + { + label: makeButtonThemeText( + __( + 'Outline {{br/}}{{helpText}}Recommended for white or light-colored backgrounds with insufficient contrast.{{/helpText}}', + 'woocommerce-gateway-stripe' + ) + ), + value: 'light-outline', + }, +]; + +const ExpressCheckoutSettingsSection = () => { + const [ buttonType, setButtonType ] = usePaymentRequestButtonType(); + const [ size, setSize ] = usePaymentRequestButtonSize(); + const [ theme, setTheme ] = usePaymentRequestButtonTheme(); + const accountId = useAccount().data?.account?.id; + const [ publishableKey ] = useAccountKeysPublishableKey(); + const [ testPublishableKey ] = useAccountKeysTestPublishableKey(); + const isECEEnabled = + wc_stripe_payment_request_settings_params.is_ece_enabled; // eslint-disable-line camelcase + + const stripePromise = useMemo( () => { + return loadStripe( + publishableKey || testPublishableKey || 'pk_test_123', + { + stripeAccount: accountId || '0001', + locale: 'en', + } + ); + }, [ testPublishableKey, publishableKey, accountId ] ); + + const [ isPaymentRequestEnabled ] = usePaymentRequestEnabledSettings(); + + const [ paymentRequestLocations, updatePaymentRequestLocations ] = + usePaymentRequestLocations(); + + const makeLocationChangeHandler = ( location ) => ( isChecked ) => { + if ( isChecked ) { + updatePaymentRequestLocations( [ + ...paymentRequestLocations, + location, + ] ); + } else { + updatePaymentRequestLocations( + paymentRequestLocations.filter( ( name ) => name !== location ) + ); + } + }; + + const StyledLink = styled.a` + &:focus, + &:visited { + box-shadow: none; + } + `; + + return ( + + + + { interpolateComponents( { + mixedString: __( + 'Some appearance settings may be overridden by the express payment section of the ' + + '{{checkoutPageLink}}Cart & Checkout blocks{{/checkoutPageLink}}.', + 'woocommerce-gateway-stripe' + ), + components: { + checkoutPageLink: ( + { + // Stop propagation is necessary so it doesn't trigger the tooltip click event. + ev.stopPropagation(); + } } + /> + ), + }, + } ) } + +

+ { __( + 'Show express checkouts on', + 'woocommerce-gateway-stripe' + ) } +

+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+

+ { __( 'Call to action', 'woocommerce-gateway-stripe' ) } +

+ +

{ __( 'Appearance', 'woocommerce-gateway-stripe' ) }

+ + +

{ __( 'Preview', 'woocommerce-gateway-stripe' ) }

+ + { isECEEnabled ? ( + + ) : ( + + + + ) } + +
+
+ ); +}; + +export default ExpressCheckoutSettingsSection; diff --git a/client/entrypoints/express-checkout-settings/index.js b/client/entrypoints/express-checkout-settings/index.js new file mode 100644 index 0000000000..1095b13ae3 --- /dev/null +++ b/client/entrypoints/express-checkout-settings/index.js @@ -0,0 +1,11 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import ExpressCheckoutPage from './express-checkout-page'; + +const container = document.getElementById( + 'wc-stripe-express-checkout-settings-container' +); + +if ( container ) { + createRoot( container ).render( ); +} diff --git a/client/entrypoints/express-checkout-settings/style.scss b/client/entrypoints/express-checkout-settings/style.scss new file mode 100644 index 0000000000..b9fae34f61 --- /dev/null +++ b/client/entrypoints/express-checkout-settings/style.scss @@ -0,0 +1,70 @@ +@use '../../styles/abstracts/styles'; + +.payment-method-settings { + &__breadcrumbs { + margin-bottom: 40px; + } + + &__option-muted-text { + color: styles.$gray-700; + } + + &__option-help-text { + color: styles.$gray-700; + padding-left: 30px; + + @media ( min-width: 600px ) { + padding-left: 26px; + } + } + + &__cta-selection { + .components-base-control__label { + // hack until the `hideLabelFromVision` is fixed for radio controls in Gutenberg + display: none; + } + } + + &__preview { + border: 1px dashed styles.$gray-300; + box-sizing: border-box; + border-radius: 3px; + background-color: styles.$gray-100; + padding: 16px; + } + + &__preview-help-text { + font-style: italic; + } +} + +.components-radio-control__input[type='radio']:checked::before { + box-sizing: border-box; +} + +.express-checkout-settings { + &__location { + margin-bottom: 26px !important; + } + + .components-card-body { + padding: calc(16px) calc(24px); + + @include styles.breakpoint( '>660px' ) { + padding: 24px 24px 24px 24px; + } + } + + &__icon { + border-radius: 2px; + display: none; + height: 40px; + margin: 1px 17px 1px 1px; // 1px to accommodate for box-shadow + box-shadow: 0 0 0 1px styles.$gray-300; + background: styles.$white; + + @include styles.breakpoint( '>660px' ) { + display: inline-block; + } + } +} diff --git a/client/entrypoints/express-checkout-settings/utils/utils.js b/client/entrypoints/express-checkout-settings/utils/utils.js new file mode 100644 index 0000000000..8262c3450b --- /dev/null +++ b/client/entrypoints/express-checkout-settings/utils/utils.js @@ -0,0 +1,15 @@ +/** + * Whether or not to use Google Pay branded button in Chrome. + * + * @return {boolean} Use Google Pay button in Chrome. + */ +export const shouldUseGooglePayBrand = () => { + const ua = window.navigator.userAgent.toLowerCase(); + const isChrome = + /chrome/.test( ua ) && + ! /edge|edg|opr|brave\//.test( ua ) && + window.navigator.vendor === 'Google Inc.'; + // newer versions of Brave do not have the userAgent string + const isBrave = isChrome && window.navigator.brave; + return isChrome && ! isBrave; +}; diff --git a/webpack.config.js b/webpack.config.js index 21da041207..551ea7f905 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -118,6 +118,8 @@ module.exports = { 'upe-settings': './client/settings/index.js', 'payment-gateways': './client/entrypoints/payment-gateways/index.js', 'express-checkout': './client/entrypoints/express-checkout/index.js', + 'express-checkout-settings': + './client/entrypoints/express-checkout-settings/index.js', 'amazon-pay-settings': './client/entrypoints/amazon-pay-settings/index.js', }, From 70a6c6eccdc851ebe9344e3b3c2e49a929909c17 Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Tue, 30 Sep 2025 17:21:58 -0300 Subject: [PATCH 04/11] Revert renaming of PRBs settings --- .../amazon-pay-settings/amazon-pay-page.js | 2 +- .../entrypoints/express-checkout-settings/index.js | 11 ----------- .../payment-request-button-preview.test.js} | 14 +++++++------- .../payment-request-settings-locations.test.js} | 14 +++++++------- .../__tests__/payment-request-settings.test.js} | 12 ++++++------ .../express-checkout-button-preview.js} | 0 .../entrypoints/payment-request-settings/index.js | 11 +++++++++++ .../payment-request-button-preview.js} | 4 ++-- .../payment-request-enable-section.js} | 4 ++-- .../payment-request-page.js} | 12 ++++++------ .../payment-request-settings-section.js} | 10 +++++----- .../style.scss | 6 ++++-- .../utils/utils.js | 0 webpack.config.js | 4 ++-- 14 files changed, 53 insertions(+), 51 deletions(-) delete mode 100644 client/entrypoints/express-checkout-settings/index.js rename client/entrypoints/{express-checkout-settings/__tests__/express-checkout-button-preview.test.js => payment-request-settings/__tests__/payment-request-button-preview.test.js} (89%) rename client/entrypoints/{express-checkout-settings/__tests__/express-checkout-settings-locations.test.js => payment-request-settings/__tests__/payment-request-settings-locations.test.js} (91%) rename client/entrypoints/{express-checkout-settings/__tests__/express-checkout-settings.test.js => payment-request-settings/__tests__/payment-request-settings.test.js} (91%) rename client/entrypoints/{express-checkout-settings/express-checkout-preview-component.js => payment-request-settings/express-checkout-button-preview.js} (100%) create mode 100644 client/entrypoints/payment-request-settings/index.js rename client/entrypoints/{express-checkout-settings/express-checkout-button-preview.js => payment-request-settings/payment-request-button-preview.js} (97%) rename client/entrypoints/{express-checkout-settings/express-checkout-enable-section.js => payment-request-settings/payment-request-enable-section.js} (90%) rename client/entrypoints/{express-checkout-settings/express-checkout-page.js => payment-request-settings/payment-request-page.js} (83%) rename client/entrypoints/{express-checkout-settings/express-checkout-settings-section.js => payment-request-settings/payment-request-settings-section.js} (97%) rename client/entrypoints/{express-checkout-settings => payment-request-settings}/style.scss (97%) rename client/entrypoints/{express-checkout-settings => payment-request-settings}/utils/utils.js (100%) diff --git a/client/entrypoints/amazon-pay-settings/amazon-pay-page.js b/client/entrypoints/amazon-pay-settings/amazon-pay-page.js index 9df3c14c07..b6a99a309d 100644 --- a/client/entrypoints/amazon-pay-settings/amazon-pay-page.js +++ b/client/entrypoints/amazon-pay-settings/amazon-pay-page.js @@ -7,7 +7,7 @@ import SettingsSection from 'wcstripe/settings/settings-section'; import SettingsLayout from 'wcstripe/settings/settings-layout'; import LoadableSettingsSection from 'wcstripe/settings/loadable-settings-section'; import SaveSettingsSection from 'wcstripe/settings/save-settings-section'; -import '../express-checkout-settings/style.scss'; +import '../payment-request-settings/style.scss'; const EnableDescription = () => ( <> diff --git a/client/entrypoints/express-checkout-settings/index.js b/client/entrypoints/express-checkout-settings/index.js deleted file mode 100644 index 1095b13ae3..0000000000 --- a/client/entrypoints/express-checkout-settings/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import { createRoot } from 'react-dom/client'; -import ExpressCheckoutPage from './express-checkout-page'; - -const container = document.getElementById( - 'wc-stripe-express-checkout-settings-container' -); - -if ( container ) { - createRoot( container ).render( ); -} diff --git a/client/entrypoints/express-checkout-settings/__tests__/express-checkout-button-preview.test.js b/client/entrypoints/payment-request-settings/__tests__/payment-request-button-preview.test.js similarity index 89% rename from client/entrypoints/express-checkout-settings/__tests__/express-checkout-button-preview.test.js rename to client/entrypoints/payment-request-settings/__tests__/payment-request-button-preview.test.js index 8a3558934d..36268bad7a 100644 --- a/client/entrypoints/express-checkout-settings/__tests__/express-checkout-button-preview.test.js +++ b/client/entrypoints/payment-request-settings/__tests__/payment-request-button-preview.test.js @@ -1,7 +1,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { useStripe } from '@stripe/react-stripe-js'; -import ExpressCheckoutButtonPreview from '../express-checkout-button-preview'; +import PaymentRequestsButtonPreview from '../payment-request-button-preview'; import { shouldUseGooglePayBrand } from '../utils/utils'; // We need to mock the actual module being used by `` in the `@wordpress/components` module @@ -30,7 +30,7 @@ jest.mock( 'wcstripe/data', () => ( { usePaymentRequestButtonTheme: jest.fn().mockReturnValue( [ 'dark' ] ), } ) ); -describe( 'ExpressCheckoutButtonPreview', () => { +describe( 'PaymentRequestsButtonPreview', () => { const canMakePaymentMock = jest.fn(); beforeEach( () => { @@ -50,7 +50,7 @@ describe( 'ExpressCheckoutButtonPreview', () => { it( 'displays Google Chrome and Google Pay when page is in Safari', async () => { shouldUseGooglePayBrand.mockReturnValue( false ); - render( ); + render( ); expect( await screen.findByText( @@ -63,7 +63,7 @@ describe( 'ExpressCheckoutButtonPreview', () => { it( 'displays Safari Apple Pay when page is in Google Chrome', async () => { shouldUseGooglePayBrand.mockReturnValue( true ); - render( ); + render( ); expect( await screen.findByText( @@ -76,7 +76,7 @@ describe( 'ExpressCheckoutButtonPreview', () => { it( 'displays an info notice if stripe is falsy', async () => { useStripe.mockReturnValue( null ); - render( ); + render( ); expect( screen.queryByText( 'Stripe button mock' ) @@ -90,7 +90,7 @@ describe( 'ExpressCheckoutButtonPreview', () => { it( 'displays an info notice if stripe fails to load', async () => { canMakePaymentMock.mockResolvedValue( null ); - render( ); + render( ); expect( await screen.findByText( @@ -103,7 +103,7 @@ describe( 'ExpressCheckoutButtonPreview', () => { } ); it( 'displays the payment button when stripe is loaded', async () => { - render( ); + render( ); expect( await screen.findByText( 'Stripe button mock' ) diff --git a/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings-locations.test.js b/client/entrypoints/payment-request-settings/__tests__/payment-request-settings-locations.test.js similarity index 91% rename from client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings-locations.test.js rename to client/entrypoints/payment-request-settings/__tests__/payment-request-settings-locations.test.js index 88c8ad23f2..7548543b88 100644 --- a/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings-locations.test.js +++ b/client/entrypoints/payment-request-settings/__tests__/payment-request-settings-locations.test.js @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import ExpressCheckoutSettingsSection from '../express-checkout-settings-section'; -import ExpressCheckoutButtonPreview from '../express-checkout-button-preview'; +import PaymentRequestsSettingsSection from '../payment-request-settings-section'; +import PaymentRequestButtonPreview from '../payment-request-button-preview'; import { usePaymentRequestEnabledSettings, usePaymentRequestLocations, @@ -24,8 +24,8 @@ jest.mock( 'wcstripe/data/account-keys/hooks', () => ( { useAccountKeysTestPublishableKey: jest.fn().mockReturnValue( [ '' ] ), } ) ); -jest.mock( '../express-checkout-button-preview' ); -ExpressCheckoutButtonPreview.mockImplementation( () => '<>' ); +jest.mock( '../payment-request-button-preview' ); +PaymentRequestButtonPreview.mockImplementation( () => '<>' ); jest.mock( '../utils/utils', () => ( { getPaymentRequestData: jest.fn().mockReturnValue( { @@ -81,7 +81,7 @@ describe( 'PaymentRequestsSettingsSection', () => { } ); it( 'should enable express checkout locations when express checkout is enabled', () => { - render( ); + render( ); const [ checkoutCheckbox, productPageCheckbox, cartCheckbox ] = screen.getAllByRole( 'checkbox' ); @@ -106,7 +106,7 @@ describe( 'PaymentRequestsSettingsSection', () => { ) ); - render( ); + render( ); // Uncheck each checkbox, and verify them what kind of action should have been called await userEvent.click( screen.getByText( 'Product page' ) ); @@ -140,7 +140,7 @@ describe( 'PaymentRequestsSettingsSection', () => { ) ); - render( ); + render( ); await userEvent.click( screen.getByText( 'Cart' ) ); diff --git a/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings.test.js b/client/entrypoints/payment-request-settings/__tests__/payment-request-settings.test.js similarity index 91% rename from client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings.test.js rename to client/entrypoints/payment-request-settings/__tests__/payment-request-settings.test.js index 37d7af7fab..126e1d6a79 100644 --- a/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings.test.js +++ b/client/entrypoints/payment-request-settings/__tests__/payment-request-settings.test.js @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import ExpressCheckoutSettingsSection from '../express-checkout-settings-section'; -import ExpressCheckoutButtonPreview from '../express-checkout-button-preview'; +import PaymentRequestsSettingsSection from '../payment-request-settings-section'; +import PaymentRequestButtonPreview from '../payment-request-button-preview'; import { usePaymentRequestEnabledSettings, usePaymentRequestLocations, @@ -27,8 +27,8 @@ jest.mock( 'wcstripe/data/account-keys/hooks', () => ( { } ) ); jest.mock( '@woocommerce/blocks-checkout', () => {}, { virtual: true } ); -jest.mock( '../express-checkout-button-preview' ); -ExpressCheckoutButtonPreview.mockImplementation( () => '<>' ); +jest.mock( '../payment-request-button-preview' ); +PaymentRequestButtonPreview.mockImplementation( () => '<>' ); jest.mock( '../utils/utils', () => ( { getPaymentRequestData: jest.fn().mockReturnValue( { @@ -82,7 +82,7 @@ describe( 'PaymentRequestsSettingsSection', () => { } ); it( 'renders settings with defaults', () => { - render( ); + render( ); // confirm settings headings. expect( @@ -125,7 +125,7 @@ describe( 'PaymentRequestsSettingsSection', () => { ] ); usePaymentRequestEnabledSettings.mockReturnValue( [ true, jest.fn() ] ); - render( ); + render( ); expect( setButtonTypeMock ).not.toHaveBeenCalled(); expect( setButtonSizeMock ).not.toHaveBeenCalled(); diff --git a/client/entrypoints/express-checkout-settings/express-checkout-preview-component.js b/client/entrypoints/payment-request-settings/express-checkout-button-preview.js similarity index 100% rename from client/entrypoints/express-checkout-settings/express-checkout-preview-component.js rename to client/entrypoints/payment-request-settings/express-checkout-button-preview.js diff --git a/client/entrypoints/payment-request-settings/index.js b/client/entrypoints/payment-request-settings/index.js new file mode 100644 index 0000000000..23f325c8f2 --- /dev/null +++ b/client/entrypoints/payment-request-settings/index.js @@ -0,0 +1,11 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import PaymentRequestsPage from './payment-request-page'; + +const container = document.getElementById( + 'wc-stripe-payment-request-settings-container' +); + +if ( container ) { + createRoot( container ).render( ); +} diff --git a/client/entrypoints/express-checkout-settings/express-checkout-button-preview.js b/client/entrypoints/payment-request-settings/payment-request-button-preview.js similarity index 97% rename from client/entrypoints/express-checkout-settings/express-checkout-button-preview.js rename to client/entrypoints/payment-request-settings/payment-request-button-preview.js index 7b3adcc4eb..963114068d 100644 --- a/client/entrypoints/express-checkout-settings/express-checkout-button-preview.js +++ b/client/entrypoints/payment-request-settings/payment-request-button-preview.js @@ -49,7 +49,7 @@ const buttonSizeToPxMap = { large: 56, }; -const ExpressCheckoutButtonPreview = () => { +const PaymentRequestsButtonPreview = () => { const stripe = useStripe(); const [ paymentRequest, setPaymentRequest ] = useState(); const [ isLoading, setIsLoading ] = useState( true ); @@ -136,4 +136,4 @@ const ExpressCheckoutButtonPreview = () => { ); }; -export default ExpressCheckoutButtonPreview; +export default PaymentRequestsButtonPreview; diff --git a/client/entrypoints/express-checkout-settings/express-checkout-enable-section.js b/client/entrypoints/payment-request-settings/payment-request-enable-section.js similarity index 90% rename from client/entrypoints/express-checkout-settings/express-checkout-enable-section.js rename to client/entrypoints/payment-request-settings/payment-request-enable-section.js index 0b104fd593..d82f71042e 100644 --- a/client/entrypoints/express-checkout-settings/express-checkout-enable-section.js +++ b/client/entrypoints/payment-request-settings/payment-request-enable-section.js @@ -3,7 +3,7 @@ import { __ } from '@wordpress/i18n'; import { Card, CheckboxControl } from '@wordpress/components'; import { usePaymentRequestEnabledSettings } from 'wcstripe/data'; import CardBody from 'wcstripe/settings/card-body'; -const ExpressCheckoutEnableSection = () => { +const PaymentRequestsEnableSection = () => { const [ isPaymentRequestEnabled, updateIsPaymentRequestEnabled ] = usePaymentRequestEnabledSettings(); @@ -28,4 +28,4 @@ const ExpressCheckoutEnableSection = () => { ); }; -export default ExpressCheckoutEnableSection; +export default PaymentRequestsEnableSection; diff --git a/client/entrypoints/express-checkout-settings/express-checkout-page.js b/client/entrypoints/payment-request-settings/payment-request-page.js similarity index 83% rename from client/entrypoints/express-checkout-settings/express-checkout-page.js rename to client/entrypoints/payment-request-settings/payment-request-page.js index 87640cff0c..092fff43fd 100644 --- a/client/entrypoints/express-checkout-settings/express-checkout-page.js +++ b/client/entrypoints/payment-request-settings/payment-request-page.js @@ -1,7 +1,7 @@ import React from 'react'; import PaymentRequestIcon from '../../payment-method-icons/payment-request'; -import ExpressCheckoutEnableSection from './express-checkout-enable-section'; -import ExpressCheckoutSettingsSection from './express-checkout-settings-section'; +import PaymentRequestsEnableSection from './payment-request-enable-section'; +import PaymentRequestsSettingsSection from './payment-request-settings-section'; import { __ } from '@wordpress/i18n'; import SettingsSection from 'wcstripe/settings/settings-section'; import SettingsLayout from 'wcstripe/settings/settings-layout'; @@ -39,18 +39,18 @@ const SettingsDescription = () => ( ); -const ExpressCheckoutPage = () => { +const PaymentRequestsPage = () => { return ( - + - + @@ -59,4 +59,4 @@ const ExpressCheckoutPage = () => { ); }; -export default ExpressCheckoutPage; +export default PaymentRequestsPage; diff --git a/client/entrypoints/express-checkout-settings/express-checkout-settings-section.js b/client/entrypoints/payment-request-settings/payment-request-settings-section.js similarity index 97% rename from client/entrypoints/express-checkout-settings/express-checkout-settings-section.js rename to client/entrypoints/payment-request-settings/payment-request-settings-section.js index 846b824b2c..d7513e2e96 100644 --- a/client/entrypoints/express-checkout-settings/express-checkout-settings-section.js +++ b/client/entrypoints/payment-request-settings/payment-request-settings-section.js @@ -6,8 +6,8 @@ import interpolateComponents from 'interpolate-components'; import { Elements } from '@stripe/react-stripe-js'; import { loadStripe } from '@stripe/stripe-js'; import styled from '@emotion/styled'; -import ExpressCheckoutButtonPreview from './express-checkout-button-preview'; -import ExpressCheckoutPreviewComponent from './express-checkout-preview-component'; +import PaymentRequestButtonPreview from './payment-request-button-preview'; +import ExpressCheckoutPreviewComponent from './express-checkout-button-preview'; import { Card, RadioControl, @@ -127,7 +127,7 @@ const buttonThemeOptions = [ }, ]; -const ExpressCheckoutSettingsSection = () => { +const PaymentRequestsSettingsSection = () => { const [ buttonType, setButtonType ] = usePaymentRequestButtonType(); const [ size, setSize ] = usePaymentRequestButtonSize(); const [ theme, setTheme ] = usePaymentRequestButtonTheme(); @@ -292,7 +292,7 @@ const ExpressCheckoutSettingsSection = () => { /> ) : ( - + ) } @@ -301,4 +301,4 @@ const ExpressCheckoutSettingsSection = () => { ); }; -export default ExpressCheckoutSettingsSection; +export default PaymentRequestsSettingsSection; diff --git a/client/entrypoints/express-checkout-settings/style.scss b/client/entrypoints/payment-request-settings/style.scss similarity index 97% rename from client/entrypoints/express-checkout-settings/style.scss rename to client/entrypoints/payment-request-settings/style.scss index b9fae34f61..8aeb235705 100644 --- a/client/entrypoints/express-checkout-settings/style.scss +++ b/client/entrypoints/payment-request-settings/style.scss @@ -42,11 +42,13 @@ box-sizing: border-box; } -.express-checkout-settings { +.payment-request-settings { &__location { margin-bottom: 26px !important; } +} +.express-checkout-settings { .components-card-body { padding: calc(16px) calc(24px); @@ -67,4 +69,4 @@ display: inline-block; } } -} +} \ No newline at end of file diff --git a/client/entrypoints/express-checkout-settings/utils/utils.js b/client/entrypoints/payment-request-settings/utils/utils.js similarity index 100% rename from client/entrypoints/express-checkout-settings/utils/utils.js rename to client/entrypoints/payment-request-settings/utils/utils.js diff --git a/webpack.config.js b/webpack.config.js index 551ea7f905..0e300b9649 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -113,13 +113,13 @@ module.exports = { }, entry: { index: './client/blocks/index.js', + 'payment-requests-settings': + './client/entrypoints/payment-request-settings/index.js', 'upe-classic': './client/classic/upe/index.js', 'upe-blocks': './client/blocks/upe/index.js', 'upe-settings': './client/settings/index.js', 'payment-gateways': './client/entrypoints/payment-gateways/index.js', 'express-checkout': './client/entrypoints/express-checkout/index.js', - 'express-checkout-settings': - './client/entrypoints/express-checkout-settings/index.js', 'amazon-pay-settings': './client/entrypoints/amazon-pay-settings/index.js', }, From e0e47970ede3122465bc5c8e7b6c5d248ec98de2 Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Tue, 30 Sep 2025 17:24:56 -0300 Subject: [PATCH 05/11] Changelog and readme entries update --- changelog.txt | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 216bbfca7a..a6513ec8de 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,7 @@ *** Changelog *** = 10.0.0 - xxxx-xx-xx = -* Dev - Removes all the frontend code related to Payment Request Buttons +* Dev - Removes frontend code related to Payment Request Buttons in the checkout page * Update - Removing the `wc_stripe_is_upe_checkout_enabled` filter, as Legacy Checkout is no longer supported * Dev - Upgrades `jest` to version 29.7.0, `@wordpress/scripts` to 26.19.0, and adds `axios`(version 1.12.2) to the JavaScript development dependencies * Update - Shows the Stripe account connection modal in settings when the merchant did not connect via OAuth along with a new notice diff --git a/readme.txt b/readme.txt index d3afda38a8..410a64b4fe 100644 --- a/readme.txt +++ b/readme.txt @@ -111,7 +111,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o == Changelog == = 10.0.0 - xxxx-xx-xx = -* Dev - Removes all the frontend code related to Payment Request Buttons +* Dev - Removes frontend code related to Payment Request Buttons in the checkout page * Update - Removing the `wc_stripe_is_upe_checkout_enabled` filter, as Legacy Checkout is no longer supported * Dev - Upgrades `jest` to version 29.7.0, `@wordpress/scripts` to 26.19.0, and adds `axios`(version 1.12.2) to the JavaScript development dependencies * Update - Shows the Stripe account connection modal in settings when the merchant did not connect via OAuth along with a new notice From b37e9f9f9f5eabf385e9d2e8295a04dda2444d3d Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Tue, 30 Sep 2025 17:34:37 -0300 Subject: [PATCH 06/11] Partially renaming PRBs settings files --- client/entrypoints/amazon-pay-settings/amazon-pay-page.js | 2 +- .../__tests__/payment-request-button-preview.test.js | 0 .../__tests__/payment-request-settings-locations.test.js | 0 .../__tests__/payment-request-settings.test.js | 0 .../express-checkout-button-preview.js | 0 .../index.js | 0 .../payment-request-button-preview.js | 0 .../payment-request-enable-section.js | 0 .../payment-request-page.js | 0 .../payment-request-settings-section.js | 0 .../style.scss | 0 .../utils/utils.js | 0 .../admin/class-wc-stripe-payment-requests-controller.php | 6 +++--- webpack.config.js | 4 ++-- 14 files changed, 6 insertions(+), 6 deletions(-) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/__tests__/payment-request-button-preview.test.js (100%) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/__tests__/payment-request-settings-locations.test.js (100%) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/__tests__/payment-request-settings.test.js (100%) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/express-checkout-button-preview.js (100%) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/index.js (100%) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/payment-request-button-preview.js (100%) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/payment-request-enable-section.js (100%) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/payment-request-page.js (100%) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/payment-request-settings-section.js (100%) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/style.scss (100%) rename client/entrypoints/{payment-request-settings => express-checkout-settings}/utils/utils.js (100%) diff --git a/client/entrypoints/amazon-pay-settings/amazon-pay-page.js b/client/entrypoints/amazon-pay-settings/amazon-pay-page.js index b6a99a309d..9df3c14c07 100644 --- a/client/entrypoints/amazon-pay-settings/amazon-pay-page.js +++ b/client/entrypoints/amazon-pay-settings/amazon-pay-page.js @@ -7,7 +7,7 @@ import SettingsSection from 'wcstripe/settings/settings-section'; import SettingsLayout from 'wcstripe/settings/settings-layout'; import LoadableSettingsSection from 'wcstripe/settings/loadable-settings-section'; import SaveSettingsSection from 'wcstripe/settings/save-settings-section'; -import '../payment-request-settings/style.scss'; +import '../express-checkout-settings/style.scss'; const EnableDescription = () => ( <> diff --git a/client/entrypoints/payment-request-settings/__tests__/payment-request-button-preview.test.js b/client/entrypoints/express-checkout-settings/__tests__/payment-request-button-preview.test.js similarity index 100% rename from client/entrypoints/payment-request-settings/__tests__/payment-request-button-preview.test.js rename to client/entrypoints/express-checkout-settings/__tests__/payment-request-button-preview.test.js diff --git a/client/entrypoints/payment-request-settings/__tests__/payment-request-settings-locations.test.js b/client/entrypoints/express-checkout-settings/__tests__/payment-request-settings-locations.test.js similarity index 100% rename from client/entrypoints/payment-request-settings/__tests__/payment-request-settings-locations.test.js rename to client/entrypoints/express-checkout-settings/__tests__/payment-request-settings-locations.test.js diff --git a/client/entrypoints/payment-request-settings/__tests__/payment-request-settings.test.js b/client/entrypoints/express-checkout-settings/__tests__/payment-request-settings.test.js similarity index 100% rename from client/entrypoints/payment-request-settings/__tests__/payment-request-settings.test.js rename to client/entrypoints/express-checkout-settings/__tests__/payment-request-settings.test.js diff --git a/client/entrypoints/payment-request-settings/express-checkout-button-preview.js b/client/entrypoints/express-checkout-settings/express-checkout-button-preview.js similarity index 100% rename from client/entrypoints/payment-request-settings/express-checkout-button-preview.js rename to client/entrypoints/express-checkout-settings/express-checkout-button-preview.js diff --git a/client/entrypoints/payment-request-settings/index.js b/client/entrypoints/express-checkout-settings/index.js similarity index 100% rename from client/entrypoints/payment-request-settings/index.js rename to client/entrypoints/express-checkout-settings/index.js diff --git a/client/entrypoints/payment-request-settings/payment-request-button-preview.js b/client/entrypoints/express-checkout-settings/payment-request-button-preview.js similarity index 100% rename from client/entrypoints/payment-request-settings/payment-request-button-preview.js rename to client/entrypoints/express-checkout-settings/payment-request-button-preview.js diff --git a/client/entrypoints/payment-request-settings/payment-request-enable-section.js b/client/entrypoints/express-checkout-settings/payment-request-enable-section.js similarity index 100% rename from client/entrypoints/payment-request-settings/payment-request-enable-section.js rename to client/entrypoints/express-checkout-settings/payment-request-enable-section.js diff --git a/client/entrypoints/payment-request-settings/payment-request-page.js b/client/entrypoints/express-checkout-settings/payment-request-page.js similarity index 100% rename from client/entrypoints/payment-request-settings/payment-request-page.js rename to client/entrypoints/express-checkout-settings/payment-request-page.js diff --git a/client/entrypoints/payment-request-settings/payment-request-settings-section.js b/client/entrypoints/express-checkout-settings/payment-request-settings-section.js similarity index 100% rename from client/entrypoints/payment-request-settings/payment-request-settings-section.js rename to client/entrypoints/express-checkout-settings/payment-request-settings-section.js diff --git a/client/entrypoints/payment-request-settings/style.scss b/client/entrypoints/express-checkout-settings/style.scss similarity index 100% rename from client/entrypoints/payment-request-settings/style.scss rename to client/entrypoints/express-checkout-settings/style.scss diff --git a/client/entrypoints/payment-request-settings/utils/utils.js b/client/entrypoints/express-checkout-settings/utils/utils.js similarity index 100% rename from client/entrypoints/payment-request-settings/utils/utils.js rename to client/entrypoints/express-checkout-settings/utils/utils.js diff --git a/includes/admin/class-wc-stripe-payment-requests-controller.php b/includes/admin/class-wc-stripe-payment-requests-controller.php index 56189bd0c0..2d9ac45f25 100644 --- a/includes/admin/class-wc-stripe-payment-requests-controller.php +++ b/includes/admin/class-wc-stripe-payment-requests-controller.php @@ -19,7 +19,7 @@ public function __construct() { */ public function admin_scripts() { // Webpack generates an assets file containing a dependencies array for our built JS file. - $script_asset_path = WC_STRIPE_PLUGIN_PATH . '/build/payment-requests-settings.asset.php'; + $script_asset_path = WC_STRIPE_PLUGIN_PATH . '/build/express-checkout-settings.asset.php'; $asset_metadata = file_exists( $script_asset_path ) ? require $script_asset_path : [ @@ -28,7 +28,7 @@ public function admin_scripts() { ]; wp_register_script( 'wc-stripe-payment-request-settings', - plugins_url( 'build/payment-requests-settings.js', WC_STRIPE_MAIN_FILE ), + plugins_url( 'build/express-checkout-settings.js', WC_STRIPE_MAIN_FILE ), $asset_metadata['dependencies'], $asset_metadata['version'], true @@ -53,7 +53,7 @@ public function admin_scripts() { wp_register_style( 'wc-stripe-payment-request-settings', - plugins_url( 'build/payment-requests-settings.css', WC_STRIPE_MAIN_FILE ), + plugins_url( 'build/express-checkout-settings.css', WC_STRIPE_MAIN_FILE ), [ 'wc-components' ], $asset_metadata['version'] ); diff --git a/webpack.config.js b/webpack.config.js index 0e300b9649..551ea7f905 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -113,13 +113,13 @@ module.exports = { }, entry: { index: './client/blocks/index.js', - 'payment-requests-settings': - './client/entrypoints/payment-request-settings/index.js', 'upe-classic': './client/classic/upe/index.js', 'upe-blocks': './client/blocks/upe/index.js', 'upe-settings': './client/settings/index.js', 'payment-gateways': './client/entrypoints/payment-gateways/index.js', 'express-checkout': './client/entrypoints/express-checkout/index.js', + 'express-checkout-settings': + './client/entrypoints/express-checkout-settings/index.js', 'amazon-pay-settings': './client/entrypoints/amazon-pay-settings/index.js', }, From a4cddceb731f5b1dd4a7e80e4baf75b88da9593e Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Tue, 30 Sep 2025 17:39:15 -0300 Subject: [PATCH 07/11] Renaming additional files --- .../amazon-pay-settings/amazon-pay-settings-section.js | 2 +- ...-button-preview.js => express-checkout-preview-component.js} | 0 ...-button-preview.js => express-checkout-preview-component.js} | 0 .../payment-request-settings-section.js | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename client/entrypoints/amazon-pay-settings/{express-checkout-button-preview.js => express-checkout-preview-component.js} (100%) rename client/entrypoints/express-checkout-settings/{express-checkout-button-preview.js => express-checkout-preview-component.js} (100%) diff --git a/client/entrypoints/amazon-pay-settings/amazon-pay-settings-section.js b/client/entrypoints/amazon-pay-settings/amazon-pay-settings-section.js index baba2780a0..eedd2c8dbb 100644 --- a/client/entrypoints/amazon-pay-settings/amazon-pay-settings-section.js +++ b/client/entrypoints/amazon-pay-settings/amazon-pay-settings-section.js @@ -3,7 +3,7 @@ import React, { useMemo } from 'react'; import interpolateComponents from 'interpolate-components'; import { loadStripe } from '@stripe/stripe-js'; import styled from '@emotion/styled'; -import ExpressCheckoutPreviewComponent from './express-checkout-button-preview'; +import ExpressCheckoutPreviewComponent from './express-checkout-preview-component'; import { Card, RadioControl, diff --git a/client/entrypoints/amazon-pay-settings/express-checkout-button-preview.js b/client/entrypoints/amazon-pay-settings/express-checkout-preview-component.js similarity index 100% rename from client/entrypoints/amazon-pay-settings/express-checkout-button-preview.js rename to client/entrypoints/amazon-pay-settings/express-checkout-preview-component.js diff --git a/client/entrypoints/express-checkout-settings/express-checkout-button-preview.js b/client/entrypoints/express-checkout-settings/express-checkout-preview-component.js similarity index 100% rename from client/entrypoints/express-checkout-settings/express-checkout-button-preview.js rename to client/entrypoints/express-checkout-settings/express-checkout-preview-component.js diff --git a/client/entrypoints/express-checkout-settings/payment-request-settings-section.js b/client/entrypoints/express-checkout-settings/payment-request-settings-section.js index d7513e2e96..88c89c675b 100644 --- a/client/entrypoints/express-checkout-settings/payment-request-settings-section.js +++ b/client/entrypoints/express-checkout-settings/payment-request-settings-section.js @@ -7,7 +7,7 @@ import { Elements } from '@stripe/react-stripe-js'; import { loadStripe } from '@stripe/stripe-js'; import styled from '@emotion/styled'; import PaymentRequestButtonPreview from './payment-request-button-preview'; -import ExpressCheckoutPreviewComponent from './express-checkout-button-preview'; +import ExpressCheckoutPreviewComponent from './express-checkout-preview-component'; import { Card, RadioControl, From ccc26b051eb2286ee8fc6a5ed8aca7a9a5b83ca6 Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Tue, 30 Sep 2025 17:44:00 -0300 Subject: [PATCH 08/11] Renaming additional files --- .../payment-request-button-preview.test.js | 14 +++++++------- ...eview.js => express-checkout-button-preview.js} | 4 ++-- .../payment-request-settings-section.js | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) rename client/entrypoints/express-checkout-settings/{payment-request-button-preview.js => express-checkout-button-preview.js} (97%) diff --git a/client/entrypoints/express-checkout-settings/__tests__/payment-request-button-preview.test.js b/client/entrypoints/express-checkout-settings/__tests__/payment-request-button-preview.test.js index 36268bad7a..8a3558934d 100644 --- a/client/entrypoints/express-checkout-settings/__tests__/payment-request-button-preview.test.js +++ b/client/entrypoints/express-checkout-settings/__tests__/payment-request-button-preview.test.js @@ -1,7 +1,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { useStripe } from '@stripe/react-stripe-js'; -import PaymentRequestsButtonPreview from '../payment-request-button-preview'; +import ExpressCheckoutButtonPreview from '../express-checkout-button-preview'; import { shouldUseGooglePayBrand } from '../utils/utils'; // We need to mock the actual module being used by `` in the `@wordpress/components` module @@ -30,7 +30,7 @@ jest.mock( 'wcstripe/data', () => ( { usePaymentRequestButtonTheme: jest.fn().mockReturnValue( [ 'dark' ] ), } ) ); -describe( 'PaymentRequestsButtonPreview', () => { +describe( 'ExpressCheckoutButtonPreview', () => { const canMakePaymentMock = jest.fn(); beforeEach( () => { @@ -50,7 +50,7 @@ describe( 'PaymentRequestsButtonPreview', () => { it( 'displays Google Chrome and Google Pay when page is in Safari', async () => { shouldUseGooglePayBrand.mockReturnValue( false ); - render( ); + render( ); expect( await screen.findByText( @@ -63,7 +63,7 @@ describe( 'PaymentRequestsButtonPreview', () => { it( 'displays Safari Apple Pay when page is in Google Chrome', async () => { shouldUseGooglePayBrand.mockReturnValue( true ); - render( ); + render( ); expect( await screen.findByText( @@ -76,7 +76,7 @@ describe( 'PaymentRequestsButtonPreview', () => { it( 'displays an info notice if stripe is falsy', async () => { useStripe.mockReturnValue( null ); - render( ); + render( ); expect( screen.queryByText( 'Stripe button mock' ) @@ -90,7 +90,7 @@ describe( 'PaymentRequestsButtonPreview', () => { it( 'displays an info notice if stripe fails to load', async () => { canMakePaymentMock.mockResolvedValue( null ); - render( ); + render( ); expect( await screen.findByText( @@ -103,7 +103,7 @@ describe( 'PaymentRequestsButtonPreview', () => { } ); it( 'displays the payment button when stripe is loaded', async () => { - render( ); + render( ); expect( await screen.findByText( 'Stripe button mock' ) diff --git a/client/entrypoints/express-checkout-settings/payment-request-button-preview.js b/client/entrypoints/express-checkout-settings/express-checkout-button-preview.js similarity index 97% rename from client/entrypoints/express-checkout-settings/payment-request-button-preview.js rename to client/entrypoints/express-checkout-settings/express-checkout-button-preview.js index 963114068d..7b3adcc4eb 100644 --- a/client/entrypoints/express-checkout-settings/payment-request-button-preview.js +++ b/client/entrypoints/express-checkout-settings/express-checkout-button-preview.js @@ -49,7 +49,7 @@ const buttonSizeToPxMap = { large: 56, }; -const PaymentRequestsButtonPreview = () => { +const ExpressCheckoutButtonPreview = () => { const stripe = useStripe(); const [ paymentRequest, setPaymentRequest ] = useState(); const [ isLoading, setIsLoading ] = useState( true ); @@ -136,4 +136,4 @@ const PaymentRequestsButtonPreview = () => { ); }; -export default PaymentRequestsButtonPreview; +export default ExpressCheckoutButtonPreview; diff --git a/client/entrypoints/express-checkout-settings/payment-request-settings-section.js b/client/entrypoints/express-checkout-settings/payment-request-settings-section.js index 88c89c675b..74218f5ff2 100644 --- a/client/entrypoints/express-checkout-settings/payment-request-settings-section.js +++ b/client/entrypoints/express-checkout-settings/payment-request-settings-section.js @@ -6,7 +6,7 @@ import interpolateComponents from 'interpolate-components'; import { Elements } from '@stripe/react-stripe-js'; import { loadStripe } from '@stripe/stripe-js'; import styled from '@emotion/styled'; -import PaymentRequestButtonPreview from './payment-request-button-preview'; +import ExpressCheckoutButtonPreview from './express-checkout-button-preview'; import ExpressCheckoutPreviewComponent from './express-checkout-preview-component'; import { Card, @@ -292,7 +292,7 @@ const PaymentRequestsSettingsSection = () => { /> ) : ( - + ) } From 44f2b42d94ab7627a456e8913c3909a43e4728d2 Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Tue, 30 Sep 2025 17:54:08 -0300 Subject: [PATCH 09/11] Renaming additional files --- ...s => express-checkout-button-preview.test.js} | 0 ... express-checkout-settings-locations.test.js} | 16 ++++++++-------- ...test.js => express-checkout-settings.test.js} | 14 +++++++------- ...ion.js => express-checkout-enable-section.js} | 4 ++-- ...-request-page.js => express-checkout-page.js} | 12 ++++++------ ...n.js => express-checkout-settings-section.js} | 4 ++-- .../express-checkout-settings/index.js | 4 ++-- 7 files changed, 27 insertions(+), 27 deletions(-) rename client/entrypoints/express-checkout-settings/__tests__/{payment-request-button-preview.test.js => express-checkout-button-preview.test.js} (100%) rename client/entrypoints/express-checkout-settings/__tests__/{payment-request-settings-locations.test.js => express-checkout-settings-locations.test.js} (90%) rename client/entrypoints/express-checkout-settings/__tests__/{payment-request-settings.test.js => express-checkout-settings.test.js} (89%) rename client/entrypoints/express-checkout-settings/{payment-request-enable-section.js => express-checkout-enable-section.js} (90%) rename client/entrypoints/express-checkout-settings/{payment-request-page.js => express-checkout-page.js} (83%) rename client/entrypoints/express-checkout-settings/{payment-request-settings-section.js => express-checkout-settings-section.js} (98%) diff --git a/client/entrypoints/express-checkout-settings/__tests__/payment-request-button-preview.test.js b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-button-preview.test.js similarity index 100% rename from client/entrypoints/express-checkout-settings/__tests__/payment-request-button-preview.test.js rename to client/entrypoints/express-checkout-settings/__tests__/express-checkout-button-preview.test.js diff --git a/client/entrypoints/express-checkout-settings/__tests__/payment-request-settings-locations.test.js b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings-locations.test.js similarity index 90% rename from client/entrypoints/express-checkout-settings/__tests__/payment-request-settings-locations.test.js rename to client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings-locations.test.js index 7548543b88..1006bec2c4 100644 --- a/client/entrypoints/express-checkout-settings/__tests__/payment-request-settings-locations.test.js +++ b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings-locations.test.js @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import PaymentRequestsSettingsSection from '../payment-request-settings-section'; -import PaymentRequestButtonPreview from '../payment-request-button-preview'; +import ExpressCheckoutSettingsSection from '../express-checkout-settings-section'; +import ExpressCheckoutButtonPreview from '../express-checkout-button-preview'; import { usePaymentRequestEnabledSettings, usePaymentRequestLocations, @@ -24,8 +24,8 @@ jest.mock( 'wcstripe/data/account-keys/hooks', () => ( { useAccountKeysTestPublishableKey: jest.fn().mockReturnValue( [ '' ] ), } ) ); -jest.mock( '../payment-request-button-preview' ); -PaymentRequestButtonPreview.mockImplementation( () => '<>' ); +jest.mock( '../express-checkout-button-preview' ); +ExpressCheckoutButtonPreview.mockImplementation( () => '<>' ); jest.mock( '../utils/utils', () => ( { getPaymentRequestData: jest.fn().mockReturnValue( { @@ -55,7 +55,7 @@ const getMockPaymentRequestLocations = ( updatePaymentRequestLocationsHandler, ]; -describe( 'PaymentRequestsSettingsSection', () => { +describe( 'ExpressCheckoutSettingsSection', () => { const globalValues = global.wc_stripe_payment_request_settings_params; beforeEach( () => { @@ -81,7 +81,7 @@ describe( 'PaymentRequestsSettingsSection', () => { } ); it( 'should enable express checkout locations when express checkout is enabled', () => { - render( ); + render( ); const [ checkoutCheckbox, productPageCheckbox, cartCheckbox ] = screen.getAllByRole( 'checkbox' ); @@ -106,7 +106,7 @@ describe( 'PaymentRequestsSettingsSection', () => { ) ); - render( ); + render( ); // Uncheck each checkbox, and verify them what kind of action should have been called await userEvent.click( screen.getByText( 'Product page' ) ); @@ -140,7 +140,7 @@ describe( 'PaymentRequestsSettingsSection', () => { ) ); - render( ); + render( ); await userEvent.click( screen.getByText( 'Cart' ) ); diff --git a/client/entrypoints/express-checkout-settings/__tests__/payment-request-settings.test.js b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings.test.js similarity index 89% rename from client/entrypoints/express-checkout-settings/__tests__/payment-request-settings.test.js rename to client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings.test.js index 126e1d6a79..66c93a0a2c 100644 --- a/client/entrypoints/express-checkout-settings/__tests__/payment-request-settings.test.js +++ b/client/entrypoints/express-checkout-settings/__tests__/express-checkout-settings.test.js @@ -1,7 +1,6 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import PaymentRequestsSettingsSection from '../payment-request-settings-section'; -import PaymentRequestButtonPreview from '../payment-request-button-preview'; +import ExpressCheckoutSettingsSection from '../express-checkout-settings-section'; import { usePaymentRequestEnabledSettings, usePaymentRequestLocations, @@ -9,6 +8,7 @@ import { usePaymentRequestButtonSize, usePaymentRequestButtonTheme, } from 'wcstripe/data'; +import ExpressCheckoutButtonPreview from 'wcstripe/entrypoints/express-checkout-settings/express-checkout-button-preview'; jest.mock( 'wcstripe/data', () => ( { usePaymentRequestEnabledSettings: jest.fn(), @@ -27,8 +27,8 @@ jest.mock( 'wcstripe/data/account-keys/hooks', () => ( { } ) ); jest.mock( '@woocommerce/blocks-checkout', () => {}, { virtual: true } ); -jest.mock( '../payment-request-button-preview' ); -PaymentRequestButtonPreview.mockImplementation( () => '<>' ); +jest.mock( '../express-checkout-button-preview' ); +ExpressCheckoutButtonPreview.mockImplementation( () => '<>' ); jest.mock( '../utils/utils', () => ( { getPaymentRequestData: jest.fn().mockReturnValue( { @@ -57,7 +57,7 @@ const getMockPaymentRequestLocations = ( updatePaymentRequestLocationsHandler, ]; -describe( 'PaymentRequestsSettingsSection', () => { +describe( 'ExpressCheckoutSettingsSection', () => { const globalValues = global.wc_stripe_payment_request_settings_params; beforeEach( () => { usePaymentRequestEnabledSettings.mockReturnValue( @@ -82,7 +82,7 @@ describe( 'PaymentRequestsSettingsSection', () => { } ); it( 'renders settings with defaults', () => { - render( ); + render( ); // confirm settings headings. expect( @@ -125,7 +125,7 @@ describe( 'PaymentRequestsSettingsSection', () => { ] ); usePaymentRequestEnabledSettings.mockReturnValue( [ true, jest.fn() ] ); - render( ); + render( ); expect( setButtonTypeMock ).not.toHaveBeenCalled(); expect( setButtonSizeMock ).not.toHaveBeenCalled(); diff --git a/client/entrypoints/express-checkout-settings/payment-request-enable-section.js b/client/entrypoints/express-checkout-settings/express-checkout-enable-section.js similarity index 90% rename from client/entrypoints/express-checkout-settings/payment-request-enable-section.js rename to client/entrypoints/express-checkout-settings/express-checkout-enable-section.js index d82f71042e..0b104fd593 100644 --- a/client/entrypoints/express-checkout-settings/payment-request-enable-section.js +++ b/client/entrypoints/express-checkout-settings/express-checkout-enable-section.js @@ -3,7 +3,7 @@ import { __ } from '@wordpress/i18n'; import { Card, CheckboxControl } from '@wordpress/components'; import { usePaymentRequestEnabledSettings } from 'wcstripe/data'; import CardBody from 'wcstripe/settings/card-body'; -const PaymentRequestsEnableSection = () => { +const ExpressCheckoutEnableSection = () => { const [ isPaymentRequestEnabled, updateIsPaymentRequestEnabled ] = usePaymentRequestEnabledSettings(); @@ -28,4 +28,4 @@ const PaymentRequestsEnableSection = () => { ); }; -export default PaymentRequestsEnableSection; +export default ExpressCheckoutEnableSection; diff --git a/client/entrypoints/express-checkout-settings/payment-request-page.js b/client/entrypoints/express-checkout-settings/express-checkout-page.js similarity index 83% rename from client/entrypoints/express-checkout-settings/payment-request-page.js rename to client/entrypoints/express-checkout-settings/express-checkout-page.js index 092fff43fd..87640cff0c 100644 --- a/client/entrypoints/express-checkout-settings/payment-request-page.js +++ b/client/entrypoints/express-checkout-settings/express-checkout-page.js @@ -1,7 +1,7 @@ import React from 'react'; import PaymentRequestIcon from '../../payment-method-icons/payment-request'; -import PaymentRequestsEnableSection from './payment-request-enable-section'; -import PaymentRequestsSettingsSection from './payment-request-settings-section'; +import ExpressCheckoutEnableSection from './express-checkout-enable-section'; +import ExpressCheckoutSettingsSection from './express-checkout-settings-section'; import { __ } from '@wordpress/i18n'; import SettingsSection from 'wcstripe/settings/settings-section'; import SettingsLayout from 'wcstripe/settings/settings-layout'; @@ -39,18 +39,18 @@ const SettingsDescription = () => ( ); -const PaymentRequestsPage = () => { +const ExpressCheckoutPage = () => { return ( - + - + @@ -59,4 +59,4 @@ const PaymentRequestsPage = () => { ); }; -export default PaymentRequestsPage; +export default ExpressCheckoutPage; diff --git a/client/entrypoints/express-checkout-settings/payment-request-settings-section.js b/client/entrypoints/express-checkout-settings/express-checkout-settings-section.js similarity index 98% rename from client/entrypoints/express-checkout-settings/payment-request-settings-section.js rename to client/entrypoints/express-checkout-settings/express-checkout-settings-section.js index 74218f5ff2..846b824b2c 100644 --- a/client/entrypoints/express-checkout-settings/payment-request-settings-section.js +++ b/client/entrypoints/express-checkout-settings/express-checkout-settings-section.js @@ -127,7 +127,7 @@ const buttonThemeOptions = [ }, ]; -const PaymentRequestsSettingsSection = () => { +const ExpressCheckoutSettingsSection = () => { const [ buttonType, setButtonType ] = usePaymentRequestButtonType(); const [ size, setSize ] = usePaymentRequestButtonSize(); const [ theme, setTheme ] = usePaymentRequestButtonTheme(); @@ -301,4 +301,4 @@ const PaymentRequestsSettingsSection = () => { ); }; -export default PaymentRequestsSettingsSection; +export default ExpressCheckoutSettingsSection; diff --git a/client/entrypoints/express-checkout-settings/index.js b/client/entrypoints/express-checkout-settings/index.js index 23f325c8f2..0f9c017918 100644 --- a/client/entrypoints/express-checkout-settings/index.js +++ b/client/entrypoints/express-checkout-settings/index.js @@ -1,11 +1,11 @@ import React from 'react'; import { createRoot } from 'react-dom/client'; -import PaymentRequestsPage from './payment-request-page'; +import ExpressCheckoutPage from './express-checkout-page'; const container = document.getElementById( 'wc-stripe-payment-request-settings-container' ); if ( container ) { - createRoot( container ).render( ); + createRoot( container ).render( ); } From 93db40b8e614a6840a09911cd40573d3ccc3c56b Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Thu, 2 Oct 2025 17:59:29 -0300 Subject: [PATCH 10/11] Update changelog.txt Co-authored-by: daledupreez --- changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index ff2a8ea7f3..e36f65e67b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,7 @@ *** Changelog *** = 10.0.0 - xxxx-xx-xx = -* Dev - Removes frontend code related to Payment Request Buttons in the checkout page +* Update - Removes frontend code related to Payment Request Buttons in the checkout page * Dev - Expands the Stripe Order Helper class to handle source ID, refund ID, intent ID, and setup intent ID metas * Update - Removing the `wc_stripe_is_upe_checkout_enabled` filter, as Legacy Checkout is no longer supported * Dev - Upgrades `jest` to version 29.7.0, `@wordpress/scripts` to 26.19.0, and adds `axios`(version 1.12.2) to the JavaScript development dependencies From c6dd3b9937da8e5ba91fa6a6f57d5e928aa6365a Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Thu, 2 Oct 2025 18:00:21 -0300 Subject: [PATCH 11/11] Readme entry update --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 4c0671cdb5..7c098cffe5 100644 --- a/readme.txt +++ b/readme.txt @@ -111,7 +111,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o == Changelog == = 10.0.0 - xxxx-xx-xx = -* Dev - Removes frontend code related to Payment Request Buttons in the checkout page +* Update - Removes frontend code related to Payment Request Buttons in the checkout page * Dev - Expands the Stripe Order Helper class to handle source ID, refund ID, intent ID, and setup intent ID metas * Update - Removing the `wc_stripe_is_upe_checkout_enabled` filter, as Legacy Checkout is no longer supported * Dev - Upgrades `jest` to version 29.7.0, `@wordpress/scripts` to 26.19.0, and adds `axios`(version 1.12.2) to the JavaScript development dependencies