From b7201e1363dd7cb9e3d486317a57d0e31c928ce1 Mon Sep 17 00:00:00 2001 From: Julia Amosova Date: Fri, 30 Aug 2019 12:53:45 +0100 Subject: [PATCH 1/4] Add new Puppeteer e2e test: tax settings --- .../wp-admin/wp-admin-settings-tax.test.js | 137 ++++++++++++++++++ tests/e2e-tests/utils/flows.js | 13 ++ tests/e2e-tests/utils/index.js | 30 ++++ 3 files changed, 180 insertions(+) create mode 100644 tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js diff --git a/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js b/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js new file mode 100644 index 00000000000..310b26e1b18 --- /dev/null +++ b/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js @@ -0,0 +1,137 @@ +/** + * @format + */ + +/** + * External dependencies + */ +import { activatePlugin } from '@wordpress/e2e-test-utils'; + +/** + * Internal dependencies + */ +import { StoreOwnerFlow } from '../../utils/flows'; +import { clearAndFillInput, settingsPageSaveChanges, uiUnblocked } from "../../utils"; + +describe( 'WooCommerce Tax Settings', () => { + beforeAll( async () => { + await activatePlugin( 'woocommerce' ); + } ); + + it( 'can enable tax calculation', async() => { + // Go to general settings page + await StoreOwnerFlow.openSettings( 'general' ); + + // Make sure the general tab is active + await expect( page ).toMatchElement( 'a.nav-tab-active', { text: 'General' } ); + + // Enable tax calculation + await expect( page ).toClick( '#woocommerce_calc_taxes' ); + await settingsPageSaveChanges(); + await expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ); + + // Verify that tax settings are now present + await expect( page ).toMatchElement( 'a.nav-tab', { text: 'Tax' } ); + } ); + + it( 'can set tax options', async () => { + // Go to tax settings page + await StoreOwnerFlow.openSettings( 'tax' ); + + // Make sure the tax tab is active + await expect( page ).toMatchElement( 'a.nav-tab-active', { text: 'Tax' } ); + + // Prices exclusive of tax + await expect( page ).toClick( 'input[name="woocommerce_prices_include_tax"][value="no"]' ); + // Tax based on customer shipping address + await expect( page ).toSelect( '#woocommerce_tax_based_on', 'Customer shipping address' ); + // Standard tax class for shipping + await expect( page ).toSelect( '#woocommerce_shipping_tax_class', 'Standard' ); + // Leave rounding unchecked (no-op) + // Display prices excluding tax + await expect( page ).toSelect( '#woocommerce_tax_display_shop', 'Excluding tax' ); + // Display prices including tax in cart and at checkout + await expect( page ).toSelect( '#woocommerce_tax_display_cart', 'Including tax' ); + // Display a single tax total + await expect( page ).toSelect( '#woocommerce_tax_total_display', 'As a single total' ); + + await settingsPageSaveChanges(); + await expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ); + } ); + + it( 'can add tax classes', async () => { + // Go to tax settings page + await StoreOwnerFlow.openSettings( 'tax' ); + + // Make sure the tax tab is active + await expect( page ).toMatchElement( 'a.nav-tab-active', { text: 'Tax' } ); + + // Remove additional tax classes + await clearAndFillInput( '#woocommerce_tax_classes', '' ); + await settingsPageSaveChanges(); + + // Add a "fancy" tax class + await clearAndFillInput( '#woocommerce_tax_classes', 'Fancy' ); + await settingsPageSaveChanges(); + await expect( page ).toMatchElement( 'ul.subsubsub > li > a', { text: 'Fancy rates' } ); + } ); + + it( 'can set rate settings', async () => { + // Go to "fancy" rates tax settings page + await StoreOwnerFlow.openSettings( 'tax', 'fancy' ); + + // Make sure the tax tab is active, with the "fancy" subsection + await expect( page ).toMatchElement( 'a.nav-tab-active', { text: 'Tax' } ); + await expect( page ).toMatchElement( 'ul.subsubsub > li > a.current', { text: 'Fancy rates' } ); + + // Create a state tax + await expect( page ).toClick( '.wc_tax_rates a.insert' ); + await expect( page ).toFill( 'input[name^="tax_rate_country[new-0"]', 'US' ); + await expect( page ).toFill( 'input[name^="tax_rate_state[new-0"]', 'CA' ); + await expect( page ).toFill( 'input[name^="tax_rate[new-0"]', '7.5' ); + await expect( page ).toFill( 'input[name^="tax_rate_name[new-0"]', 'CA State Tax' ); + + // Create a federal tax + await expect( page ).toClick( '.wc_tax_rates a.insert' ); + await expect( page ).toFill( 'input[name^="tax_rate_country[new-1"]', 'US' ); + await expect( page ).toFill( 'input[name^="tax_rate[new-1"]', '1.5' ); + await expect( page ).toFill( 'input[name^="tax_rate_priority[new-1"]', '2' ); + await expect( page ).toFill( 'input[name^="tax_rate_name[new-1"]', 'Federal Tax' ); + await expect( page ).toClick( 'input[name^="tax_rate_shipping[new-1"]' ); + + // Save changes (AJAX here) + await expect( page ).toClick( 'button.woocommerce-save-button' ); + await uiUnblocked(); + + // Verify 2 tax rates + expect( await page.$$( '#rates tr' ) ).toHaveLength( 2 ); + + // Delete federal rate + await expect( page ).toClick( '#rates tr:nth-child(2) input' ); + await expect( page ).toClick( '.wc_tax_rates a.remove_tax_rates' ); + + // Save changes (AJAX here) + await expect( page ).toClick( 'button.woocommerce-save-button' ); + await uiUnblocked(); + + // Verify 1 rate + expect( await page.$$( '#rates tr' ) ).toHaveLength( 1 ); + await expect( page ).toMatchElement( + '#rates tr:first-of-type input[name^="tax_rate_state"][value="CA"]' + ); + } ); + + it( 'can remove tax classes', async () => { + // Go to tax settings page + await StoreOwnerFlow.openSettings( 'tax' ); + + // Make sure the tax tab is active + await expect( page ).toMatchElement( 'a.nav-tab-active', { text: 'Tax' } ); + + // Remove "fancy" tax class + await clearAndFillInput( '#woocommerce_tax_classes', ' ' ); + await settingsPageSaveChanges(); + await expect( page ).not.toMatchElement( 'ul.subsubsub > li > a', { text: 'Fancy rates' } ); + await page.waitFor( 10000 ); + } ); +} ); diff --git a/tests/e2e-tests/utils/flows.js b/tests/e2e-tests/utils/flows.js index 535d3371e00..fc5d06720f6 100644 --- a/tests/e2e-tests/utils/flows.js +++ b/tests/e2e-tests/utils/flows.js @@ -5,6 +5,7 @@ const baseUrl = process.env.WP_BASE_URL; const WP_ADMIN_NEW_PRODUCT = baseUrl + '/wp-admin/post-new.php?post_type=product'; +const WP_ADMIN_WC_SETTINGS = baseUrl + '/wp-admin/admin.php?page=wc-settings&tab='; const StoreOwnerFlow = { openNewProduct: async () => { @@ -12,6 +13,18 @@ const StoreOwnerFlow = { waitUntil: 'networkidle0', } ); }, + + openSettings: async ( tab, section = null ) => { + let settingsUrl = WP_ADMIN_WC_SETTINGS + tab; + + if ( section ) { + settingsUrl += `§ion=${ section }`; + } + + await page.goto( settingsUrl, { + waitUntil: 'networkidle0', + } ); + }, }; export { StoreOwnerFlow }; diff --git a/tests/e2e-tests/utils/index.js b/tests/e2e-tests/utils/index.js index 7a5a3d64e29..e58ba174113 100644 --- a/tests/e2e-tests/utils/index.js +++ b/tests/e2e-tests/utils/index.js @@ -1,8 +1,25 @@ +/** + * External dependencies + */ +import { pressKeyWithModifier } from '@wordpress/e2e-test-utils'; + /** * Internal dependencies */ const flows = require( './flows' ); +/** + * Perform a "select all" and then fill a input. + * + * @param {string} selector + * @param {string} value + */ +const clearAndFillInput = async ( selector, value ) => { + await page.focus( selector ); + await pressKeyWithModifier( 'primary', 'a' ); + await page.type( selector, value ); +}; + /** * Click a tab (on post type edit screen). * @@ -12,6 +29,17 @@ const clickTab = async ( tabName ) => { await expect( page ).toClick( '.wc-tabs > li > a', { text: tabName } ); }; +/** + * Save changes on a WooCommerce settings page. + */ +const settingsPageSaveChanges = async () => { + await page.focus( 'button.woocommerce-save-button' ); + await Promise.all( [ + page.waitForNavigation( { waitUntil: 'networkidle0' } ), + page.click( 'button.woocommerce-save-button' ), + ] ); +}; + /** * Wait for UI blocking to end. */ @@ -21,6 +49,8 @@ const uiUnblocked = async () => { module.exports = { ...flows, + clearAndFillInput, clickTab, + settingsPageSaveChanges, uiUnblocked, }; From 6989ae76c7d97161e917e26e02f54803d90f949f Mon Sep 17 00:00:00 2001 From: Julia Amosova Date: Tue, 3 Sep 2019 12:55:25 +0100 Subject: [PATCH 2/4] Add `setCheckbox` & `unsetCheckbox` functions --- .../wp-admin/wp-admin-settings-tax.test.js | 4 +-- tests/e2e-tests/utils/index.js | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js b/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js index 310b26e1b18..c00f300c933 100644 --- a/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js +++ b/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js @@ -11,7 +11,7 @@ import { activatePlugin } from '@wordpress/e2e-test-utils'; * Internal dependencies */ import { StoreOwnerFlow } from '../../utils/flows'; -import { clearAndFillInput, settingsPageSaveChanges, uiUnblocked } from "../../utils"; +import { clearAndFillInput, setCheckbox, settingsPageSaveChanges, uiUnblocked } from "../../utils"; describe( 'WooCommerce Tax Settings', () => { beforeAll( async () => { @@ -26,7 +26,7 @@ describe( 'WooCommerce Tax Settings', () => { await expect( page ).toMatchElement( 'a.nav-tab-active', { text: 'General' } ); // Enable tax calculation - await expect( page ).toClick( '#woocommerce_calc_taxes' ); + await setCheckbox( 'input[name="woocommerce_calc_taxes"]' ); await settingsPageSaveChanges(); await expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ); diff --git a/tests/e2e-tests/utils/index.js b/tests/e2e-tests/utils/index.js index e58ba174113..9afe359aeac 100644 --- a/tests/e2e-tests/utils/index.js +++ b/tests/e2e-tests/utils/index.js @@ -40,6 +40,34 @@ const settingsPageSaveChanges = async () => { ] ); }; +/** + * Set checkbox. + * + * @param {string} selector + */ +const setCheckbox = async( selector ) => { + await page.focus( selector ); + const checkbox = await page.$( selector ); + const checkboxStatus = ( await ( await checkbox.getProperty( 'checked' ) ).jsonValue() ); + if ( checkboxStatus !== true ) { + await page.click( selector ); + } +}; + +/** + * Unset checkbox. + * + * @param {string} selector + */ +const unsetCheckbox = async( selector ) => { + await page.focus( selector ); + const checkbox = await page.$( selector ); + const checkboxStatus = ( await ( await checkbox.getProperty( 'checked' ) ).jsonValue() ); + if ( checkboxStatus === true ) { + await page.click( selector ); + } +}; + /** * Wait for UI blocking to end. */ @@ -52,5 +80,7 @@ module.exports = { clearAndFillInput, clickTab, settingsPageSaveChanges, + setCheckbox, + unsetCheckbox, uiUnblocked, }; From 40219168c0645522078a4ca6905feaccc31809c4 Mon Sep 17 00:00:00 2001 From: Julia Amosova Date: Wed, 4 Sep 2019 17:29:13 +0100 Subject: [PATCH 3/4] Add verification of settings after they've been saved --- .../wp-admin/wp-admin-settings-tax.test.js | 48 +++++++++++++++++-- tests/e2e-tests/utils/index.js | 40 ++++++++++++++++ 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js b/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js index c00f300c933..c53e26efaca 100644 --- a/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js +++ b/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js @@ -11,7 +11,14 @@ import { activatePlugin } from '@wordpress/e2e-test-utils'; * Internal dependencies */ import { StoreOwnerFlow } from '../../utils/flows'; -import { clearAndFillInput, setCheckbox, settingsPageSaveChanges, uiUnblocked } from "../../utils"; +import { + clearAndFillInput, + setCheckbox, + settingsPageSaveChanges, + uiUnblocked, + verifyCheckboxIsSet, + verifyValueOfInputField +} from "../../utils"; describe( 'WooCommerce Tax Settings', () => { beforeAll( async () => { @@ -28,7 +35,12 @@ describe( 'WooCommerce Tax Settings', () => { // Enable tax calculation await setCheckbox( 'input[name="woocommerce_calc_taxes"]' ); await settingsPageSaveChanges(); - await expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ); + + // Verify that settings have been saved + await Promise.all( [ + expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ), + verifyCheckboxIsSet( '#woocommerce_calc_taxes' ), + ] ); // Verify that tax settings are now present await expect( page ).toMatchElement( 'a.nav-tab', { text: 'Tax' } ); @@ -56,7 +68,17 @@ describe( 'WooCommerce Tax Settings', () => { await expect( page ).toSelect( '#woocommerce_tax_total_display', 'As a single total' ); await settingsPageSaveChanges(); - await expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ); + + // Verify that settings have been saved + await Promise.all( [ + expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ), + verifyValueOfInputField( 'input[name="woocommerce_prices_include_tax"][value="no"]', 'no' ), + expect( page ).toMatchElement( '#woocommerce_tax_based_on', { text: 'Customer shipping address' } ), + expect( page ).toMatchElement( '#woocommerce_shipping_tax_class', { text: 'Standard' } ), + expect( page ).toMatchElement( '#woocommerce_tax_display_shop', { text: 'Excluding tax' } ), + expect( page ).toMatchElement( '#woocommerce_tax_display_cart', { text: 'Including tax' } ), + expect( page ).toMatchElement( '#woocommerce_tax_total_display', { text: 'As a single total' } ), + ] ); } ); it( 'can add tax classes', async () => { @@ -70,10 +92,21 @@ describe( 'WooCommerce Tax Settings', () => { await clearAndFillInput( '#woocommerce_tax_classes', '' ); await settingsPageSaveChanges(); + // Verify that settings have been saved + await Promise.all( [ + expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ), + verifyValueOfInputField( '#woocommerce_tax_classes', '' ), + ] ); + // Add a "fancy" tax class await clearAndFillInput( '#woocommerce_tax_classes', 'Fancy' ); await settingsPageSaveChanges(); - await expect( page ).toMatchElement( 'ul.subsubsub > li > a', { text: 'Fancy rates' } ); + + // Verify that settings have been saved + await Promise.all( [ + expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ), + expect( page ).toMatchElement( 'ul.subsubsub > li > a', { text: 'Fancy rates' } ), + ] ); } ); it( 'can set rate settings', async () => { @@ -131,7 +164,12 @@ describe( 'WooCommerce Tax Settings', () => { // Remove "fancy" tax class await clearAndFillInput( '#woocommerce_tax_classes', ' ' ); await settingsPageSaveChanges(); - await expect( page ).not.toMatchElement( 'ul.subsubsub > li > a', { text: 'Fancy rates' } ); + + // Verify that settings have been saved + await Promise.all( [ + expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ), + expect( page ).not.toMatchElement( 'ul.subsubsub > li > a', { text: 'Fancy rates' } ), + ] ); await page.waitFor( 10000 ); } ); } ); diff --git a/tests/e2e-tests/utils/index.js b/tests/e2e-tests/utils/index.js index 9afe359aeac..d79b004b789 100644 --- a/tests/e2e-tests/utils/index.js +++ b/tests/e2e-tests/utils/index.js @@ -75,6 +75,43 @@ const uiUnblocked = async () => { await page.waitForFunction( () => ! Boolean( document.querySelector( '.blockUI' ) ) ); }; +/** + * Verify that checkbox is set. + * + * @param {string} selector Selector of the checkbox that needs to be verified. + */ +const verifyCheckboxIsSet = async( selector ) => { + await page.focus( selector ); + const checkbox = await page.$( selector ); + const checkboxStatus = ( await ( await checkbox.getProperty( 'checked' ) ).jsonValue() ); + await expect( checkboxStatus ).toBe( true ); +}; + +/** + * Verify that checkbox is unset. + * + * @param {string} selector Selector of the checkbox that needs to be verified. + */ +const verifyCheckboxIsUnset = async( selector ) => { + await page.focus( selector ); + const checkbox = await page.$( selector ); + const checkboxStatus = ( await ( await checkbox.getProperty( 'checked' ) ).jsonValue() ); + await expect( checkboxStatus ).not.toBe( true ); +}; + +/** + * Verify the value of input field once it was saved (can be used for radio buttons verification as well). + * + * @param {string} selector Selector of the input field that needs to be verified. + * @param {string} value Value of the input field that needs to be verified. + */ +const verifyValueOfInputField = async( selector, value ) => { + await page.focus( selector ); + const field = await page.$( selector ); + const fieldValue = ( await ( await field.getProperty( 'value' ) ).jsonValue() ); + await expect( fieldValue ).toBe( value ); +}; + module.exports = { ...flows, clearAndFillInput, @@ -83,4 +120,7 @@ module.exports = { setCheckbox, unsetCheckbox, uiUnblocked, + verifyCheckboxIsSet, + verifyCheckboxIsUnset, + verifyValueOfInputField, }; From 7c95f52050bd6b7d37aada8b53ecf16923a39142 Mon Sep 17 00:00:00 2001 From: Julia Amosova Date: Sun, 20 Oct 2019 21:52:53 +0100 Subject: [PATCH 4/4] Change verification method after deleting existing tax classes --- tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js b/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js index c53e26efaca..f2384a7db55 100644 --- a/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js +++ b/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js @@ -95,7 +95,7 @@ describe( 'WooCommerce Tax Settings', () => { // Verify that settings have been saved await Promise.all( [ expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ), - verifyValueOfInputField( '#woocommerce_tax_classes', '' ), + expect( page ).toMatchElement( '#woocommerce_tax_classes', { text: '' } ), ] ); // Add a "fancy" tax class