diff --git a/changelog/dev-9961-convert-merchant-orders-full-refund-spec b/changelog/dev-9961-convert-merchant-orders-full-refund-spec new file mode 100644 index 00000000000..4a215882ff2 --- /dev/null +++ b/changelog/dev-9961-convert-merchant-orders-full-refund-spec @@ -0,0 +1,5 @@ +Significance: patch +Type: dev +Comment: Convert merchant-orders-full-refund spec from Puppeteer to Playwright + + diff --git a/tests/e2e-pw/specs/merchant/merchant-orders-full-refund.spec.ts b/tests/e2e-pw/specs/merchant/merchant-orders-full-refund.spec.ts new file mode 100644 index 00000000000..8ea26d1dd3f --- /dev/null +++ b/tests/e2e-pw/specs/merchant/merchant-orders-full-refund.spec.ts @@ -0,0 +1,119 @@ +/** + * External dependencies + */ +import { test, expect, Page } from '@playwright/test'; + +/** + * Internal dependencies + */ +import { getMerchant, getShopper } from '../../utils/helpers'; +import { + deactivateMulticurrency, + isMulticurrencyEnabled, +} from '../../utils/merchant'; +import * as shopper from '../../utils/shopper'; +import { goToOrder, goToPaymentDetails } from '../../utils/merchant-navigation'; + +test.describe( 'WooCommerce Payments - Full Refund', () => { + let merchantPage: Page; + let shopperPage: Page; + let orderId: string; + let orderAmount: string; + + test.beforeAll( async ( { browser } ) => { + merchantPage = ( await getMerchant( browser ) ).merchantPage; + shopperPage = ( await getShopper( browser ) ).shopperPage; + + // Disable multi-currency in the merchant settings. This step is important because local environment setups + // might have multi-currency enabled. We need to ensure a consistent environment for the test. + if ( await isMulticurrencyEnabled( merchantPage ) ) { + await deactivateMulticurrency( merchantPage ); + } + } ); + + test( 'should process a full refund for an order', async () => { + // Place an order to refund later and get the order ID so we can open it in the merchant view + orderId = await shopper.placeOrderWithCurrency( shopperPage, 'USD' ); + + // Get the order total so we can verify the refund amount + orderAmount = await shopperPage + .locator( + '.woocommerce-order-overview__total .woocommerce-Price-amount' + ) + .textContent(); + + // Open the order + await goToOrder( merchantPage, orderId ); + + // Click refund button + await merchantPage + .getByRole( 'button', { + name: 'Refund', + } ) + .click(); + + // Fill refund details + await merchantPage.getByLabel( 'Refund amount' ).fill( orderAmount ); + // await merchantPage.fill( '.refund_line_total', orderAmount ); + await merchantPage + .getByLabel( 'Reason for refund' ) + .fill( 'No longer wanted' ); + + const refundButton = await merchantPage.getByRole( 'button', { + name: `Refund ${ orderAmount } via WooPayments`, + } ); + + await expect( refundButton ).toBeVisible(); + + // TODO: This visual regression test is not flaky, but we should revisit the approach. + // await expect( merchantPage ).toHaveScreenshot(); + + // Click refund and handle confirmation dialog + merchantPage.on( 'dialog', ( dialog ) => dialog.accept() ); + await refundButton.click(); + + // Wait for refund to process + await merchantPage.waitForLoadState( 'networkidle' ); + + // Verify refund details + await expect( + merchantPage.getByRole( 'cell', { + name: `-${ orderAmount }`, + } ) + ).toHaveCount( 2 ); + await expect( + merchantPage.getByText( + `A refund of ${ orderAmount } was successfully processed using WooPayments. Reason: No longer wanted` + ) + ).toBeVisible(); + + // TODO: This visual regression test is not flaky, but we should revisit the approach. + // await expect( merchantPage ).toHaveScreenshot(); + } ); + + test( 'should be able to view a refunded transaction', async () => { + // Get and navigate to payment details + const paymentIntentId = await merchantPage + .locator( '#order_data' ) + .getByRole( 'link', { + name: /pi_/, + } ) + .innerText(); + + await goToPaymentDetails( merchantPage, paymentIntentId ); + + // Verify timeline events + await expect( + merchantPage.getByText( + `A payment of ${ orderAmount } was successfully refunded.` + ) + ).toBeVisible(); + + await expect( + merchantPage.getByText( 'Payment status changed to Refunded.' ) + ).toBeVisible(); + + // TODO: This visual regression test is not flaky, but we should revisit the approach. + // await expect( merchantPage ).toHaveScreenshot(); + } ); +} ); diff --git a/tests/e2e/specs/wcpay/merchant/merchant-orders-full-refund.spec.js b/tests/e2e/specs/wcpay/merchant/merchant-orders-full-refund.spec.js deleted file mode 100644 index ea303a43b88..00000000000 --- a/tests/e2e/specs/wcpay/merchant/merchant-orders-full-refund.spec.js +++ /dev/null @@ -1,135 +0,0 @@ -/** - * External dependencies - */ -import config from 'config'; - -const { merchant, shopper } = require( '@woocommerce/e2e-utils' ); - -/** - * Internal dependencies - */ -import { merchantWCP, takeScreenshot } from '../../../utils'; -import { fillCardDetails, setupProductCheckout } from '../../../utils/payments'; - -let orderId; -let orderAmount; - -describe( 'Order > Full refund', () => { - beforeAll( async () => { - // Disable multi-currency in the merchant settings. This step is important because local environment setups - // might have multi-currency enabled. We need to ensure a consistent - // environment for the test. - await merchant.login(); - await merchantWCP.deactivateMulticurrency(); - await merchant.logout(); - - await shopper.login(); - // Place an order to refund later - await setupProductCheckout( - config.get( 'addresses.customer.billing' ) - ); - const card = config.get( 'cards.basic' ); - await fillCardDetails( page, card ); - await shopper.placeOrder(); - await expect( page ).toMatchTextContent( 'Order received' ); - - // Get the order ID so we can open it in the merchant view - const ORDER_RECEIVED_ID_SELECTOR = - '.woocommerce-order-overview__order.order > strong'; - const orderIdField = await page.$( ORDER_RECEIVED_ID_SELECTOR ); - orderId = await orderIdField.evaluate( ( el ) => el.innerText ); - - // Get the order total so we can verify the refund amount - const ORDER_RECEIVED_AMOUNT_SELECTOR = - '.woocommerce-order-overview__total .woocommerce-Price-amount'; - const orderTotalField = await page.$( ORDER_RECEIVED_AMOUNT_SELECTOR ); - orderAmount = await orderTotalField.evaluate( ( el ) => el.innerText ); - - // Login and open the order - await merchant.login(); - await merchant.goToOrder( orderId ); - - // We need to remove any listeners on the `dialog` event otherwise we can't catch the dialog below - await page.removeAllListeners( 'dialog' ); - } ); - - afterAll( async () => { - page.removeAllListeners( 'dialog' ); - page.on( 'dialog', async function ( dialog ) { - try { - await dialog.accept(); - } catch ( err ) {} - } ); - await merchant.logout(); - } ); - - it( 'should process a full refund for an order', async () => { - // Click the Refund button - await expect( page ).toClick( 'button.refund-items' ); - - // Verify the refund section shows - await page.waitForSelector( 'div.wc-order-refund-items', { - visible: true, - } ); - - // Verify Refund via WooPayments button is displayed - await page.waitForSelector( 'button.do-api-refund' ); - - // Initiate a refund - await expect( page ).toFill( '.refund_line_total', orderAmount ); - await expect( page ).toFill( '#refund_reason', 'No longer wanted' ); - - await expect( page ).toMatchElement( '.do-api-refund', { - text: `Refund ${ orderAmount } via WooPayments`, - } ); - await takeScreenshot( 'merchant-orders-full-refund_refunding' ); - - const refundDialog = await expect( page ).toDisplayDialog( async () => { - await expect( page ).toClick( 'button.do-api-refund' ); - } ); - - // Accept the refund - await refundDialog.accept(); - - await page.waitForNavigation( { waitUntil: 'networkidle0' } ); - - await Promise.all( [ - // Verify the product line item shows the refunded amount - expect( page ).toMatchElement( '.line_cost .refunded', { - text: `-${ orderAmount }`, - } ), - - // Verify the refund shows in the list with the amount - expect( page ).toMatchElement( '.refund > .line_cost', { - text: `-${ orderAmount }`, - } ), - - // Verify system note was added - expect( page ).toMatchElement( '.system-note', { - text: `A refund of ${ orderAmount } was successfully processed using WooPayments. Reason: No longer wanted`, - } ), - ] ); - await takeScreenshot( 'merchant-orders-full-refund_refunded' ); - } ); - - it( 'should be able to view a refunded transaction', async () => { - // Pull out and follow the link to avoid working in multiple tabs - const paymentDetailsLink = await page.$eval( - 'p.order_number > a', - ( anchor ) => anchor.getAttribute( 'href' ) - ); - - await merchantWCP.openPaymentDetails( paymentDetailsLink ); - await takeScreenshot( 'merchant-orders-full-refund_payment-details' ); - - // Verify the transaction timeline reflects the refund events - await Promise.all( [ - expect( page ).toMatchElement( 'li.woocommerce-timeline-item', { - text: `A payment of ${ orderAmount } was successfully refunded.`, - } ), - expect( page ).toMatchElement( 'li.woocommerce-timeline-item', { - text: 'Payment status changed to Refunded.', - } ), - ] ); - } ); -} );