Add new Puppeteer front-end e2e test: checkout page

This commit is contained in:
Julia Amosova 2019-09-24 15:44:10 +01:00
parent fc24adce30
commit 76ccc248aa
4 changed files with 391 additions and 1 deletions

View File

@ -0,0 +1,151 @@
/**
* @format
*/
/**
* External dependencies
*/
import { activatePlugin } from '@wordpress/e2e-test-utils';
/**
* Internal dependencies
*/
import { createSimpleProduct } from '../../utils/components';
import { CustomerFlow, StoreOwnerFlow } from '../../utils/flows';
import { setCheckbox, settingsPageSaveChanges, uiUnblocked, verifyCheckboxIsSet } from "../../utils";
describe( 'Checkout page', () => {
beforeAll( async () => {
await activatePlugin( 'woocommerce' );
await createSimpleProduct();
// Go to general settings page
await StoreOwnerFlow.openSettings( 'general' );
// Set base location with state CA.
await expect( page ).toSelect( 'select[name="woocommerce_default_country"]', 'United States (US) — California' );
// Sell to all countries
await expect( page ).toSelect( '#woocommerce_allowed_countries', 'Sell to all countries' );
// Set currency to USD
await expect( page ).toSelect( '#woocommerce_currency', 'United States (US) dollar ($)' );
// Tax calculation should have been enabled by another test - no-op
// Save
await settingsPageSaveChanges();
// Verify that settings have been saved
await Promise.all( [
expect( page ).toMatchElement( '#message', { text: 'Your settings have been saved.' } ),
expect( page ).toMatchElement( 'select[name="woocommerce_default_country"]', { text: 'United States (US) — California' } ),
expect( page ).toMatchElement( '#woocommerce_allowed_countries', { text: 'Sell to all countries' } ),
expect( page ).toMatchElement( '#woocommerce_currency', { text: 'United States (US) dollar ($)' } ),
] );
// Enable BACS payment method
await StoreOwnerFlow.openSettings( 'checkout', 'bacs' );
await setCheckbox( '#woocommerce_bacs_enabled' );
await settingsPageSaveChanges();
// Verify that settings have been saved
await verifyCheckboxIsSet( '#woocommerce_bacs_enabled' );
// Enable COD payment method
await StoreOwnerFlow.openSettings( 'checkout', 'cod' );
await setCheckbox( '#woocommerce_cod_enabled' );
await settingsPageSaveChanges();
// Verify that settings have been saved
await verifyCheckboxIsSet( '#woocommerce_cod_enabled' );
// Enable PayPal payment method
await StoreOwnerFlow.openSettings( 'checkout', 'paypal' );
await setCheckbox( '#woocommerce_paypal_enabled' );
await settingsPageSaveChanges();
// Verify that settings have been saved
await verifyCheckboxIsSet( '#woocommerce_paypal_enabled' );
await StoreOwnerFlow.logout();
} );
it( 'should displays cart items in order review', async () => {
await CustomerFlow.goToShop();
await CustomerFlow.addToCartFromShopPage( 'Simple product' );
await CustomerFlow.goToCheckout();
await CustomerFlow.productIsInCheckout( 'Simple product', 1, 9.99 );
await expect( page ).toMatchElement( '.cart-subtotal .amount', { text: '$9.99' } );
} );
it( 'allows customer to choose available payment methods', async () => {
await CustomerFlow.goToShop();
await CustomerFlow.addToCartFromShopPage( 'Simple product' );
await CustomerFlow.goToCheckout();
await expect( page ).toClick( '.wc_payment_method label', { text: 'PayPal' } );
await expect( page ).toClick( '.wc_payment_method label', { text: 'Direct bank transfer' } );
await expect( page ).toClick( '.wc_payment_method label', { text: 'Cash on delivery' } );
} );
it( 'allows customer to fill billing details', async () => {
await CustomerFlow.goToShop();
await CustomerFlow.addToCartFromShopPage( 'Simple product' );
await CustomerFlow.goToCheckout();
await expect( page ).toFill( '#billing_first_name', 'John' );
await expect( page ).toFill( '#billing_last_name', 'Doe' );
await expect( page ).toFill( '#billing_company', 'Automattic' );
await expect( page ).toFill( '#billing_email', 'john.doe@example.com' );
await expect( page ).toFill( '#billing_phone', '123456789' );
await expect( page ).toSelect( '#billing_country', 'United States (US)' );
await expect( page ).toFill( '#billing_address_1', 'addr 1' );
await expect( page ).toFill( '#billing_address_2', 'addr 2' );
await expect( page ).toFill( '#billing_city', 'San Francisco' );
await expect( page ).toSelect( '#billing_state', 'California' );
await expect( page ).toFill( '#billing_postcode', '94107' );
} );
it( 'allows customer to fill shipping details', async () => {
await CustomerFlow.goToShop();
await CustomerFlow.addToCartFromShopPage( 'Simple product' );
await CustomerFlow.goToCheckout();
await expect( page ).toClick( '#ship-to-different-address-checkbox' );
await uiUnblocked();
await expect( page ).toFill( '#shipping_first_name', 'John' );
await expect( page ).toFill( '#shipping_last_name', 'Doe' );
await expect( page ).toFill( '#shipping_company', 'Automattic' );
await expect( page ).toSelect( '#shipping_country', 'United States (US)' );
await expect( page ).toFill( '#shipping_address_1', 'addr 1' );
await expect( page ).toFill( '#shipping_address_2', 'addr 2' );
await expect( page ).toFill( '#shipping_city', 'San Francisco' );
await expect( page ).toSelect( '#shipping_state', 'California' );
await expect( page ).toFill( '#shipping_postcode', '94107' );
} );
it( 'allows guest customer to place order', async () => {
await CustomerFlow.goToShop();
await CustomerFlow.addToCartFromShopPage( 'Simple product' );
await CustomerFlow.goToCheckout();
await expect( page ).toFill( '#billing_first_name', 'John' );
await expect( page ).toFill( '#billing_last_name', 'Doe' );
await expect( page ).toFill( '#billing_company', 'Automattic' );
await expect( page ).toFill( '#billing_email', 'john.doe@example.com' );
await expect( page ).toFill( '#billing_phone', '123456789' );
await expect( page ).toSelect( '#billing_country', 'United States (US)' );
await expect( page ).toFill( '#billing_address_1', 'addr 1' );
await expect( page ).toFill( '#billing_address_2', 'addr 2' );
await expect( page ).toFill( '#billing_city', 'San Francisco' );
await expect( page ).toSelect( '#billing_state', 'California' );
await expect( page ).toFill( '#billing_postcode', '94107' );
await uiUnblocked();
await expect( page ).toClick( '.wc_payment_method label', { text: 'Cash on delivery' } );
await expect( page ).toMatchElement( '.payment_method_cod', { text: 'Pay with cash upon delivery.' } );
await uiUnblocked();
await CustomerFlow.placeOrder();
await expect( page ).toMatch( 'Order received' );
} );
} );

View File

@ -0,0 +1,129 @@
/**
* @format
*/
/**
* Internal dependencies
*/
import { StoreOwnerFlow } from "./flows";
import { clickTab, uiUnblocked } from "./index";
const verifyAndPublish = async () => {
// Wait for auto save
await page.waitFor( 2000 );
// Publish product
await expect( page ).toClick( '#publish' );
await page.waitForSelector( '.updated.notice' );
// Verify
await expect( page ).toMatchElement( '.updated.notice', { text: 'Product published.' } );
};
/**
* Create simple product.
*/
const createSimpleProduct = async () => {
// Go to "add product" page
await StoreOwnerFlow.openNewProduct();
// Make sure we're on the add order page
await expect(page.title()).resolves.toMatch('Add new product');
// Set product data
await expect(page).toFill('#title', 'Simple product');
await clickTab('General');
await expect(page).toFill('#_regular_price', '9.99');
await verifyAndPublish();
};
/**
* Create variable product.
*/
const createVariableProduct = async () => {
// Go to "add product" page
await StoreOwnerFlow.openNewProduct();
// Make sure we're on the add order page
await expect( page.title() ).resolves.toMatch( 'Add new product' );
// Set product data
await expect( page ).toFill( '#title', 'Variable Product with Two Variations' );
await expect( page ).toSelect( '#product-type', 'Variable product' );
// Create attributes for variations
await clickTab( 'Attributes' );
await expect( page ).toSelect( 'select[name="attribute_taxonomy"]', 'Custom product attribute' );
for ( let i = 0; i < 3; i++ ) {
await expect( page ).toClick( 'button.add_attribute', { text: 'Add' } );
// Wait for attribute form to load
await uiUnblocked();
await page.focus( `input[name="attribute_names[${ i }]"]` );
await expect( page ).toFill( `input[name="attribute_names[${ i }]"]`, 'attr #' + ( i + 1 ) );
await expect( page ).toFill( `textarea[name="attribute_values[${ i }]"]`, 'val1 | val2' );
await expect( page ).toClick( `input[name="attribute_variation[${ i }]"]` );
}
await expect( page ).toClick( 'button', { text: 'Save attributes' } );
// Wait for attribute form to save (triggers 2 UI blocks)
await uiUnblocked();
await uiUnblocked();
// Create variations from attributes
await clickTab( 'Variations' );
await page.waitForSelector( 'select.variation_actions:not([disabled])' );
await page.focus( 'select.variation_actions' );
await expect( page ).toSelect( 'select.variation_actions', 'Create variations from all attributes' );
const firstDialog = await expect( page ).toDisplayDialog( async () => {
// Using this technique since toClick() isn't working.
// See: https://github.com/GoogleChrome/puppeteer/issues/1805#issuecomment-464802876
page.$eval( 'a.do_variation_action', elem => elem.click() );
} );
expect( firstDialog.message() ).toMatch( 'Are you sure you want to link all variations?' );
const secondDialog = await expect( page ).toDisplayDialog( async () => {
await firstDialog.accept();
} );
expect( secondDialog.message() ).toMatch( '8 variations added' );
await secondDialog.dismiss();
// Set some variation data
await uiUnblocked();
await uiUnblocked();
await page.waitForSelector( '.woocommerce_variation .handlediv' );
await expect( page ).toClick( '.woocommerce_variation:nth-of-type(1) .handlediv' );
await page.focus( 'input[name="variable_is_virtual[0]"]' );
await expect( page ).toClick( 'input[name="variable_is_virtual[0]"]' );
await expect( page ).toFill( 'input[name="variable_regular_price[0]"]', '9.99' );
await expect( page ).toClick( '.woocommerce_variation:nth-of-type(2) .handlediv' );
await page.focus( 'input[name="variable_is_virtual[1]"]' );
await expect( page ).toClick( 'input[name="variable_is_virtual[1]"]' );
await expect( page ).toFill( 'input[name="variable_regular_price[1]"]', '11.99' );
await expect( page ).toClick( '.woocommerce_variation:nth-of-type(3) .handlediv' );
await page.focus( 'input[name="variable_manage_stock[2]"]' );
await expect( page ).toClick( 'input[name="variable_manage_stock[2]"]' );
await expect( page ).toFill( 'input[name="variable_regular_price[2]"]', '20' );
await expect( page ).toFill( 'input[name="variable_weight[2]"]', '200' );
await expect( page ).toFill( 'input[name="variable_length[2]"]', '10' );
await expect( page ).toFill( 'input[name="variable_width[2]"]', '20' );
await expect( page ).toFill( 'input[name="variable_height[2]"]', '15' );
await page.focus( 'button.save-variation-changes' );
await expect( page ).toClick( 'button.save-variation-changes', { text: 'Save changes' } );
await verifyAndPublish();
};
export { createSimpleProduct };

View File

@ -5,13 +5,83 @@
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 SHOP_PAGE = baseUrl + '/shop/';
const SHOP_CHECKOUT_PAGE = baseUrl + '/checkout/';
const CustomerFlow = {
addToCartFromShopPage: async ( productTitle ) => {
const addToCartXPath = `//li[contains(@class, "type-product") and a/h2[contains(text(), "${ productTitle }")]]` +
'//a[contains(@class, "add_to_cart_button") and contains(@class, "ajax_add_to_cart")';
const [ addToCartButton ] = await page.$x( addToCartXPath + ']' );
addToCartButton.click();
await page.waitFor( addToCartXPath + ' and contains(@class, "added")]' );
},
goToCheckout: async () => {
await page.goto( SHOP_CHECKOUT_PAGE, {
waitUntil: 'networkidle0',
} );
},
goToShop: async () => {
await page.goto(SHOP_PAGE, {
waitUntil: 'networkidle0',
});
},
placeOrder: async () => {
await Promise.all( [
expect( page ).toClick( '#place_order' ),
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
] );
},
productIsInCheckout: async ( productTitle, quantity, total ) => {
const checkoutItemXPath =
'//tr[@class="cart_item" and ' +
`.//td[contains(., "${ productTitle }") and contains(., "× ${ quantity }")] and ` +
`.//td[contains(., "${ total }")]` +
']';
await expect( page.$x( checkoutItemXPath ) ).resolves.toHaveLength( 1 );
},
};
const StoreOwnerFlow = {
logout: async () => {
await page.goto( baseUrl + '/wp-login.php?action=logout', {
waitUntil: 'networkidle0',
} );
await expect( page ).toMatch( 'You are attempting to log out' );
await Promise.all( [
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
page.click( 'a' ),
] );
},
openNewProduct: async () => {
await page.goto( WP_ADMIN_NEW_PRODUCT, {
waitUntil: 'networkidle0',
} );
},
openSettings: async ( tab, section = null ) => {
let settingsUrl = WP_ADMIN_WC_SETTINGS + tab;
if ( section ) {
settingsUrl += `&section=${ section }`;
}
await page.goto( settingsUrl, {
waitUntil: 'networkidle0',
} );
},
};
export { StoreOwnerFlow };
export { CustomerFlow, StoreOwnerFlow };

View File

@ -12,6 +12,31 @@ 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' ),
] );
};
/**
* 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 );
}
};
/**
* Wait for UI blocking to end.
*/
@ -19,8 +44,23 @@ 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 );
};
module.exports = {
...flows,
clickTab,
settingsPageSaveChanges,
setCheckbox,
uiUnblocked,
verifyCheckboxIsSet,
};