diff --git a/changelog/add-8413-compute-styles-on-add-payment-method-page b/changelog/add-8413-compute-styles-on-add-payment-method-page new file mode 100644 index 00000000000..4c51615aba1 --- /dev/null +++ b/changelog/add-8413-compute-styles-on-add-payment-method-page @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Add a separate transient to save UPE appearance styles for the Add Payment Method standalone page. Correct regression that prevented proper styles calculation in the shortcode checkout. diff --git a/client/checkout/classic/event-handlers.js b/client/checkout/classic/event-handlers.js index c034aaccedd..cd04e3a1374 100644 --- a/client/checkout/classic/event-handlers.js +++ b/client/checkout/classic/event-handlers.js @@ -69,7 +69,7 @@ jQuery( function ( $ ) { } ); $( document.body ).on( 'updated_checkout', () => { - maybeMountStripePaymentElement(); + maybeMountStripePaymentElement( 'shortcode_checkout' ); injectStripePMMEContainers(); } ); @@ -112,7 +112,11 @@ jQuery( function ( $ ) { } ); if ( $addPaymentMethodForm.length || $payForOrderForm.length ) { - maybeMountStripePaymentElement(); + maybeMountStripePaymentElement( 'add_payment_method' ); + } + + if ( $payForOrderForm.length ) { + maybeMountStripePaymentElement( 'shortcode_checkout' ); } $addPaymentMethodForm.on( 'submit', function () { @@ -214,13 +218,17 @@ jQuery( function ( $ ) { } } - async function maybeMountStripePaymentElement() { + async function maybeMountStripePaymentElement( elementsLocation ) { if ( $( '.wcpay-upe-element' ).length && ! $( '.wcpay-upe-element' ).children().length ) { for ( const upeElement of $( '.wcpay-upe-element' ).toArray() ) { - await mountStripePaymentElement( api, upeElement ); + await mountStripePaymentElement( + api, + upeElement, + elementsLocation + ); restrictPaymentMethodToLocation( upeElement ); } maybeEnableStripeLink( api ); diff --git a/client/checkout/classic/payment-processing.js b/client/checkout/classic/payment-processing.js index c3c50b60f33..ab10e4b5e6c 100644 --- a/client/checkout/classic/payment-processing.js +++ b/client/checkout/classic/payment-processing.js @@ -49,17 +49,24 @@ for ( const paymentMethodType in getUPEConfig( 'paymentMethodsConfig' ) ) { * it is simply returned. * * @param {Object} api The API object used to save the UPE configuration. + * @param {string} elementsLocation The location of the UPE elements. * @return {Promise} The appearance object for the UPE. */ -async function initializeAppearance( api ) { - const appearance = getUPEConfig( 'upeAppearance' ); +async function initializeAppearance( api, elementsLocation ) { + const upeConfigMap = { + shortcode_checkout: 'upeAppearance', + add_payment_method: 'upeAddPaymentMethodAppearance', + }; + const upeConfigProperty = + upeConfigMap[ elementsLocation ] ?? 'upeAppearance'; + const appearance = getUPEConfig( upeConfigProperty ); if ( appearance ) { return Promise.resolve( appearance ); } return await api.saveUPEAppearance( - getAppearance( 'shortcode_checkout' ), - 'shortcode_checkout' + getAppearance( elementsLocation ), + elementsLocation ); } @@ -202,9 +209,14 @@ function createStripePaymentMethod( * * @param {Object} api The API object used to create the Stripe payment element. * @param {string} paymentMethodType The type of Stripe payment method to create. + * @param {string} elementsLocation The location of the UPE elements. * @return {Object} A promise that resolves with the created Stripe payment element. */ -async function createStripePaymentElement( api, paymentMethodType ) { +async function createStripePaymentElement( + api, + paymentMethodType, + elementsLocation +) { const amount = Number( getUPEConfig( 'cartTotal' ) ); const paymentMethodTypes = getPaymentMethodTypes( paymentMethodType ); const options = { @@ -213,7 +225,7 @@ async function createStripePaymentElement( api, paymentMethodType ) { amount: amount, paymentMethodCreation: 'manual', paymentMethodTypes: paymentMethodTypes, - appearance: await initializeAppearance( api ), + appearance: await initializeAppearance( api, elementsLocation ), fonts: getFontRulesFromPage(), }; @@ -373,8 +385,13 @@ export function maybeEnableStripeLink( api ) { * * @param {Object} api The API object. * @param {string} domElement The selector of the DOM element of particular payment method to mount the UPE element to. + * @param {string} elementsLocation Thhe location of the UPE element. **/ -export async function mountStripePaymentElement( api, domElement ) { +export async function mountStripePaymentElement( + api, + domElement, + elementsLocation +) { try { if ( ! fingerprint ) { const { visitorId } = await getFingerprint(); @@ -404,7 +421,11 @@ export async function mountStripePaymentElement( api, domElement ) { const upeElement = gatewayUPEComponents[ paymentMethodType ].upeElement || - ( await createStripePaymentElement( api, paymentMethodType ) ); + ( await createStripePaymentElement( + api, + paymentMethodType, + elementsLocation + ) ); upeElement.mount( domElement ); upeElement.on( 'loaderror', ( e ) => { // setting the flag to true to prevent the form from being submitted. @@ -565,3 +586,15 @@ export const processPayment = ( // Prevent WC Core default form submission (see woocommerce/assets/js/frontend/checkout.js) from happening. return false; }; + +/** + * Used only for testing, resets the gatewayUPEComponents internal cache of elements for a given property. + * + * @param {string} paymentMethodType The paymentMethodType we want to remove the upeElement from. + * @return {void} + */ +export function __resetGatewayUPEComponentsElement( paymentMethodType ) { + if ( gatewayUPEComponents[ paymentMethodType ]?.upeElement ) { + delete gatewayUPEComponents[ paymentMethodType ].upeElement; + } +} diff --git a/client/checkout/classic/test/payment-processing.test.js b/client/checkout/classic/test/payment-processing.test.js index edcaf14107e..44a120fda50 100644 --- a/client/checkout/classic/test/payment-processing.test.js +++ b/client/checkout/classic/test/payment-processing.test.js @@ -6,6 +6,7 @@ import { mountStripePaymentElement, processPayment, renderTerms, + __resetGatewayUPEComponentsElement, } from '../payment-processing'; import { getAppearance } from '../../upe-styles'; import { getUPEConfig } from 'wcpay/utils/checkout'; @@ -142,108 +143,118 @@ describe( 'Stripe Payment Element mounting', () => { jest.clearAllMocks(); } ); - test( 'initializes the appearance when it is not set and saves it', async () => { - getUPEConfig.mockImplementation( ( argument ) => { - if ( - argument === 'wcBlocksUPEAppearance' || - argument === 'upeAppearance' - ) { - return null; - } - - if ( argument === 'paymentMethodsConfig' ) { - return { - card: { - label: 'Card', - forceNetworkSavedCards: true, - }, - giropay: { - label: 'Giropay', - forceNetworkSavedCards: false, - }, - ideal: { - label: 'iDEAL', - forceNetworkSavedCards: false, - }, - sepa: { - label: 'SEPA', - forceNetworkSavedCards: false, - }, - }; - } - - if ( argument === 'currency' ) { - return 'eur'; - } - } ); - - // Create a mock function to track the event dispatch for tokenization-form.js execution - const dispatchMock = jest.fn(); - document.body.dispatchEvent = dispatchMock; - - const appearanceMock = { backgroundColor: '#fff' }; - getAppearance.mockReturnValue( appearanceMock ); - getFingerprint.mockImplementation( () => { - return 'fingerprint'; - } ); - - mockDomElement.dataset.paymentMethodType = 'giropay'; - - await mountStripePaymentElement( apiMock, mockDomElement ); - - expect( getAppearance ).toHaveBeenCalled(); - expect( apiMock.saveUPEAppearance ).toHaveBeenCalledWith( - appearanceMock, - 'shortcode_checkout' - ); - expect( dispatchMock ).toHaveBeenCalled(); - } ); - - test( 'does not call getAppearance or saveUPEAppearance if appearance is already set', async () => { - const appearanceMock = { backgroundColor: '#fff' }; - getAppearance.mockReturnValue( appearanceMock ); - getFingerprint.mockImplementation( () => { - return 'fingerprint'; - } ); - getUPEConfig.mockImplementation( ( argument ) => { - if ( argument === 'currency' ) { - return 'eur'; - } - - if ( argument === 'upeAppearance' ) { - return { - backgroundColor: '#fff', - }; - } - - if ( argument === 'paymentMethodsConfig' ) { - return { - ideal: { - label: 'iDEAL', - forceNetworkSavedCards: false, - }, - card: { - label: 'Card', - forceNetworkSavedCards: true, - }, - giropay: { - label: 'Giropay', - forceNetworkSavedCards: false, - }, - sepa: { - label: 'SEPA', - forceNetworkSavedCards: false, - }, - }; - } + [ + { + elementsLocation: 'shortcode_checkout', + expectedProperty: 'upeAppearance', + }, + { + elementsLocation: 'add_payment_method', + expectedProperty: 'upeAddPaymentMethodAppearance', + }, + { + elementsLocation: 'other', + expectedProperty: 'upeAppearance', + }, + ].forEach( ( { elementsLocation, expectedProperty } ) => { + describe( `when elementsLocation is ${ elementsLocation }`, () => { + beforeEach( () => { + __resetGatewayUPEComponentsElement( 'giropay' ); + } ); + + test( 'initializes the appearance when it is not set and saves it', async () => { + getUPEConfig.mockImplementation( ( argument ) => { + if ( + argument === 'upeAddPaymentMethodAppearance' || + argument === 'upeAppearance' + ) { + return null; + } + + if ( argument === 'paymentMethodsConfig' ) { + return { + giropay: { + label: 'Giropay', + forceNetworkSavedCards: false, + }, + }; + } + + if ( argument === 'currency' ) { + return 'eur'; + } + } ); + + // Create a mock function to track the event dispatch for tokenization-form.js execution + const dispatchMock = jest.fn(); + document.body.dispatchEvent = dispatchMock; + + const appearanceMock = { backgroundColor: '#fff' }; + getAppearance.mockReturnValue( appearanceMock ); + getFingerprint.mockImplementation( () => { + return 'fingerprint'; + } ); + + mockDomElement.dataset.paymentMethodType = 'giropay'; + + await mountStripePaymentElement( + apiMock, + mockDomElement, + elementsLocation + ); + + expect( getAppearance ).toHaveBeenCalled(); + expect( apiMock.saveUPEAppearance ).toHaveBeenCalledWith( + appearanceMock, + elementsLocation + ); + expect( getUPEConfig ).toHaveBeenCalledWith( expectedProperty ); + expect( dispatchMock ).toHaveBeenCalled(); + } ); + + test( 'does not call getAppearance or saveUPEAppearance if appearance is already set', async () => { + const appearanceMock = { backgroundColor: '#fff' }; + getAppearance.mockReturnValue( appearanceMock ); + getFingerprint.mockImplementation( () => { + return 'fingerprint'; + } ); + getUPEConfig.mockImplementation( ( argument ) => { + if ( argument === 'currency' ) { + return 'eur'; + } + + if ( + argument === 'upeAppearance' || + argument === 'upeAddPaymentMethodAppearance' + ) { + return { + backgroundColor: '#fff', + }; + } + + if ( argument === 'paymentMethodsConfig' ) { + return { + giropay: { + label: 'Giropay', + forceNetworkSavedCards: false, + }, + }; + } + } ); + + mockDomElement.dataset.paymentMethodType = 'giropay'; + + await mountStripePaymentElement( + apiMock, + mockDomElement, + elementsLocation + ); + + expect( getUPEConfig ).toHaveBeenCalledWith( expectedProperty ); + expect( getAppearance ).not.toHaveBeenCalled(); + expect( apiMock.saveUPEAppearance ).not.toHaveBeenCalled(); + } ); } ); - - mockDomElement.dataset.paymentMethodType = 'giropay'; - - await mountStripePaymentElement( apiMock, mockDomElement ); - - expect( getAppearance ).not.toHaveBeenCalled(); - expect( apiMock.saveUPEAppearance ).not.toHaveBeenCalled(); } ); test( 'Prevents from mounting when no figerprint is available', async () => { diff --git a/client/checkout/upe-styles/index.js b/client/checkout/upe-styles/index.js index 255feaa3f55..5fb0806e99c 100644 --- a/client/checkout/upe-styles/index.js +++ b/client/checkout/upe-styles/index.js @@ -11,7 +11,7 @@ import { getBackgroundColor, } from './utils.js'; -const appearanceSelectors = { +export const appearanceSelectors = { default: { hiddenContainer: '#wcpay-hidden-div', hiddenInput: '#wcpay-hidden-input', @@ -148,7 +148,7 @@ const appearanceSelectors = { case 'blocks_checkout': appearanceSelector = this.blocksCheckout; break; - case 'classic_checkout': + case 'shortcode_checkout': appearanceSelector = this.classicCheckout; break; case 'bnpl_product_page': diff --git a/client/checkout/upe-styles/test/index.js b/client/checkout/upe-styles/test/index.js index 099da8a4a33..0d9c70f64c8 100644 --- a/client/checkout/upe-styles/test/index.js +++ b/client/checkout/upe-styles/test/index.js @@ -199,4 +199,57 @@ describe( 'Getting styles for automated theming', () => { }, } ); } ); + + [ + { + elementsLocation: 'shortcode_checkout', + expectedSelectors: [ + upeStyles.appearanceSelectors.classicCheckout + .upeThemeInputSelector, + upeStyles.appearanceSelectors.classicCheckout + .upeThemeLabelSelector, + ], + }, + { + elementsLocation: 'blocks_checkout', + expectedSelectors: [ + upeStyles.appearanceSelectors.blocksCheckout + .upeThemeInputSelector, + upeStyles.appearanceSelectors.blocksCheckout + .upeThemeLabelSelector, + ], + }, + { + elementsLocation: 'other', + expectedSelectors: [ + upeStyles.appearanceSelectors.blocksCheckout + .upeThemeInputSelector, + upeStyles.appearanceSelectors.blocksCheckout + .upeThemeLabelSelector, + ], + }, + ].forEach( ( { elementsLocation, expectedSelectors } ) => { + afterEach( () => { + document.querySelector.mockClear(); + } ); + + describe( `when elementsLocation is ${ elementsLocation }`, () => { + test( 'getAppearance uses the correct appearanceSelectors based on the elementsLocation', () => { + jest.spyOn( document, 'querySelector' ).mockImplementation( + () => mockElement + ); + jest.spyOn( window, 'getComputedStyle' ).mockImplementation( + () => mockCSStyleDeclaration + ); + + upeStyles.getAppearance( elementsLocation ); + + expectedSelectors.forEach( ( selector ) => { + expect( document.querySelector ).toHaveBeenCalledWith( + selector + ); + } ); + } ); + } ); + } ); } ); diff --git a/includes/class-wc-payment-gateway-wcpay.php b/includes/class-wc-payment-gateway-wcpay.php index bd3c9ab913d..0fe8b9c4dad 100644 --- a/includes/class-wc-payment-gateway-wcpay.php +++ b/includes/class-wc-payment-gateway-wcpay.php @@ -115,17 +115,19 @@ class WC_Payment_Gateway_WCPay extends WC_Payment_Gateway_CC { const USER_FORMATTED_TOKENS_LIMIT = 100; - const PROCESS_REDIRECT_ORDER_MISMATCH_ERROR_CODE = 'upe_process_redirect_order_id_mismatched'; - const UPE_APPEARANCE_TRANSIENT = 'wcpay_upe_appearance'; - const WC_BLOCKS_UPE_APPEARANCE_TRANSIENT = 'wcpay_wc_blocks_upe_appearance'; - const UPE_BNPL_PRODUCT_PAGE_APPEARANCE_TRANSIENT = 'wcpay_upe_bnpl_product_page_appearance'; - const UPE_BNPL_CLASSIC_CART_APPEARANCE_TRANSIENT = 'wcpay_upe_bnpl_classic_cart_appearance'; - const UPE_BNPL_CART_BLOCK_APPEARANCE_TRANSIENT = 'wcpay_upe_bnpl_cart_block_appearance'; - const UPE_APPEARANCE_THEME_TRANSIENT = 'wcpay_upe_appearance_theme'; - const WC_BLOCKS_UPE_APPEARANCE_THEME_TRANSIENT = 'wcpay_wc_blocks_upe_appearance_theme'; - const UPE_BNPL_PRODUCT_PAGE_APPEARANCE_THEME_TRANSIENT = 'wcpay_upe_bnpl_product_page_appearance_theme'; - const UPE_BNPL_CLASSIC_CART_APPEARANCE_THEME_TRANSIENT = 'wcpay_upe_bnpl_classic_cart_appearance_theme'; - const UPE_BNPL_CART_BLOCK_APPEARANCE_THEME_TRANSIENT = 'wcpay_upe_bnpl_cart_block_appearance_theme'; + const PROCESS_REDIRECT_ORDER_MISMATCH_ERROR_CODE = 'upe_process_redirect_order_id_mismatched'; + const UPE_APPEARANCE_TRANSIENT = 'wcpay_upe_appearance'; + const UPE_ADD_PAYMENT_METHOD_APPEARANCE_TRANSIENT = 'wcpay_upe_add_payment_method_appearance'; + const WC_BLOCKS_UPE_APPEARANCE_TRANSIENT = 'wcpay_wc_blocks_upe_appearance'; + const UPE_BNPL_PRODUCT_PAGE_APPEARANCE_TRANSIENT = 'wcpay_upe_bnpl_product_page_appearance'; + const UPE_BNPL_CLASSIC_CART_APPEARANCE_TRANSIENT = 'wcpay_upe_bnpl_classic_cart_appearance'; + const UPE_BNPL_CART_BLOCK_APPEARANCE_TRANSIENT = 'wcpay_upe_bnpl_cart_block_appearance'; + const UPE_APPEARANCE_THEME_TRANSIENT = 'wcpay_upe_appearance_theme'; + const UPE_ADD_PAYMENT_METHOD_APPEARANCE_THEME_TRANSIENT = 'wcpay_upe_add_payment_method_appearance_theme'; + const WC_BLOCKS_UPE_APPEARANCE_THEME_TRANSIENT = 'wcpay_wc_blocks_upe_appearance_theme'; + const UPE_BNPL_PRODUCT_PAGE_APPEARANCE_THEME_TRANSIENT = 'wcpay_upe_bnpl_product_page_appearance_theme'; + const UPE_BNPL_CLASSIC_CART_APPEARANCE_THEME_TRANSIENT = 'wcpay_upe_bnpl_classic_cart_appearance_theme'; + const UPE_BNPL_CART_BLOCK_APPEARANCE_THEME_TRANSIENT = 'wcpay_upe_bnpl_cart_block_appearance_theme'; /** * The locations of appearance transients. @@ -4037,7 +4039,7 @@ public function save_upe_appearance_ajax() { $elements_location = isset( $_POST['elements_location'] ) ? wc_clean( wp_unslash( $_POST['elements_location'] ) ) : null; $appearance = isset( $_POST['appearance'] ) ? json_decode( wc_clean( wp_unslash( $_POST['appearance'] ) ) ) : null; - $valid_locations = [ 'blocks_checkout', 'shortcode_checkout', 'bnpl_product_page', 'bnpl_classic_cart', 'bnpl_cart_block' ]; + $valid_locations = [ 'blocks_checkout', 'shortcode_checkout', 'bnpl_product_page', 'bnpl_classic_cart', 'bnpl_cart_block', 'add_payment_method' ]; if ( ! $elements_location || ! in_array( $elements_location, $valid_locations, true ) ) { throw new Exception( __( 'Unable to update UPE appearance values at this time.', 'woocommerce-payments' ) @@ -4059,7 +4061,7 @@ public function save_upe_appearance_ajax() { /** * This filter is only called on "save" of the appearance, to avoid calling it on every page load. * If you apply changes through this filter, you'll need to clear the transient data to see them at checkout. - * $elements_location can be 'blocks_checkout', 'shortcode_checkout', 'bnpl_product_page', 'bnpl_classic_cart', 'bnpl_cart_block'. + * $elements_location can be 'blocks_checkout', 'shortcode_checkout', 'bnpl_product_page', 'bnpl_classic_cart', 'bnpl_cart_block', 'add_payment_method'. * * @since 7.4.0 */ @@ -4067,6 +4069,7 @@ public function save_upe_appearance_ajax() { $appearance_transient = [ 'shortcode_checkout' => self::UPE_APPEARANCE_TRANSIENT, + 'add_payment_method' => self::UPE_ADD_PAYMENT_METHOD_APPEARANCE_TRANSIENT, 'blocks_checkout' => self::WC_BLOCKS_UPE_APPEARANCE_TRANSIENT, 'bnpl_product_page' => self::UPE_BNPL_PRODUCT_PAGE_APPEARANCE_TRANSIENT, 'bnpl_classic_cart' => self::UPE_BNPL_CLASSIC_CART_APPEARANCE_TRANSIENT, @@ -4074,6 +4077,7 @@ public function save_upe_appearance_ajax() { ][ $elements_location ]; $appearance_theme_transient = [ 'shortcode_checkout' => self::UPE_APPEARANCE_THEME_TRANSIENT, + 'add_payment_method' => self::UPE_ADD_PAYMENT_METHOD_APPEARANCE_THEME_TRANSIENT, 'blocks_checkout' => self::WC_BLOCKS_UPE_APPEARANCE_THEME_TRANSIENT, 'bnpl_product_page' => self::UPE_BNPL_PRODUCT_PAGE_APPEARANCE_THEME_TRANSIENT, 'bnpl_classic_cart' => self::UPE_BNPL_CLASSIC_CART_APPEARANCE_THEME_TRANSIENT, diff --git a/includes/class-wc-payments-checkout.php b/includes/class-wc-payments-checkout.php index 2486cec98df..ea391c8fbdd 100644 --- a/includes/class-wc-payments-checkout.php +++ b/includes/class-wc-payments-checkout.php @@ -217,23 +217,25 @@ public function get_payment_fields_js_config() { */ $payment_fields = apply_filters( 'wcpay_payment_fields_js_config', $js_config ); - $payment_fields['accountDescriptor'] = $this->gateway->get_account_statement_descriptor(); - $payment_fields['addPaymentReturnURL'] = wc_get_account_endpoint_url( 'payment-methods' ); - $payment_fields['gatewayId'] = WC_Payment_Gateway_WCPay::GATEWAY_ID; - $payment_fields['isCheckout'] = is_checkout(); - $payment_fields['paymentMethodsConfig'] = $this->get_enabled_payment_method_config(); - $payment_fields['testMode'] = WC_Payments::mode()->is_test(); - $payment_fields['upeAppearance'] = get_transient( WC_Payment_Gateway_WCPay::UPE_APPEARANCE_TRANSIENT ); - $payment_fields['upeBnplProductPageAppearance'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_PRODUCT_PAGE_APPEARANCE_TRANSIENT ); - $payment_fields['upeBnplProductPageAppearanceTheme'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_PRODUCT_PAGE_APPEARANCE_THEME_TRANSIENT ); - $payment_fields['upeBnplClassicCartAppearance'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_CLASSIC_CART_APPEARANCE_TRANSIENT ); - $payment_fields['upeBnplClassicCartAppearanceTheme'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_CLASSIC_CART_APPEARANCE_THEME_TRANSIENT ); - $payment_fields['upeBnplCartBlockAppearance'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_CART_BLOCK_APPEARANCE_TRANSIENT ); - $payment_fields['upeBnplCartBlockAppearanceTheme'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_CART_BLOCK_APPEARANCE_THEME_TRANSIENT ); - $payment_fields['wcBlocksUPEAppearance'] = get_transient( WC_Payment_Gateway_WCPay::WC_BLOCKS_UPE_APPEARANCE_TRANSIENT ); - $payment_fields['wcBlocksUPEAppearanceTheme'] = get_transient( WC_Payment_Gateway_WCPay::WC_BLOCKS_UPE_APPEARANCE_THEME_TRANSIENT ); - $payment_fields['cartContainsSubscription'] = $this->gateway->is_subscription_item_in_cart(); - $payment_fields['currency'] = get_woocommerce_currency(); + $payment_fields['accountDescriptor'] = $this->gateway->get_account_statement_descriptor(); + $payment_fields['addPaymentReturnURL'] = wc_get_account_endpoint_url( 'payment-methods' ); + $payment_fields['gatewayId'] = WC_Payment_Gateway_WCPay::GATEWAY_ID; + $payment_fields['isCheckout'] = is_checkout(); + $payment_fields['paymentMethodsConfig'] = $this->get_enabled_payment_method_config(); + $payment_fields['testMode'] = WC_Payments::mode()->is_test(); + $payment_fields['upeAppearance'] = get_transient( WC_Payment_Gateway_WCPay::UPE_APPEARANCE_TRANSIENT ); + $payment_fields['upeAddPaymentMethodAppearance'] = get_transient( WC_Payment_Gateway_WCPay::UPE_ADD_PAYMENT_METHOD_APPEARANCE_TRANSIENT ); + $payment_fields['upeAddPaymentMethodAppearanceTheme'] = get_transient( WC_Payment_Gateway_WCPay::UPE_ADD_PAYMENT_METHOD_APPEARANCE_THEME_TRANSIENT ); + $payment_fields['upeBnplProductPageAppearance'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_PRODUCT_PAGE_APPEARANCE_TRANSIENT ); + $payment_fields['upeBnplProductPageAppearanceTheme'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_PRODUCT_PAGE_APPEARANCE_THEME_TRANSIENT ); + $payment_fields['upeBnplClassicCartAppearance'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_CLASSIC_CART_APPEARANCE_TRANSIENT ); + $payment_fields['upeBnplClassicCartAppearanceTheme'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_CLASSIC_CART_APPEARANCE_THEME_TRANSIENT ); + $payment_fields['upeBnplCartBlockAppearance'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_CART_BLOCK_APPEARANCE_TRANSIENT ); + $payment_fields['upeBnplCartBlockAppearanceTheme'] = get_transient( WC_Payment_Gateway_WCPay::UPE_BNPL_CART_BLOCK_APPEARANCE_THEME_TRANSIENT ); + $payment_fields['wcBlocksUPEAppearance'] = get_transient( WC_Payment_Gateway_WCPay::WC_BLOCKS_UPE_APPEARANCE_TRANSIENT ); + $payment_fields['wcBlocksUPEAppearanceTheme'] = get_transient( WC_Payment_Gateway_WCPay::WC_BLOCKS_UPE_APPEARANCE_THEME_TRANSIENT ); + $payment_fields['cartContainsSubscription'] = $this->gateway->is_subscription_item_in_cart(); + $payment_fields['currency'] = get_woocommerce_currency(); $cart_total = ( WC()->cart ? WC()->cart->get_total( '' ) : 0 ); $payment_fields['cartTotal'] = WC_Payments_Utils::prepare_amount( $cart_total, get_woocommerce_currency() ); diff --git a/tests/unit/test-class-wc-payments-checkout.php b/tests/unit/test-class-wc-payments-checkout.php index e0c8b54dc16..34175b8dc70 100644 --- a/tests/unit/test-class-wc-payments-checkout.php +++ b/tests/unit/test-class-wc-payments-checkout.php @@ -510,4 +510,30 @@ public function test_save_option_for_reusable_payment_payment() { ); $this->assertSame( true, $this->system_under_test->get_payment_fields_js_config()['paymentMethodsConfig'][ Payment_Method::CARD ]['showSaveOption'] ); } + + public function test_upe_appearance_transients() { + $this->mock_wcpay_gateway + ->expects( $this->any() ) + ->method( 'get_payment_method_ids_enabled_at_checkout' ) + ->willReturn( + [ + Payment_Method::CARD, + ] + ); + $this->mock_wcpay_gateway + ->method( 'wc_payments_get_payment_method_by_id' ) + ->willReturn( + new CC_Payment_Method( $this->mock_token_service ) + ); + + set_transient( WC_Payment_Gateway_WCPay::UPE_APPEARANCE_TRANSIENT, '{}', DAY_IN_SECONDS ); + set_transient( WC_Payment_Gateway_WCPay::WC_BLOCKS_UPE_APPEARANCE_THEME_TRANSIENT, 'night', DAY_IN_SECONDS ); + delete_transient( WC_Payment_Gateway_WCPay::UPE_ADD_PAYMENT_METHOD_APPEARANCE_TRANSIENT ); + + $js_config = $this->system_under_test->get_payment_fields_js_config(); + + $this->assertSame( '{}', $js_config['upeAppearance'] ); + $this->assertSame( 'night', $js_config['wcBlocksUPEAppearanceTheme'] ); + $this->assertFalse( $js_config['upeAddPaymentMethodAppearance'] ); + } }