diff --git a/tests/e2e/core-tests/CHANGELOG.md b/tests/e2e/core-tests/CHANGELOG.md index 76cb0c73794..e1de76511aa 100644 --- a/tests/e2e/core-tests/CHANGELOG.md +++ b/tests/e2e/core-tests/CHANGELOG.md @@ -1,5 +1,8 @@ # Unreleased +## Added +- Merchant Order Status Filter tests + ## Fixed - Flaky Create Product, Coupon, and Order tests diff --git a/tests/e2e/core-tests/README.md b/tests/e2e/core-tests/README.md index 8107b6420f7..c90af7e4bf5 100644 --- a/tests/e2e/core-tests/README.md +++ b/tests/e2e/core-tests/README.md @@ -52,6 +52,7 @@ The functions to access the core tests are: - `runUpdateGeneralSettingsTest` - Merchant can update general settings - `runProductSettingsTest` - Merchant can update product settings - `runTaxSettingsTest` - Merchant can update tax settings +- `runOrderStatusFilterTest` - Merchant can filter orders by order status ### Shopper diff --git a/tests/e2e/core-tests/specs/index.js b/tests/e2e/core-tests/specs/index.js index a0d915867a7..256c87a4dba 100644 --- a/tests/e2e/core-tests/specs/index.js +++ b/tests/e2e/core-tests/specs/index.js @@ -2,19 +2,26 @@ /* * Internal dependencies */ + +// Setup and onboarding tests const runActivationTest = require( './activate-and-setup/activate.test' ); const { runOnboardingFlowTest, runTaskListTest } = require( './activate-and-setup/onboarding-tasklist.test' ); const runInitialStoreSettingsTest = require( './activate-and-setup/setup.test' ); + +// Shopper tests const runCartPageTest = require( './shopper/front-end-cart.test' ); const runCheckoutPageTest = require( './shopper/front-end-checkout.test' ); const runMyAccountPageTest = require( './shopper/front-end-my-account.test' ); const runSingleProductPageTest = require( './shopper/front-end-single-product.test' ); + +// Merchant tests const runCreateCouponTest = require( './merchant/wp-admin-coupon-new.test' ); const runCreateOrderTest = require( './merchant/wp-admin-order-new.test' ); const { runAddSimpleProductTest, runAddVariableProductTest } = require( './merchant/wp-admin-product-new.test' ); const runUpdateGeneralSettingsTest = require( './merchant/wp-admin-settings-general.test' ); const runProductSettingsTest = require( './merchant/wp-admin-settings-product.test' ); const runTaxSettingsTest = require( './merchant/wp-admin-settings-tax.test' ); +const runOrderStatusFilterTest = require( './merchant/wp-admin-order-status-filter.test' ); const runSetupOnboardingTests = () => { runActivationTest(); @@ -38,6 +45,7 @@ const runMerchantTests = () => { runUpdateGeneralSettingsTest(); runProductSettingsTest(); runTaxSettingsTest(); + runOrderStatusFilterTest(); } module.exports = { @@ -58,5 +66,6 @@ module.exports = { runUpdateGeneralSettingsTest, runProductSettingsTest, runTaxSettingsTest, + runOrderStatusFilterTest, runMerchantTests, }; diff --git a/tests/e2e/core-tests/specs/merchant/wp-admin-order-status-filter.test.js b/tests/e2e/core-tests/specs/merchant/wp-admin-order-status-filter.test.js new file mode 100644 index 00000000000..4f69df2a236 --- /dev/null +++ b/tests/e2e/core-tests/specs/merchant/wp-admin-order-status-filter.test.js @@ -0,0 +1,108 @@ +/* eslint-disable jest/no-export, jest/no-disabled-tests */ +/** + * Internal dependencies + */ +const { + StoreOwnerFlow, + createSimpleOrder, + clickFilter, + moveAllItemsToTrash, +} = require( '@woocommerce/e2e-utils' ); + +let statusColumnTextSelector = 'mark.order-status > span'; + +const runOrderFiltersTest = () => { + describe('WooCommerce Orders > Filter Orders by Status', () => { + beforeAll(async () => { + // First, let's login + await StoreOwnerFlow.login(); + + // Next, let's create some orders we can filter against + await createSimpleOrder('Pending payment'); + await createSimpleOrder('Processing'); + await createSimpleOrder('Completed'); + await createSimpleOrder('Cancelled'); + await createSimpleOrder('Refunded'); + }); + + afterAll( async () => { + // Make sure we're on the all orders view and cleanup the orders we created + await StoreOwnerFlow.openAllOrdersView(); + await moveAllItemsToTrash(); + }); + + it('should filter by Pending payment', async () => { + await StoreOwnerFlow.openAllOrdersView(); + await clickFilter('.wc-pending'); + await expect(page).toMatchElement(statusColumnTextSelector, {text: 'Pending payment'}); + + // Verify other statuses don't show + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Processing'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Completed'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Cancelled'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Refunded'}); + }); + + it('should filter by Processing', async () => { + await StoreOwnerFlow.openAllOrdersView(); + await clickFilter('.wc-processing'); + await expect(page).toMatchElement(statusColumnTextSelector, {text: 'Processing'}); + + // Verify other statuses don't show + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Pending payment'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Completed'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Cancelled'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Refunded'}); + }); + + it('should filter by Completed', async () => { + await StoreOwnerFlow.openAllOrdersView(); + await clickFilter('.wc-completed'); + await expect(page).toMatchElement(statusColumnTextSelector, {text: 'Completed'}); + + // Verify other statuses don't show + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Pending payment'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Processing'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Cancelled'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Refunded'}); + }); + + it('should filter by Cancelled', async () => { + await StoreOwnerFlow.openAllOrdersView(); + await clickFilter('.wc-cancelled'); + await expect(page).toMatchElement(statusColumnTextSelector, {text: 'Cancelled'}); + + // Verify other statuses don't show + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Pending payment'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Processing'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Completed'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Refunded'}); + }); + + it('should filter by Refunded', async () => { + await StoreOwnerFlow.openAllOrdersView(); + await clickFilter('.wc-refunded'); + await expect(page).toMatchElement(statusColumnTextSelector, {text: 'Refunded'}); + + // Verify other statuses don't show + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Pending payment'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Processing'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Completed'}); + await expect(page).not.toMatchElement(statusColumnTextSelector, {text: 'Cancelled'}); + }); + + it('should filter by All', async () => { + await StoreOwnerFlow.openAllOrdersView(); + // Make sure all the order statuses that were created show in this list + await clickFilter('.all'); + await expect(page).toMatchElement(statusColumnTextSelector, {text: 'Pending payment'}); + await expect(page).toMatchElement(statusColumnTextSelector, {text: 'Processing'}); + await expect(page).toMatchElement(statusColumnTextSelector, {text: 'Completed'}); + await expect(page).toMatchElement(statusColumnTextSelector, {text: 'Cancelled'}); + await expect(page).toMatchElement(statusColumnTextSelector, {text: 'Refunded'}); + }); + + }); +}; + +module.exports = runOrderFiltersTest; diff --git a/tests/e2e/utils/CHANGELOG.md b/tests/e2e/utils/CHANGELOG.md index 1e54a5e6553..4792a1fbbb4 100644 --- a/tests/e2e/utils/CHANGELOG.md +++ b/tests/e2e/utils/CHANGELOG.md @@ -1,5 +1,10 @@ # Unreleased +## Added +- `clickFilter()` util helper method that clicks on a list page filter +- `moveAllItemsToTrash()` util helper method that checks every item in a list page and moves them to the trash +- `createSimpleOrder( status )` component which accepts an order status string and creates a basic order with that status + # 0.1.1 - Initial/beta release diff --git a/tests/e2e/utils/README.md b/tests/e2e/utils/README.md index bcd841f2af3..6a31fde72dc 100644 --- a/tests/e2e/utils/README.md +++ b/tests/e2e/utils/README.md @@ -91,6 +91,8 @@ describe( 'Cart page', () => { | `verifyCheckboxIsSet` | `selector` | Verify that a checkbox is checked | | `verifyCheckboxIsUnset` | `selector` | Verify that a checkbox is unchecked | | `verifyValueOfInputField` | `selector, value` | Verify an input contains the passed value | +| `clickFilter` | `selector` | Click on a list page filter | +| `moveAllItemsToTrash` | | Moves all items in a list view to the Trash | |----------|------------|-------------| ### Test Utilities diff --git a/tests/e2e/utils/src/components.js b/tests/e2e/utils/src/components.js index 5df1b4425b8..4e82df359ae 100644 --- a/tests/e2e/utils/src/components.js +++ b/tests/e2e/utils/src/components.js @@ -220,7 +220,7 @@ const createVariableProduct = async () => { // Go to "add product" page await StoreOwnerFlow.openNewProduct(); - // Make sure we're on the add order page + // Make sure we're on the add product page await expect( page.title() ).resolves.toMatch( 'Add new product' ); // Set product data @@ -344,9 +344,36 @@ const createVariableProduct = async () => { return variablePostIdValue; }; +/** + * Create a basic order with the provided order status. + * + * @param orderStatus Status of the new order. Defaults to `Pending payment`. + */ +const createSimpleOrder = async ( orderStatus = 'Pending payment' ) => { + // Go to 'Add new order' page + await StoreOwnerFlow.openNewOrder(); + + // Make sure we're on the add order page + await expect( page.title() ).resolves.toMatch( 'Add new order' ); + + // Set order status + await expect( page ).toSelect( '#order_status', orderStatus ); + + // Wait for auto save + await page.waitFor( 2000 ); + + // Create the order + await expect( page ).toClick( 'button.save_order' ); + await page.waitForSelector( '#message' ); + + // Verify + await expect( page ).toMatchElement( '#message', { text: 'Order updated.' } ); +}; + export { completeOnboardingWizard, createSimpleProduct, createVariableProduct, + createSimpleOrder, verifyAndPublish, }; diff --git a/tests/e2e/utils/src/page-utils.js b/tests/e2e/utils/src/page-utils.js index 00b48dc54ae..2a77ba4b709 100644 --- a/tests/e2e/utils/src/page-utils.js +++ b/tests/e2e/utils/src/page-utils.js @@ -155,6 +155,34 @@ const verifyValueOfInputField = async( selector, value ) => { await expect( fieldValue ).toBe( value ); }; +/** + * Clicks on a filter on a list page, such as WooCommerce > Orders or Posts > All Posts. + * + * @param {string} selector Selector of the filter link to be clicked. + */ +const clickFilter = async( selector ) => { + await page.waitForSelector( selector ); + await page.focus( selector ); + await Promise.all( [ + page.click( `.subsubsub > ${selector} > a` ), + page.waitForNavigation( { waitUntil: 'networkidle0' } ), + ] ); +}; + +/** + * Moves all items in a list view to the trash. + * + * If there's more than 20 items, it moves all 20 items on the current page. + */ +const moveAllItemsToTrash = async() => { + await setCheckbox( '#cb-select-all-1' ); + await expect( page ).toSelect( '#bulk-action-selector-top', 'Move to Trash' ); + await Promise.all( [ + page.click( '#doaction' ), + page.waitForNavigation( { waitUntil: 'networkidle0' } ), + ] ); +}; + export { clearAndFillInput, clickTab, @@ -167,4 +195,6 @@ export { verifyCheckboxIsSet, verifyCheckboxIsUnset, verifyValueOfInputField, + clickFilter, + moveAllItemsToTrash, };