diff --git a/changelog/dev-10067-convert-shopper-multi-currency-widget-spec b/changelog/dev-10067-convert-shopper-multi-currency-widget-spec new file mode 100644 index 00000000000..e4f0e6ac9ae --- /dev/null +++ b/changelog/dev-10067-convert-shopper-multi-currency-widget-spec @@ -0,0 +1,4 @@ +Significance: patch +Type: dev + +Convert shopper-multi-currency-widget spec from Puppeteer to Playwright diff --git a/tests/e2e-pw/specs/shopper/multi-currency-checkout.spec.ts b/tests/e2e-pw/specs/shopper/multi-currency-checkout.spec.ts index fa5453b70e4..a174ab1bcf7 100644 --- a/tests/e2e-pw/specs/shopper/multi-currency-checkout.spec.ts +++ b/tests/e2e-pw/specs/shopper/multi-currency-checkout.spec.ts @@ -10,7 +10,7 @@ import { activateMulticurrency, addCurrency, deactivateMulticurrency, - removeCurrency, + restoreCurrencies, } from '../../utils/merchant'; import { emptyCart, placeOrderWithCurrency } from '../../utils/shopper'; import * as navigation from '../../utils/shopper-navigation'; @@ -33,7 +33,7 @@ test.describe( 'Multi-currency checkout', () => { } ); test.afterAll( async () => { - await removeCurrency( merchantPage, 'EUR' ); + await restoreCurrencies( merchantPage ); await emptyCart( shopperPage ); if ( ! wasMulticurrencyEnabled ) { diff --git a/tests/e2e-pw/specs/shopper/shopper-bnpls-checkout.spec.ts b/tests/e2e-pw/specs/shopper/shopper-bnpls-checkout.spec.ts index cf8630c6ca2..569093b959a 100644 --- a/tests/e2e-pw/specs/shopper/shopper-bnpls-checkout.spec.ts +++ b/tests/e2e-pw/specs/shopper/shopper-bnpls-checkout.spec.ts @@ -18,16 +18,26 @@ const bnplProviders = [ 'Affirm', 'Afterpay' ]; test.describe( 'BNPL checkout', () => { let merchantPage: Page; let shopperPage: Page; + let wasMulticurrencyEnabled: boolean; test.beforeAll( async ( { browser } ) => { shopperPage = ( await getShopper( browser ) ).shopperPage; merchantPage = ( await getMerchant( browser ) ).merchantPage; + wasMulticurrencyEnabled = await merchant.isMulticurrencyEnabled( + merchantPage + ); await merchant.enablePaymentMethods( merchantPage, bnplProviders ); + if ( wasMulticurrencyEnabled ) { + await merchant.deactivateMulticurrency( merchantPage ); + } } ); test.afterAll( async () => { await merchant.disablePaymentMethods( merchantPage, bnplProviders ); + if ( wasMulticurrencyEnabled ) { + await merchant.activateMulticurrency( merchantPage ); + } } ); for ( const ctpEnabled of cardTestingProtectionStates ) { diff --git a/tests/e2e-pw/specs/shopper/shopper-multi-currency-widget.spec.ts b/tests/e2e-pw/specs/shopper/shopper-multi-currency-widget.spec.ts new file mode 100644 index 00000000000..d0185b3f828 --- /dev/null +++ b/tests/e2e-pw/specs/shopper/shopper-multi-currency-widget.spec.ts @@ -0,0 +1,126 @@ +/** + * External dependencies + */ +import { test, expect, Page } from '@playwright/test'; +/** + * Internal dependencies + */ +import * as merchant from '../../utils/merchant'; +import * as shopper from '../../utils/shopper'; +import * as navigation from '../../utils/shopper-navigation'; +import { goToOrder } from '../../utils/merchant-navigation'; +import RestAPI from '../../utils/rest-api'; +import { getMerchant, getShopper } from '../../utils/helpers'; + +test.describe( 'Shopper Multi-Currency widget', () => { + let merchantPage: Page; + let shopperPage: Page; + let wasMulticurrencyEnabled: boolean; + + test.beforeAll( async ( { browser } ) => { + shopperPage = ( await getShopper( browser ) ).shopperPage; + merchantPage = ( await getMerchant( browser ) ).merchantPage; + wasMulticurrencyEnabled = await merchant.activateMulticurrency( + merchantPage + ); + await merchant.restoreCurrencies( merchantPage ); + } ); + + test.afterAll( async () => { + if ( ! wasMulticurrencyEnabled ) { + await merchant.deactivateMulticurrency( merchantPage ); + } + } ); + + test( 'should display currency switcher widget if multi-currency is enabled', async () => { + await merchant.addMulticurrencyWidget( merchantPage ); + + await navigation.goToShop( shopperPage ); + await expect( + shopperPage.locator( '.widget select[name=currency]' ) + ).toBeVisible(); + } ); + + test( 'should not display currency switcher widget if multi-currency is disabled', async () => { + await merchant.deactivateMulticurrency( merchantPage ); + + await navigation.goToShop( shopperPage ); + await expect( + shopperPage.locator( '.widget select[name=currency]' ) + ).not.toBeVisible(); + + await merchant.activateMulticurrency( merchantPage ); + } ); + + test.describe( 'Should allow shopper to switch currency', () => { + test.afterEach( async () => { + await shopperPage.selectOption( + '.widget select[name=currency]', + 'EUR' + ); + await expect( shopperPage ).toHaveURL( /.*currency=EUR/ ); + + // Change it back to USD for the other tests. + await navigation.goToShopWithCurrency( shopperPage, 'USD' ); + } ); + + test( 'at the product page', async () => { + await navigation.goToProductPageBySlug( shopperPage, 'beanie' ); + } ); + + test( 'at the cart page', async () => { + await navigation.goToCart( shopperPage ); + } ); + + test( 'at the checkout page', async () => { + await navigation.goToCheckout( shopperPage ); + } ); + } ); + + test.describe( 'Should not affect prices', () => { + let orderId: string; + + test.afterEach( async () => { + await shopperPage.selectOption( + '.widget select[name=currency]', + 'EUR' + ); + + await expect( + shopperPage.getByText( '$18.00 USD' ).first() + ).toBeVisible(); + + await navigation.goToShopWithCurrency( shopperPage, 'USD' ); + } ); + + test( 'at the order received page', async () => { + orderId = await shopper.placeOrderWithCurrency( + shopperPage, + 'USD' + ); + } ); + + test( 'at My account > Orders', async () => { + await navigation.goToOrders( shopperPage ); + await expect( + shopperPage.getByLabel( `View order number ${ orderId }` ) + ).toBeVisible(); + } ); + } ); + + test( 'should not display currency switcher on pay for order page', async ( {}, { + project, + } ) => { + const restApi = new RestAPI( project.use.baseURL ); + const orderId = await restApi.createOrder(); + + await goToOrder( merchantPage, orderId ); + await merchantPage + .getByRole( 'link', { name: 'Customer payment page' } ) + .click(); + + await expect( + merchantPage.locator( '.widget select[name=currency]' ) + ).not.toBeVisible(); + } ); +} ); diff --git a/tests/e2e-pw/utils/merchant.ts b/tests/e2e-pw/utils/merchant.ts index 5a063dff60b..5dd2b866cf7 100644 --- a/tests/e2e-pw/utils/merchant.ts +++ b/tests/e2e-pw/utils/merchant.ts @@ -93,6 +93,7 @@ export const deactivateMulticurrency = async ( page: Page ) => { export const addMulticurrencyWidget = async ( page: Page ) => { await navigation.goToWidgets( page ); // Wait for all widgets to load. This is important to prevent flakiness. + await page.locator( '.components-spinner' ).first().waitFor(); await expect( page.locator( '.components-spinner' ) ).toHaveCount( 0 ); if ( await page.getByRole( 'button', { name: 'Close' } ).isVisible() ) { @@ -100,7 +101,8 @@ export const addMulticurrencyWidget = async ( page: Page ) => { } const isWidgetAdded = await page - .getByRole( 'heading', { name: 'Currency Switcher Widget' } ) + .locator( 'iframe[srcdoc*=currency]' ) + .first() .isVisible(); if ( ! isWidgetAdded ) { diff --git a/tests/e2e-pw/utils/rest-api.ts b/tests/e2e-pw/utils/rest-api.ts index 400262422d2..1cb1e1e6d48 100644 --- a/tests/e2e-pw/utils/rest-api.ts +++ b/tests/e2e-pw/utils/rest-api.ts @@ -9,6 +9,7 @@ import { HTTPClientFactory } from '@woocommerce/api'; import { config } from '../config/default'; const userEndpoint = '/wp/v2/users'; +const ordersEndpoint = '/wc/v3/orders'; class RestAPI { private baseUrl: string; @@ -63,6 +64,21 @@ class RestAPI { } } } + + async createOrder(): Promise< string > { + const client = this.getAdminClient(); + + const order = await client.post( ordersEndpoint, { + line_items: [ + { + product_id: 16, + quantity: 1, + }, + ], + } ); + + return `${ order.data.id }`; + } } export default RestAPI; diff --git a/tests/e2e/specs/wcpay/shopper/shopper-multi-currency-widget.spec.js b/tests/e2e/specs/wcpay/shopper/shopper-multi-currency-widget.spec.js deleted file mode 100644 index 7b8a7ea3cb0..00000000000 --- a/tests/e2e/specs/wcpay/shopper/shopper-multi-currency-widget.spec.js +++ /dev/null @@ -1,204 +0,0 @@ -/** - * External dependencies - */ -const { merchant, shopper } = require( '@woocommerce/e2e-utils' ); - -/** - * Internal dependencies - */ -import config from 'config'; -import { merchantWCP, shopperWCP } from '../../../utils'; -import { fillCardDetails, setupProductCheckout } from '../../../utils/payments'; - -const PAY_FOR_ORDER_LINK_SELECTOR = '.wc-order-status a'; -const pagesTable = [ - [ - 'home page', - async () => { - await shopper.goToShop(); - }, - 'shop', - ], - [ - 'product page', - async () => { - await page.click( 'li.product > a > img[src*="beanie"' ); - }, - 'product/beanie', - ], - [ - 'cart', - async () => { - await shopperWCP.addToCartBySlug( 'beanie' ); - await shopper.goToCart(); - }, - 'cart', - ], - [ - 'checkout', - async () => { - await setupProductCheckout( - config.get( 'addresses.customer.billing' ) - ); - }, - 'checkout', - ], -]; - -describe( 'Shopper Multi-Currency widget', () => { - let wasMulticurrencyEnabled; - - beforeAll( async () => { - await merchant.login(); - wasMulticurrencyEnabled = await merchantWCP.activateMulticurrency(); - await merchantWCP.addCurrency( 'EUR' ); - } ); - - afterAll( async () => { - if ( ! wasMulticurrencyEnabled ) { - await merchant.login(); - await merchantWCP.deactivateMulticurrency(); - } - await merchant.logout(); - } ); - - it( 'should display currency switcher widget if multi-currency is enabled', async () => { - await merchantWCP.addMulticurrencyWidget(); - await merchant.logout(); - await shopper.goToShop(); - await page.waitForSelector( '.widget select[name=currency]', { - visible: true, - timeout: 5000, - } ); - } ); - - it( 'should not display currency switcher widget if multi-currency is disabled', async () => { - await merchant.login(); - await merchantWCP.openWCPSettings(); - await merchantWCP.deactivateMulticurrency(); - await shopper.goToShop(); - - const currencySwitcher = await page.$( - '.widget select[name=currency]' - ); - expect( currencySwitcher ).toBeNull(); - - // Activate it again for the other tests. - await merchantWCP.activateMulticurrency(); - await merchant.logout(); - } ); - - describe.each( pagesTable )( - 'Should allow shopper to switch currency', - ( pageName, setupTest, url ) => { - it( `at the ${ pageName }`, async () => { - await setupTest(); - await page.waitForSelector( '.widget select[name=currency]', { - visible: true, - timeout: 5000, - } ); - await Promise.all( [ - page.select( '.widget select[name=currency]', 'EUR' ), - page.waitForNavigation( { waitUntil: 'networkidle0' } ), - ] ); - await expect( page.url() ).toContain( - `${ url }/?currency=EUR` - ); - await page.waitForSelector( - '.widget select[name=currency] option[value=EUR][selected]' - ); - // Change it back to USD for the other tests. - await Promise.all( [ - page.select( '.widget select[name=currency]', 'USD' ), - page.waitForNavigation( { waitUntil: 'networkidle0' } ), - ] ); - } ); - } - ); - - it( 'should not affect prices when currency switching on My account > Orders', async () => { - await shopper.login(); - await Promise.all( [ - page.select( '.widget select[name=currency]', 'USD' ), - page.waitForNavigation( { waitUntil: 'networkidle0' } ), - ] ); - await setupProductCheckout( - config.get( 'addresses.customer.billing' ) - ); - await fillCardDetails( page, config.get( 'cards.basic' ) ); - await shopper.placeOrder(); - await expect( page ).toMatchTextContent( 'Order received' ); - - const orderId = await page.evaluate( - () => document.querySelector( 'li.order strong' ).innerText - ); - const orderTotal = Number( - await page.evaluate( () => - document - .querySelector( 'li.total strong' ) - .innerText.replace( /[^\d.]/g, '' ) - ) - ); - - await shopperWCP.goToOrders(); - await Promise.all( [ - page.select( '.widget select[name=currency]', 'EUR' ), - page.waitForNavigation( { waitUntil: 'networkidle0' } ), - ] ); - await page.waitForSelector( - '.widget select[name=currency] option[value=EUR][selected]' - ); - await expect( page ).toMatchTextContent( `#${ orderId }` ); - await expect( page ).toMatchTextContent( - `${ orderTotal.toFixed( 2 ) } USD` - ); - } ); - - it( 'should not affect prices when currency switching at the order received page', async () => { - await page.select( '.widget select[name=currency]', 'USD' ); - await setupProductCheckout( - config.get( 'addresses.customer.billing' ) - ); - await fillCardDetails( page, config.get( 'cards.basic' ) ); - await shopper.placeOrder(); - await expect( page ).toMatchTextContent( 'Order received' ); - - const orderId = await page.evaluate( - () => document.querySelector( 'li.order strong' ).innerText - ); - const orderTotal = Number( - await page.evaluate( () => - document - .querySelector( 'li.total strong' ) - .innerText.replace( /[^\d.]/g, '' ) - ) - ); - - await Promise.all( [ - page.select( '.widget select[name=currency]', 'EUR' ), - page.waitForNavigation( { waitUntil: 'networkidle0' } ), - ] ); - await page.waitForSelector( - '.widget select[name=currency] option[value=EUR][selected]' - ); - await expect( page ).toMatchTextContent( `${ orderId }` ); - await expect( page ).toMatchTextContent( - `${ orderTotal.toFixed( 2 ) } USD` - ); - await page.select( '.widget select[name=currency]', 'USD' ); - await shopper.logout(); - } ); - - // Disabled due to issue on CI hard to reproduce locally, which is not worth investigating further as this test will be migrated soon. - it.skip( 'should not display currency switcher on pay for order page', async () => { - await merchant.login(); - await merchantWCP.createPayForOrder(); - await page.click( PAY_FOR_ORDER_LINK_SELECTOR ); - - const currencySwitcher = await page.$( - '.widget select[name=currency]' - ); - expect( currencySwitcher ).toBeNull(); - await merchant.logout(); - } ); -} );