diff --git a/tests/e2e/core-tests/CHANGELOG.md b/tests/e2e/core-tests/CHANGELOG.md index 2f535983a3f..1204b97fcdb 100644 --- a/tests/e2e/core-tests/CHANGELOG.md +++ b/tests/e2e/core-tests/CHANGELOG.md @@ -24,6 +24,7 @@ - Merchant Orders Customer Checkout Page - Shopper Cart Apply Coupon - Shopper Variable product info updates on different variations +- Merchant order emails flow ## Fixed diff --git a/tests/e2e/core-tests/README.md b/tests/e2e/core-tests/README.md index 38e0ed3f258..c9c5ec1788c 100644 --- a/tests/e2e/core-tests/README.md +++ b/tests/e2e/core-tests/README.md @@ -58,6 +58,7 @@ The functions to access the core tests are: - `runProductEditDetailsTest` - Merchant can edit an existing product - `runProductSearchTest` - Merchant can search for a product and view it - `runMerchantOrdersCustomerPaymentPage` - Merchant can visit the customer payment page + - `runMerchantOrderEmailsTest` - Merchant can receive order emails and resend emails by Order Actions ### Shopper diff --git a/tests/e2e/core-tests/specs/index.js b/tests/e2e/core-tests/specs/index.js index 984a52f2dd6..2a59fed2696 100644 --- a/tests/e2e/core-tests/specs/index.js +++ b/tests/e2e/core-tests/specs/index.js @@ -32,6 +32,7 @@ const runOrderApplyCouponTest = require( './merchant/wp-admin-order-apply-coupon const runProductEditDetailsTest = require( './merchant/wp-admin-product-edit-details.test' ); const runProductSearchTest = require( './merchant/wp-admin-product-search.test' ); const runMerchantOrdersCustomerPaymentPage = require( './merchant/wp-admin-order-customer-payment-page.test' ); +const runMerchantOrderEmailsTest = require( './merchant/wp-admin-order-emails.test' ); // REST API tests const runExternalProductAPITest = require( './api/external-product.test' ); @@ -112,6 +113,7 @@ module.exports = { runProductEditDetailsTest, runProductSearchTest, runMerchantOrdersCustomerPaymentPage, + runMerchantOrderEmailsTest, runMerchantTests, runProductBrowseSearchSortTest, runApiTests, diff --git a/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js b/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js new file mode 100644 index 00000000000..ad18a8de6d1 --- /dev/null +++ b/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js @@ -0,0 +1,73 @@ +/* eslint-disable jest/no-export, jest/no-disabled-tests, jest/no-standalone-expect */ +/** + * Internal dependencies + */ +const { + merchant, + clickUpdateOrder, + createSimpleOrder, + selectOrderAction, + deleteAllEmailLogs, +} = require( '@woocommerce/e2e-utils' ); + +const config = require( 'config' ); +const simpleProductName = config.get( 'products.simple.name' ); +const customerEmail = config.get( 'addresses.customer.billing.email' ); +const adminEmail = 'admin@woocommercecoree2etestsuite.com'; +const storeName = 'WooCommerce Core E2E Test Suite'; + +let orderId; + +const runMerchantOrderEmailsTest = () => { + + describe('Merchant > Order Action emails received', () => { + beforeAll( async () => { + await merchant.login(); + + // Clear out the existing email logs if any + await deleteAllEmailLogs(); + + orderId = await createSimpleOrder( 'Processing' ); + + await Promise.all( [ + // Select the billing email address field and add the customer billing email from the config + await page.click( 'div.order_data_column:nth-child(2) > h3:nth-child(1) > a:nth-child(1)' ), + await expect( page ).toFill( '#_billing_email', customerEmail ), + await clickUpdateOrder( 'Order updated.' ), + ] ); + } ); + + afterEach( async () => { + // Clear out any emails after each test + await deleteAllEmailLogs(); + } ); + + // New order emails are sent automatically when we create the simple order above, so let's verify we get these emails + it('can receive new order email', async () => { + await merchant.openEmailLog(); + await expect( page ).toMatchElement( '.column-receiver', { text: adminEmail } ); + await expect( page ).toMatchElement( '.column-subject', { text: `[${storeName}]: New order #${orderId}` } ); + } ); + + it('can resend new order notification', async () => { + await merchant.goToOrder( orderId ); + await selectOrderAction( 'send_order_details_admin' ); + + await merchant.openEmailLog(); + await expect( page ).toMatchElement( '.column-receiver', { text: adminEmail } ); + await expect( page ).toMatchElement( '.column-subject', { text: `[${storeName}]: New order #${orderId}` } ); + } ); + + it('can email invoice/order details to customer', async () => { + await merchant.goToOrder( orderId ); + await selectOrderAction( 'send_order_details' ); + + await merchant.openEmailLog(); + await expect( page ).toMatchElement( '.column-receiver', { text: customerEmail } ); + await expect( page ).toMatchElement( '.column-subject', { text: `Invoice for order #${orderId} on ${storeName}` } ); + } ); + + } ); +} + +module.exports = runMerchantOrderEmailsTest; diff --git a/tests/e2e/docker/initialize.sh b/tests/e2e/docker/initialize.sh index c5cbea47181..0a9592f5379 100755 --- a/tests/e2e/docker/initialize.sh +++ b/tests/e2e/docker/initialize.sh @@ -8,3 +8,6 @@ wp user create customer customer@woocommercecoree2etestsuite.com --user_pass=pas # we cannot create API keys for the API, so we using basic auth, this plugin allows that. wp plugin install https://github.com/WP-API/Basic-Auth/archive/master.zip --activate + +# install the WP Mail Logging plugin to test emails +wp plugin install wp-mail-logging --activate diff --git a/tests/e2e/env/CHANGELOG.md b/tests/e2e/env/CHANGELOG.md index 94be2bfd1f8..8e6272ba44b 100644 --- a/tests/e2e/env/CHANGELOG.md +++ b/tests/e2e/env/CHANGELOG.md @@ -11,6 +11,7 @@ - support for custom container name - Insert a 12 hour delay in using new docker image tags - Package `bin` script `wc-e2e` +- WP Mail Log plugin as part of container initialization ## Fixed diff --git a/tests/e2e/specs/wp-admin/order-emails.test.js b/tests/e2e/specs/wp-admin/order-emails.test.js new file mode 100644 index 00000000000..e0597074bda --- /dev/null +++ b/tests/e2e/specs/wp-admin/order-emails.test.js @@ -0,0 +1,6 @@ +/* + * Internal dependencies + */ +const { runMerchantOrderEmailsTest } = require( '@woocommerce/e2e-core-tests' ); + +runMerchantOrderEmailsTest(); diff --git a/tests/e2e/utils/CHANGELOG.md b/tests/e2e/utils/CHANGELOG.md index 2a38d03bb3f..519bc634d5e 100644 --- a/tests/e2e/utils/CHANGELOG.md +++ b/tests/e2e/utils/CHANGELOG.md @@ -20,6 +20,10 @@ - `createSimpleProductWithCategory` component which creates a simple product with categories, containing three parameters for title, price and category name. - `applyCoupon( couponName )` util helper method which applies previously created coupon to cart or checkout - `removeCoupon()` util helper method that removes a single coupon within cart or checkout +- `selectOrderAction( action )` util helper method to select and initiate an order action in the Order Action postbox +- `merchant.openEmailLog()` go to the WP Mail Log page +- `deleteAllEmailLogs` delete all email logs in the WP Mail Log plugin +- `clickUpdateOrder( noticeText, waitForSave )` util helper that clicks the `Update` button on an order ## Changes diff --git a/tests/e2e/utils/README.md b/tests/e2e/utils/README.md index 747d4fb081b..ca185bae73b 100644 --- a/tests/e2e/utils/README.md +++ b/tests/e2e/utils/README.md @@ -54,6 +54,7 @@ describe( 'Cart page', () => { | `openSettings` | | Go to WooCommerce -> Settings | | `runSetupWizard` | | Open the onboarding profiler | | `updateOrderStatus` | `orderId, status` | Update the status of an order | +| `openEmailLog` | | Open the WP Mail Log page | ### Shopper `shopper` @@ -102,9 +103,11 @@ describe( 'Cart page', () => { | `clickFilter` | `selector` | Click on a list page filter | | `moveAllItemsToTrash` | | Moves all items in a list view to the Trash | | `verifyAndPublish` | `noticeText` | Verify that an item can be published | -| `selectOptionInSelect2` | `selector, value` | helper method that searchs for select2 type fields and select plus insert value inside -| `applyCoupon` | `couponName` | helper method which applies a coupon in cart or checkout -| `removeCoupon` | | helper method that removes a single coupon within cart or checkout +| `selectOptionInSelect2` | `selector, value` | helper method that searchs for select2 type fields and select plus insert value inside | +| `applyCoupon` | `couponName` | helper method which applies a coupon in cart or checkout | +| `removeCoupon` | | helper method that removes a single coupon within cart or checkout | +| `selectOrderAction` | `action` | Helper method to select an order action in the `Order Actions` postbox | +| `clickUpdateOrder` | `noticeText`, `waitForSave` | Helper method to click the Update button on the order details page | ### Test Utilities diff --git a/tests/e2e/utils/src/components.js b/tests/e2e/utils/src/components.js index e72ae11d2b0..1776478cecf 100644 --- a/tests/e2e/utils/src/components.js +++ b/tests/e2e/utils/src/components.js @@ -6,7 +6,7 @@ * Internal dependencies */ import { merchant } from './flows'; -import { clickTab, uiUnblocked, verifyCheckboxIsUnset, evalAndClick, selectOptionInSelect2 } from './page-utils'; +import { clickTab, uiUnblocked, verifyCheckboxIsUnset, evalAndClick, selectOptionInSelect2, setCheckbox } from './page-utils'; import factories from './factories'; const config = require( 'config' ); @@ -473,6 +473,42 @@ const createCoupon = async ( couponAmount = '5', discountType = 'Fixed cart disc return couponCode; }; +/** + * Click the Update button on the order details page. + * + * @param noticeText The text that appears in the notice after updating the order. + * @param waitForSave Optionally wait for auto save. + */ +const clickUpdateOrder = async ( noticeText, waitForSave = false ) => { + if ( waitForSave ) { + await page.waitFor( 2000 ); + } + + // PUpdate order + await expect( page ).toClick( 'button.save_order' ); + await page.waitForSelector( '.updated.notice' ); + + // Verify + await expect( page ).toMatchElement( '.updated.notice', { text: noticeText } ); +}; + +/** + * Delete all email logs in the WP Mail Logging plugin page. + */ +const deleteAllEmailLogs = async () => { + await merchant.openEmailLog(); + + // Make sure we have emails to delete. If we don't, this selector will return null. + if ( await page.$( '#bulk-action-selector-top' ) !== null ) { + await setCheckbox( '#cb-select-all-1' ); + await expect( page ).toSelect( '#bulk-action-selector-top', 'Delete' ); + await Promise.all( [ + page.click( '#doaction' ), + page.waitForNavigation( { waitUntil: 'networkidle0' } ), + ] ); + } +}; + export { completeOnboardingWizard, createSimpleProduct, @@ -483,4 +519,6 @@ export { addProductToOrder, createCoupon, createSimpleProductWithCategory, + clickUpdateOrder, + deleteAllEmailLogs, }; diff --git a/tests/e2e/utils/src/flows/merchant.js b/tests/e2e/utils/src/flows/merchant.js index df4fae99d68..242a42c171d 100644 --- a/tests/e2e/utils/src/flows/merchant.js +++ b/tests/e2e/utils/src/flows/merchant.js @@ -169,6 +169,12 @@ const merchant = { await expect( page ).toMatchElement( 'label[for="customer_user"] a[href*=user-edit]', { text: 'Profile' } ); } }, + + openEmailLog: async () => { + await page.goto( `${baseUrl}wp-admin/tools.php?page=wpml_plugin_log`, { + waitUntil: 'networkidle0', + } ); + } }; module.exports = merchant; diff --git a/tests/e2e/utils/src/page-utils.js b/tests/e2e/utils/src/page-utils.js index 9ab8c7b3aa5..400a2c8fd29 100644 --- a/tests/e2e/utils/src/page-utils.js +++ b/tests/e2e/utils/src/page-utils.js @@ -242,6 +242,20 @@ const removeCoupon = async ( couponCode ) => { await expect(page).toMatchElement('.woocommerce-message', {text: 'Coupon has been removed.'}); }; +/** + * + * Select and perform an order action in the `Order actions` postbox. + * + * @param {string} action The action to take on the order. + */ +const selectOrderAction = async ( action ) => { + await page.select( 'select[name=wc_order_action]', action ); + await Promise.all( [ + page.click( '.wc-reload' ), + page.waitForNavigation( { waitUntil: 'networkidle0' } ), + ] ); +} + export { clearAndFillInput, clickTab, @@ -258,6 +272,7 @@ export { moveAllItemsToTrash, evalAndClick, selectOptionInSelect2, - applyCoupon, + applyCoupon, removeCoupon, + selectOrderAction, };