Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into dev/10241-remove-p…
Browse files Browse the repository at this point in the history
…uppeteer-references
  • Loading branch information
eduardoumpierre committed Feb 12, 2025
2 parents 582d155 + 1916341 commit 2df669c
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 6 deletions.
4 changes: 4 additions & 0 deletions changelog/add-4606-e2e-for-currency-switch-at-checkout
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: add

Add E2E tests for currency switching at checkout.
4 changes: 4 additions & 0 deletions changelog/add-9129-account-management-component
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: add

Add the Stripe embedded account management component into the Payments → Settings page.
68 changes: 68 additions & 0 deletions client/settings/account-management/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* External dependencies
*/
import React, { useState } from 'react';
import { Card, CardBody } from '@wordpress/components';
import {
ConnectAccountManagement,
ConnectComponentsProvider,
} from '@stripe/react-connect-js';

/**
* Internal dependencies
*/
import StripeSpinner from 'wcpay/components/stripe-spinner';
import BannerNotice from 'wcpay/components/banner-notice';
import appearance from 'wcpay/utils/embedded-components/appearance';
import useAccountSession from 'wcpay/utils/embedded-components/account-session';
import './style.scss';

const AccountManagement = () => {
const [ loadErrorMessage, setLoadErrorMessage ] = useState( '' );
const [ loading, setLoading ] = useState( true );
const stripeConnectInstance = useAccountSession( {
setLoadErrorMessage,
appearance,
} );

return (
<>
<Card>
<CardBody>
{ loading && (
<div className="account-management-loader-wrapper">
<StripeSpinner />
</div>
) }
{ loadErrorMessage ? (
<BannerNotice status="error">
{ loadErrorMessage }
</BannerNotice>
) : (
stripeConnectInstance && (
<ConnectComponentsProvider
connectInstance={ stripeConnectInstance }
>
<ConnectAccountManagement
onLoaderStart={ () => setLoading( false ) }
onLoadError={ ( loadError ) =>
setLoadErrorMessage(
loadError.error.message ||
'Unknown error'
)
}
collectionOptions={ {
fields: 'eventually_due',
futureRequirements: 'include',
} }
/>
</ConnectComponentsProvider>
)
) }
</CardBody>
</Card>
</>
);
};

export default AccountManagement;
6 changes: 6 additions & 0 deletions client/settings/account-management/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Wrap loader so it's centered and does not get cut.
.account-management-loader-wrapper {
text-align: center;
height: 35px;
padding: 20px 0;
}
26 changes: 25 additions & 1 deletion client/settings/settings-manager/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import SettingsLayout from '../settings-layout';
import SaveSettingsSection from '../save-settings-section';
import Transactions from '../transactions';
import Deposits from '../deposits';
import AccountManagement from '../account-management';
import LoadableSettingsSection from '../loadable-settings-section';
import PaymentMethodsSection from '../payment-methods-section';
import BuyNowPayLaterSection from '../buy-now-pay-later-section';
Expand Down Expand Up @@ -102,6 +103,20 @@ const DepositsDescription = () => {
);
};

const AccountDetailsDescription = () => {
return (
<>
<h2>{ __( 'Account details', 'woocommerce-payments' ) }</h2>
<p>
{ __(
'View and edit your WooPayments account details like personal or business information and public information.',
'woocommerce-payments'
) }
</p>
</>
);
};

const FraudProtectionDescription = () => {
return (
<>
Expand Down Expand Up @@ -143,7 +158,6 @@ const SettingsManager = () => {
const [ isTransactionInputsValid, setTransactionInputsValid ] = useState(
true
);

const { isLoading } = useSettings();

useLayoutEffect( () => {
Expand Down Expand Up @@ -211,6 +225,16 @@ const SettingsManager = () => {
</LoadableSettingsSection>
</SettingsSection>
</DuplicatedPaymentMethodsContext.Provider>
<SettingsSection
description={ AccountDetailsDescription }
id="account-details"
>
<LoadableSettingsSection numLines={ 20 }>
<ErrorBoundary>
<AccountManagement />
</ErrorBoundary>
</LoadableSettingsSection>
</SettingsSection>
<SettingsSection
description={ TransactionsDescription }
id="transactions"
Expand Down
114 changes: 111 additions & 3 deletions tests/e2e/specs/wcpay/shopper/multi-currency-checkout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ import { test, expect, Page } from '@playwright/test';
/**
* Internal dependencies
*/
import { config } from '../../../config/default';
import { getMerchant, getShopper } from '../../../utils/helpers';
import {
activateMulticurrency,
addCurrency,
deactivateMulticurrency,
disablePaymentMethods,
enablePaymentMethods,
restoreCurrencies,
setDefaultCurrency,
} from '../../../utils/merchant';
import { emptyCart, placeOrderWithCurrency } from '../../../utils/shopper';
import { goToWooCommerceSettings } from '../../../utils/merchant-navigation';
import * as shopper from '../../../utils/shopper';
import * as navigation from '../../../utils/shopper-navigation';

test.describe( 'Multi-currency checkout', () => {
Expand All @@ -34,7 +39,7 @@ test.describe( 'Multi-currency checkout', () => {

test.afterAll( async () => {
await restoreCurrencies( merchantPage );
await emptyCart( shopperPage );
await shopper.emptyCart( shopperPage );

if ( ! wasMulticurrencyEnabled ) {
await deactivateMulticurrency( merchantPage );
Expand All @@ -45,7 +50,9 @@ test.describe( 'Multi-currency checkout', () => {
Object.keys( currenciesOrders ).forEach( ( currency: string ) => {
test( `checkout with ${ currency }`, async () => {
await test.step( `pay with ${ currency }`, async () => {
currenciesOrders[ currency ] = await placeOrderWithCurrency(
currenciesOrders[
currency
] = await shopper.placeOrderWithCurrency(
shopperPage,
currency
);
Expand Down Expand Up @@ -97,4 +104,105 @@ test.describe( 'Multi-currency checkout', () => {
}
} );
} );

test.describe( 'Available payment methods', () => {
let originalCurrency = 'USD';

test.beforeAll( async () => {
await goToWooCommerceSettings( merchantPage, 'general' );
originalCurrency = await merchantPage
.locator( '#woocommerce_currency' )
.inputValue();

await enablePaymentMethods( merchantPage, [ 'bancontact' ] );
} );

test.afterAll( async () => {
await disablePaymentMethods( merchantPage, [ 'bancontact' ] );
await setDefaultCurrency( merchantPage, originalCurrency );
} );

test.beforeEach( async () => {
await shopper.emptyCart( shopperPage );
} );

test( 'should display EUR payment methods when switching to EUR and default is USD', async () => {
await setDefaultCurrency( merchantPage, 'USD' );

// Shopper switch to USD.
await shopper.addToCartFromShopPage(
shopperPage,
config.products.simple,
'USD'
);
await navigation.goToCheckout( shopperPage );
await shopper.fillBillingAddress(
shopperPage,
config.addresses[ 'upe-customer' ].billing.be
);
await expect(
shopperPage.getByText( 'Bancontact' )
).not.toBeVisible();

// Shopper switch to EUR.
await navigation.goToCheckout( shopperPage, {
currency: 'EUR',
} );
await shopper.fillBillingAddress(
shopperPage,
config.addresses[ 'upe-customer' ].billing.be
);
await expect( shopperPage.getByText( 'Bancontact' ) ).toBeVisible();

// Shopper checkout with Bancontact.
await shopperPage.getByText( 'Bancontact' ).click();
await shopper.focusPlaceOrderButton( shopperPage );
await shopper.placeOrder( shopperPage );
await shopperPage
.getByRole( 'link', {
name: 'Authorize Test Payment',
} )
.click();
await expect(
shopperPage.getByText( 'Order received' ).first()
).toBeVisible();
} );

test( 'should display USD payment methods when switching to USD and default is EUR', async () => {
await setDefaultCurrency( merchantPage, 'EUR' );

// Shopper switch to EUR.
await shopper.addToCartFromShopPage(
shopperPage,
config.products.simple,
'EUR'
);
await navigation.goToCheckout( shopperPage );
await shopper.fillBillingAddress(
shopperPage,
config.addresses[ 'upe-customer' ].billing.be
);
await expect( shopperPage.getByText( 'Bancontact' ) ).toBeVisible();

// Shopper switch to USD.
await navigation.goToCheckout( shopperPage, {
currency: 'USD',
} );
await shopper.fillBillingAddress(
shopperPage,
config.addresses[ 'upe-customer' ].billing.be
);
await expect(
shopperPage.getByText( 'Bancontact' )
).not.toBeVisible();

// Shopper checkout with CC.
await shopper.fillCardDetails( shopperPage );
await shopper.focusPlaceOrderButton( shopperPage );
await shopper.placeOrder( shopperPage );
await expect(
shopperPage.getByText( 'Order received' ).first()
).toBeVisible();
} );
} );
} );
24 changes: 24 additions & 0 deletions tests/e2e/utils/merchant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,30 @@ export const removeCurrency = async ( page: Page, currencyCode: string ) => {
).toBeHidden();
};

export const setDefaultCurrency = async (
page: Page,
currencyCode: string
) => {
await navigation.goToWooCommerceSettings( page );

// Determine if the currency is already set as default.
const currentCurrencyCode = await page
.locator( '#woocommerce_currency' )
.inputValue();
if ( currentCurrencyCode === currencyCode ) {
return false;
}

// Set default currency.
await page.locator( '#woocommerce_currency' ).selectOption( currencyCode );
await page.getByRole( 'button', { name: 'Save changes' } ).click();
await expect(
page.getByText( 'Your settings have been saved.' )
).toBeVisible();

return true;
};

export const editCurrency = async ( page: Page, currencyCode: string ) => {
await navigation.goToMultiCurrencySettings( page );
await page
Expand Down
13 changes: 11 additions & 2 deletions tests/e2e/utils/shopper-navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,17 @@ export const goToCart = async ( page: Page ) => {
await isUIUnblocked( page );
};

export const goToCheckout = async ( page: Page ) => {
await page.goto( '/checkout/', { waitUntil: 'load' } );
export const goToCheckout = async (
page: Page,
{ currency }: { currency?: string } = {}
) => {
let url = '/checkout/';

if ( currency ) {
url += `?currency=${ currency }`;
}

await page.goto( url, { waitUntil: 'load' } );
await isUIUnblocked( page );
};

Expand Down

0 comments on commit 2df669c

Please sign in to comment.