Remove Selenium e2e tests & add Puppeteer new product e2e test

This commit is contained in:
Julia Amosova 2019-08-27 13:22:24 +01:00
parent 917bc768e3
commit 560f64d212
23 changed files with 215 additions and 1121 deletions

View File

@ -64,8 +64,7 @@
"prettier": "github:automattic/calypso-prettier#c56b4251",
"puppeteer": "1.19.0",
"stylelint": "10.1.0",
"stylelint-config-wordpress": "14.0.0",
"wc-e2e-page-objects": "0.10.0"
"stylelint-config-wordpress": "14.0.0"
},
"engines": {
"node": ">=10.15.0",

View File

@ -26,6 +26,7 @@ spawn(
'--maxWorkers=1',
'--config=tests/e2e-tests/config/jest.config.js',
'--rootDir=./',
'--verbose',
program.args,
],
{

View File

@ -13,6 +13,7 @@ Automated end-to-end tests for WooCommerce.
- [Running tests](#running-tests)
- [How to run tests](#how-to-run-tests)
- [Writing tests](#writing-tests)
- [Debugging tests](#debugging-tests)
## Pre-requisites
@ -100,7 +101,7 @@ The `Development mode` also enables SlowMo mode. SlowMo slows down Puppeteers
To run an individual test, use the direct path to the spec. For example:
```bash
npm run test:e2e ./tests/e2e-tests/specs/activate-woocommerce.test.js
npm run test:e2e ./tests/e2e-tests/specs/wp-admin/wp-admin-product-new.test.js
```
You can also provide the base URL, Test username and Test password like this:
@ -121,4 +122,22 @@ Tests are kept in `tests/e2e-tests/specs` folder.
The following packages are being used to write tests:
- `e2e-test-utils` - End-To-End (E2E) test utils for WordPress. You can find the full list of utils [here](https://github.com/WordPress/gutenberg/tree/master/packages/e2e-test-utils).
- `e2e-test-utils` - End-To-End (E2E) test utils for WordPress. You can find the full list of utils [here](https://github.com/WordPress/gutenberg/tree/master/packages/e2e-test-utils).
## Debugging tests
Debugging tools are pre-built in the existing Puppeteer's architecture. To enable debugging:
- Run tests in the `Development mode`;
- Use `await jestPuppeteer.debug();` in test code to pause execution.
Doing the above will allow for the following:
- Tests to be run non-headless;
- SlowMo mode enabled;
- Chrome Dev Tools open by default;
- Test timeout time increased to 2 minutes.
If more than 2 minutes needed for inspection, adjust the `jestTimeoutInMilliSeconds` value in `./tests/e2e-tests/config/jest.setup.js`.
For more Puppeteer debugging tips, check [Google's documentation](https://developers.google.com/web/tools/puppeteer/debugging).

View File

@ -1,62 +0,0 @@
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { WPLogin, WPAdmin } from 'wp-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
let manager;
let driver;
test.describe( 'Check for functional WordPress installation', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
// login
test.before( () => {
const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } );
wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) );
} );
// Update the database to the current version of WP
test.it( 'update WordPress database', () => {
const updateArgs = { url: manager.getPageUrl( '/wp-admin/upgrade.php?step=upgrade_db' ), visit: true };
const update = new WPAdmin( driver, updateArgs );
} );
// Check theme status after conditionally attempting to revert to the default theme
test.it( 'have working theme', () => {
const themesArgs = { url: manager.getPageUrl( '/wp-admin/themes.php' ), visit: true };
const themes = new WPAdmin( driver, themesArgs );
driver.navigate().refresh();
assert.eventually.notEqual( themes.hasNotice( 'The active theme is broken.' ) );
assert.eventually.notEqual( themes.hasNotice( 'No themes found.' ) );
assert.eventually.notEqual( themes.hasNotice( 'ERROR:' ) );
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,7 +1,12 @@
/** format */
/**
* Increase the default timeout to 10s
*/
let jestTimeoutInMilliSeconds = 10000;
//Set the default test timeout to 30s
let jestTimeoutInMilliSeconds = 30000;
// When running test in the Development mode, the test timeout is increased to 2 minutes which allows for errors to be inspected.
// Use `await jestPuppeteer.debug()` in test code to pause execution.
if ( process.env.JEST_PUPPETEER_CONFIG === 'tests/e2e-tests/config/jest-puppeteer.dev.config.js' ) {
jestTimeoutInMilliSeconds = 120000;
}
jest.setTimeout( jestTimeoutInMilliSeconds );

View File

@ -1,118 +0,0 @@
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { ShopPage, CartPage } from 'wc-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
let manager;
let driver;
test.describe( 'Cart page', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
test.it( 'should displays no item in the cart', () => {
const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
assert.eventually.equal( cartPage.hasNoItem(), true );
} );
test.it( 'should adds the product to the cart when "Add to cart" is clicked', () => {
const shopPage = new ShopPage( driver, { url: manager.getPageUrl( '/shop' ) } );
assert.eventually.equal( shopPage.addProductToCart( 'Album' ), true );
assert.eventually.equal( shopPage.addProductToCart( 'Polo' ), true );
const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
assert.eventually.equal( cartPage.hasItem( 'Album' ), true );
assert.eventually.equal( cartPage.hasItem( 'Polo' ), true );
} );
test.it( 'should increases item qty when "Add to cart" of the same product is clicked', () => {
const shopPage = new ShopPage( driver, { url: manager.getPageUrl( '/shop' ) } );
assert.eventually.equal( shopPage.addProductToCart( 'Album' ), true );
const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
assert.eventually.equal( cartPage.hasItem( 'Album', { qty: 2 } ), true );
assert.eventually.equal( cartPage.hasItem( 'Polo', { qty: 1 } ), true );
} );
test.it( 'should updates qty when updated via qty input', () => {
const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
cartPage.getItem( 'Album', { qty: 2 } ).setQty( 4 );
cartPage.getItem( 'Polo', { qty: 1 } ).setQty( 3 );
cartPage.update();
assert.eventually.equal( cartPage.hasItem( 'Album', { qty: 4 } ), true );
assert.eventually.equal( cartPage.hasItem( 'Polo', { qty: 3 } ), true );
} );
test.it( 'should remove the item from the cart when remove is clicked', () => {
const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
cartPage.getItem( 'Album', { qty: 4 } ).remove();
cartPage.getItem( 'Polo', { qty: 3 } ).remove();
assert.eventually.equal( cartPage.hasNoItem(), true );
} );
test.it( 'should update subtotal in cart totals when adding product to the cart', () => {
const shopPage = new ShopPage( driver, { url: manager.getPageUrl( '/shop' ) } );
assert.eventually.equal( shopPage.addProductToCart( 'Album' ), true );
const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
assert.eventually.equal(
cartPage.hasItem( 'Album', { qty: 1 } ),
true,
'Cart item "Album" with qty 1 is not displayed'
);
assert.eventually.equal(
cartPage.hasSubtotal( '15.00' ),
true,
'Cart totals does not display subtotal of 15.00'
);
cartPage.getItem( 'Album', { qty: 1 } ).setQty( 2 );
cartPage.update();
assert.eventually.equal(
cartPage.hasSubtotal( '30.00' ),
true,
'Cart totals does not display subtotal of 30.00'
);
} );
test.it( 'should go to the checkout page when "Proceed to Checkout" is clicked', () => {
const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
const checkoutPage = cartPage.checkout();
assert.eventually.equal(
checkoutPage.components.orderReview.displayed(),
true,
'Order review in checkout page is not displayed'
);
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,162 +0,0 @@
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { Helper, PageMap, CheckoutOrderReceivedPage, StoreOwnerFlow, GuestCustomerFlow } from 'wc-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
const PAGE = PageMap.PAGE;
const storeOwnerFlowArgs = {
baseUrl: config.get( 'url' ),
username: config.get( 'users.admin.username' ),
password: config.get( 'users.admin.password' )
};
const assertOrderItem = ( orderReview, itemName, attrs ) => {
assert.eventually.ok(
orderReview.hasItem( itemName, attrs ),
`Could not find order item "${ itemName }" with qty ${ attrs.qty } and total ${ attrs.total }`
);
};
let manager;
let driver;
test.describe( 'Checkout Page', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
const storeOwner = new StoreOwnerFlow( driver, storeOwnerFlowArgs );
// General settings for this test.
storeOwner.setGeneralSettings( {
baseLocation: [ 'United States', 'United States (US) — California' ],
sellingLocation: 'Sell to all countries',
enableTaxes: true,
currency: [ 'United States', 'United States (US) dollar ($)' ],
} );
// Make sure payment method is set in setting.
storeOwner.enableBACS();
storeOwner.enableCOD();
storeOwner.enablePayPal();
storeOwner.logout();
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
test.it( 'should displays cart items in order review', () => {
const guest = new GuestCustomerFlow( driver, { baseUrl: config.get( 'url' ) } );
guest.fromShopAddProductsToCart( 'Beanie', 'Long Sleeve Tee' );
const checkoutPage = guest.openCheckout();
assert.eventually.ok( Helper.waitTillUIBlockNotPresent( driver ) );
const orderReview = checkoutPage.components.orderReview;
assertOrderItem( orderReview, 'Beanie', { qty: '1', total: '18.00' } );
assertOrderItem( orderReview, 'Long Sleeve Tee', { qty: '1', total: '25.00' } );
assert.eventually.ok( orderReview.hasSubtotal( '43.00' ), 'Could not find subtotal 43.00' );
} );
test.it( 'allows customer to choose available payment methods', () => {
const guest = new GuestCustomerFlow( driver, { baseUrl: config.get( 'url' ) } );
guest.fromShopAddProductsToCart( 'Beanie', 'Long Sleeve Tee' );
const checkoutPage = guest.openCheckout();
assert.eventually.ok( Helper.waitTillUIBlockNotPresent( driver ) );
assert.eventually.ok( checkoutPage.selectPaymentMethod( 'PayPal' ) );
assert.eventually.ok( checkoutPage.selectPaymentMethod( 'Direct bank transfer' ) );
assert.eventually.ok( checkoutPage.selectPaymentMethod( 'Cash on delivery' ) );
} );
test.it( 'allows customer to fill billing details', () => {
const guest = new GuestCustomerFlow( driver, { baseUrl: config.get( 'url' ) } );
guest.fromShopAddProductsToCart( 'Beanie', 'Long Sleeve Tee' );
const checkoutPage = guest.open( PAGE.CHECKOUT );
assert.eventually.ok( Helper.waitTillUIBlockNotPresent( driver ) );
const billingDetails = checkoutPage.components.billingDetails;
assert.eventually.ok( billingDetails.setFirstName( 'John' ) );
assert.eventually.ok( billingDetails.setLastName( 'Doe' ) );
assert.eventually.ok( billingDetails.setCompany( 'Automattic' ) );
assert.eventually.ok( billingDetails.setEmail( 'john.doe@example.com' ) );
assert.eventually.ok( billingDetails.setPhone( '123456789' ) );
assert.eventually.ok( billingDetails.selectCountry( 'united states', 'United States (US)' ) );
assert.eventually.ok( billingDetails.setAddress1( 'addr 1' ) );
assert.eventually.ok( billingDetails.setAddress2( 'addr 2' ) );
assert.eventually.ok( billingDetails.setCity( 'San Francisco' ) );
assert.eventually.ok( billingDetails.selectState( 'cali', 'California' ) );
assert.eventually.ok( billingDetails.setZip( '94107' ) );
} );
test.it( 'allows customer to fill shipping details', () => {
const guest = new GuestCustomerFlow( driver, { baseUrl: config.get( 'url' ) } );
guest.fromShopAddProductsToCart( 'Beanie', 'Long Sleeve Tee' );
const checkoutPage = guest.open( PAGE.CHECKOUT );
assert.eventually.ok( Helper.waitTillUIBlockNotPresent( driver ) );
assert.eventually.ok( checkoutPage.checkShipToDifferentAddress() );
const shippingDetails = checkoutPage.components.shippingDetails;
assert.eventually.ok( shippingDetails.setFirstName( 'John' ) );
assert.eventually.ok( shippingDetails.setLastName( 'Doe' ) );
assert.eventually.ok( shippingDetails.setCompany( 'Automattic' ) );
assert.eventually.ok( shippingDetails.selectCountry( 'united states', 'United States (US)' ) );
assert.eventually.ok( shippingDetails.setAddress1( 'addr 1' ) );
assert.eventually.ok( shippingDetails.setAddress2( 'addr 2' ) );
assert.eventually.ok( shippingDetails.setCity( 'San Francisco' ) );
assert.eventually.ok( shippingDetails.selectState( 'cali', 'California' ) );
assert.eventually.ok( shippingDetails.setZip( '94107' ) );
} );
test.it( 'allows guest customer to place order', () => {
const guest = new GuestCustomerFlow( driver, { baseUrl: config.get( 'url' ) } );
guest.fromShopAddProductsToCart( 'Beanie', 'Long Sleeve Tee' );
const checkoutPage = guest.open( PAGE.CHECKOUT );
const billingDetails = checkoutPage.components.billingDetails;
Helper.waitTillUIBlockNotPresent( driver );
billingDetails.setFirstName( 'John' );
billingDetails.setLastName( 'Doe' );
billingDetails.setCompany( 'Automattic' );
billingDetails.setEmail( 'john.doe@example.com' );
billingDetails.setPhone( '123456789' );
billingDetails.selectCountry( 'united states', 'United States (US)' );
billingDetails.setAddress1( 'addr 1' );
billingDetails.setAddress2( 'addr 2' );
billingDetails.setCity( 'San Francisco' );
billingDetails.selectState( 'cali', 'California' );
billingDetails.setZip( '94107' );
Helper.waitTillUIBlockNotPresent( driver );
checkoutPage.selectPaymentMethod( 'Cash on delivery' );
checkoutPage.placeOrder();
Helper.waitTillUIBlockNotPresent( driver );
assert.eventually.ok(
checkoutPage.hasText( 'Order received' )
);
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,129 +0,0 @@
/**
* External dependencies
*/
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { CustomerFlow, MyAccountPage, PageMap } from 'wc-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
let manager;
let driver;
test.describe( 'My account page', function() {
const loginAsCustomer = () => {
return new CustomerFlow( driver, {
baseUrl: config.get( 'url' ),
username: config.get( 'users.customer.username' ),
password: config.get( 'users.customer.password' )
} );
};
const getMyAccountSubPageUrl = path => {
return PageMap.getPageUrl( config.get( 'url' ), {
path: '/my-account/%s'
}, path );
};
const untrailingslashit = url => {
return url.endsWith( '/' ) ? url.substring( 0, url.length - 1 ) : url;
};
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
test.it( 'allows customer to login', () => {
loginAsCustomer();
const myAccount = new MyAccountPage( driver, {
baseUrl: config.get( 'url' ),
visit: false
} );
assert.eventually.ok( myAccount.hasText( 'Hello Customer' ), 'see "Hello Customer" text' );
assert.eventually.ok( myAccount.hasMenu( 'Dashboard' ), 'see Dashboard menu.' );
assert.eventually.ok( myAccount.hasMenu( 'Orders' ), 'see Orders menu' );
} );
test.it( 'allows customer to see orders', () => {
loginAsCustomer();
const myAccount = new MyAccountPage( driver, {
baseUrl: config.get( 'url' ),
visit: false
} );
myAccount.clickMenu( 'Orders' );
assert.eventually.equal(
driver.getCurrentUrl().then( untrailingslashit ),
untrailingslashit( getMyAccountSubPageUrl( 'orders' ) )
);
assert.eventually.ok( myAccount.hasText( 'Orders' ), 'see "Orders" text' );
} );
test.it( 'allows customer to see downloads', () => {
loginAsCustomer();
const myAccount = new MyAccountPage( driver, {
baseUrl: config.get( 'url' ),
visit: false
} );
myAccount.clickMenu( 'Downloads' );
assert.eventually.equal(
driver.getCurrentUrl().then( untrailingslashit ),
untrailingslashit( getMyAccountSubPageUrl( 'downloads' ) )
);
assert.eventually.ok( myAccount.hasText( 'Downloads' ), 'see "Downloads" text' );
} );
test.it( 'allows customer to edit addresses', () => {
loginAsCustomer();
const myAccount = new MyAccountPage( driver, {
baseUrl: config.get( 'url' ),
visit: false
} );
myAccount.clickMenu( 'Addresses' );
assert.eventually.equal(
driver.getCurrentUrl().then( untrailingslashit ),
untrailingslashit( getMyAccountSubPageUrl( 'edit-address' ) )
);
assert.eventually.ok( myAccount.hasText( 'Addresses' ), 'see "Addresses" text' );
} );
test.it( 'allows customer to edit account details', () => {
loginAsCustomer();
const myAccount = new MyAccountPage( driver, {
baseUrl: config.get( 'url' ),
visit: false
} );
myAccount.clickMenu( 'Account details' );
assert.eventually.equal(
driver.getCurrentUrl().then( untrailingslashit ),
untrailingslashit( getMyAccountSubPageUrl( 'edit-account' ) )
);
assert.eventually.ok( myAccount.hasText( 'Account details' ), 'see "Account details" text' );
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,75 +0,0 @@
/**
* External dependencies
*/
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { SingleProductPage, CartPage } from 'wc-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
let manager;
let driver;
test.describe( 'Single Product Page', function() {
const visitProductByPath = path => {
return new SingleProductPage( driver, { url: manager.getPageUrl( path ) } );
};
const visitCart = () => {
return new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
};
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
test.it( 'should be able to add simple products to the cart', () => {
const productPage = visitProductByPath( '/product/t-shirt' );
productPage.setQuantity( 5 );
productPage.addToCart();
assert.eventually.equal( visitCart().hasItem( 'T-Shirt', { qty: 5 } ), true );
} );
test.it( 'should be able to add variation products to the cart', () => {
let variableProductPage;
variableProductPage = visitProductByPath( '/product/hoodie' );
variableProductPage.selectVariation( 'Color', 'Blue' );
variableProductPage.selectVariation( 'Logo', 'Yes' );
driver.sleep( 500 );
variableProductPage.addToCart();
assert.eventually.ok( visitCart().hasItem( 'Hoodie - Blue, Yes' ), '"Hoodie - Blue, Yes" in the cart' );
variableProductPage = visitProductByPath( '/product/hoodie' );
variableProductPage.selectVariation( 'Color', 'Green' );
variableProductPage.selectVariation( 'Logo', 'No' );
driver.sleep( 500 );
variableProductPage.addToCart();
assert.eventually.ok( visitCart().hasItem( 'Hoodie - Green, No' ), '"Hoodie - Green, No" in the cart' );
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,34 +0,0 @@
/**
* WordPress dependencies
*/
import { activatePlugin } from "@wordpress/e2e-test-utils";
/**
* activatePlugin( slug ) - Activates an installed plugin.
*
* @param {string} slug Plugin slug.
*
* Within the activatePlugin() function:
*
* 1) Switches the current user to the admin user (if the user
* running the test is not already the admin user).
*
* 2) Visits admin page; if user is not logged in then it logging in it first, then visits admin page.
*
* 3) Checks if plugin is activated. If not, activates the plugin.
*
* 4) Switches the current user to whichever user we should be
* running the tests as (if we're not already that user).
*/
describe( 'Can login and make sure WooCommerce plugin is activated', () => {
test( 'Can activate WooCommerce plugin if it is deactivated' , async () => {
try {
await activatePlugin( 'woocommerce' );
} catch ( error ) {
await activatePlugin( 'woocommerce' );
}
});
} );

View File

@ -0,0 +1,140 @@
/**
* @format
*/
/**
* External dependencies
*/
import { activatePlugin } from '@wordpress/e2e-test-utils';
/**
* Internal dependencies
*/
import { StoreOwnerFlow } from '../../utils/flows';
import { clickTab, uiUnblocked } from '../../utils';
const verifyPublishAndTrash = 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.' } );
// Trash product
await expect( page ).toClick( 'a', { text: 'Move to Trash' } );
await page.waitForSelector( '#message' );
// Verify
await expect( page ).toMatchElement( '.updated.notice', { text: '1 product moved to the Trash.' } );
};
describe( 'Add New Product Page', () => {
beforeAll( async () => {
await activatePlugin( 'woocommerce' );
} );
it( 'can create simple virtual product titled "Simple Product" with regular price $9.99', 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 expect( page ).toClick( '#_virtual' );
await clickTab( 'General' );
await expect( page ).toFill( '#_regular_price', '9.99' );
await verifyPublishAndTrash();
} );
it( 'can create product with variations', 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 verifyPublishAndTrash();
} );
} );

View File

@ -0,0 +1,17 @@
/**
* @format
*/
const baseUrl = process.env.WP_BASE_URL;
const WP_ADMIN_NEW_PRODUCT = baseUrl + '/wp-admin/post-new.php?post_type=product';
const StoreOwnerFlow = {
openNewProduct: async () => {
await page.goto( WP_ADMIN_NEW_PRODUCT, {
waitUntil: 'networkidle0',
} );
},
};
export { StoreOwnerFlow };

View File

@ -0,0 +1,26 @@
/**
* Internal dependencies
*/
const flows = require( './flows' );
/**
* Click a tab (on post type edit screen).
*
* @param {string} tabName Tab label.
*/
const clickTab = async ( tabName ) => {
await expect( page ).toClick( '.wc-tabs > li > a', { text: tabName } );
};
/**
* Wait for UI blocking to end.
*/
const uiUnblocked = async () => {
await page.waitForFunction( () => ! Boolean( document.querySelector( '.blockUI' ) ) );
};
module.exports = {
...flows,
clickTab,
uiUnblocked,
};

View File

@ -1,60 +0,0 @@
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { StoreOwnerFlow } from 'wc-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
let manager;
let driver;
test.describe( 'Add New Coupon Page', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
test.it( 'can create new coupon', () => {
const flowArgs = {
baseUrl: config.get( 'url' ),
username: config.get( 'users.admin.username' ),
password: config.get( 'users.admin.password' )
};
const storeOwner = new StoreOwnerFlow( driver, flowArgs );
const couponPage = storeOwner.openNewCoupon();
couponPage.setTitle( 'code-' + new Date().getTime().toString() );
couponPage.setDescription( 'test coupon' );
const couponData = couponPage.components.metaBoxCouponData;
const generalPanel = couponData.clickTab( 'General' );
generalPanel.selectDiscountType( 'Cart Discount' );
generalPanel.setCouponAmount( '100' );
couponPage.publish();
assert.eventually.ok( couponPage.hasNotice( 'Coupon updated.' ) );
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,61 +0,0 @@
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { StoreOwnerFlow } from 'wc-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
let manager;
let driver;
test.describe( 'Add New Order Page', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
test.it( 'can create new order', () => {
const flowArgs = {
baseUrl: config.get( 'url' ),
username: config.get( 'users.admin.username' ),
password: config.get( 'users.admin.password' )
};
const storeOwner = new StoreOwnerFlow( driver, flowArgs );
const orderPage = storeOwner.openNewOrder();
const orderData = orderPage.components.metaBoxOrderData;
orderData.selectOrderStatus( 'Processing' );
orderData.setOrderDate( '2016-12-13' );
orderData.setOrderDateHour( '18' );
orderData.setOrderDateMinute( '55' );
orderPage.components.metaBoxOrderActions.saveOrder();
assert.eventually.ok( orderData.hasOrderStatus( 'Processing' ) );
const orderNotes = orderPage.components.metaBoxOrderNotes;
assert.eventually.ok( orderNotes.hasNote( 'Order status changed from Pending payment to Processing.' ) );
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,138 +0,0 @@
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { WPLogin } from 'wp-e2e-page-objects';
import { WPAdminProductNew } from 'wc-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
let manager;
let driver;
test.describe( 'Add New Product Page', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
// login
test.before( () => {
const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } );
wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) );
} );
test.it( 'can create simple virtual product titled "Simple Product" with regular price $9.99', () => {
const product = new WPAdminProductNew( driver, { url: manager.getPageUrl( '/wp-admin/post-new.php?post_type=product' ) } );
product.setTitle( 'Simple Product' );
const productData = product.components.metaBoxProductData;
productData.selectProductType( 'Simple product' );
productData.checkVirtual();
const panelGeneral = productData.clickTab( 'General' );
panelGeneral.setRegularPrice( '9.99' );
product.publish();
assert.eventually.ok( product.hasNotice( 'Product published.' ) );
product.moveToTrash();
assert.eventually.ok( product.hasNotice( '1 product moved to the Trash.' ) );
} );
test.it( 'can create product with variations', () => {
const product = new WPAdminProductNew( driver, { url: manager.getPageUrl( '/wp-admin/post-new.php?post_type=product' ) } );
product.setTitle( 'Variable Product with Two Variations' );
const productData = product.components.metaBoxProductData;
productData.selectProductType( 'Variable product' );
const panelAttributes = productData.clickTab( 'Attributes' );
panelAttributes.selectAttribute( 'Custom product attribute' );
const attr1 = panelAttributes.add();
assert.eventually.ok( attr1.displayed() );
attr1.setName( 'attr #1' );
attr1.checkVisibleOnTheProductPage();
attr1.checkUsedForVariations();
attr1.setValue( 'val1 | val2' );
attr1.toggle();
const attr2 = panelAttributes.add();
assert.eventually.ok( attr2.displayed() );
attr2.setName( 'attr #2' );
attr2.checkVisibleOnTheProductPage();
attr2.checkUsedForVariations();
attr2.setValue( 'val1 | val2' );
const attr3 = panelAttributes.add();
assert.eventually.ok( attr3.displayed() );
attr3.setName( 'attr #3' );
attr3.checkVisibleOnTheProductPage();
attr3.checkUsedForVariations();
attr3.setValue( 'val1 | val2' );
attr3.toggle(); attr2.toggle();
panelAttributes.saveAttributes();
const panelVaritions = productData.clickTab( 'Variations' );
panelVaritions.selectAction( 'Create variations from all attributes' );
panelVaritions.go();
// We start at two because of a new message introduced at the top of the panel.
const var1 = panelVaritions.getRow( 2 );
var1.toggle();
var1.checkEnabled();
var1.checkVirtual();
var1.setRegularPrice( '9.99' );
const var2 = panelVaritions.getRow( 3 );
var2.toggle();
var2.checkEnabled();
var2.checkVirtual();
var2.setRegularPrice( '11.99' );
const var3 = panelVaritions.getRow( 4 );
var3.toggle();
var3.checkEnabled();
var3.checkManageStock();
var3.setRegularPrice( '20' );
var3.setWeight( '200' );
var3.setDimensionLength( '10' );
var3.setDimensionWidth( '20' );
var3.setDimensionHeight( '15' );
panelVaritions.saveChanges();
helper.scrollUp( driver );
helper.scrollUp( driver );
helper.scrollUp( driver );
product.publish();
assert.eventually.ok( product.hasNotice( 'Product published.' ) );
product.moveToTrash();
assert.eventually.ok( product.hasNotice( '1 product moved to the Trash.' ) );
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,80 +0,0 @@
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { WPLogin } from 'wp-e2e-page-objects';
import { WPAdminWCSettingsGeneral } from 'wc-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
let manager;
let driver;
test.describe( 'WooCommerce General Settings', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
// login
test.before( () => {
const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } );
wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) );
} );
test.it( 'can update settings', () => {
const settingsArgs = { url: manager.getPageUrl( '/wp-admin/admin.php?page=wc-settings&tab=general' ) };
const settings = new WPAdminWCSettingsGeneral( driver, settingsArgs );
assert.eventually.ok( settings.hasActiveTab( 'General' ) );
// Set selling location to all countries first, so we can choose california
// as base location.
settings.selectSellingLocation( 'Sell to all countries' );
settings.saveChanges();
assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) );
// Set base location with state CA.
settings.selectBaseLocation( 'california', 'United States (US) — California' );
settings.saveChanges();
assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) );
// Set selling location to specific countries first, so we can choose
// U.S as base location (without state). This will makes specific
// countries option appears.
settings.selectSellingLocation( 'Sell to specific countries' );
settings.removeChoiceInSellToSpecificCountries( 'United States (US)' );
settings.setSellToSpecificCountries( 'united states', 'United States (US)' );
settings.saveChanges();
assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) );
// Set currency options.
settings.setThousandSeparator( ',' );
settings.setDecimalSeparator( '.' );
settings.setNumberOfDecimals( '2' );
settings.saveChanges();
assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) );
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,65 +0,0 @@
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { WPLogin } from 'wp-e2e-page-objects';
import { WPAdminWCSettingsProductsDownloadable } from 'wc-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
let manager;
let driver;
test.describe( 'WooCommerce Products > Downloadable Products Settings', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
// login
test.before( () => {
const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } );
wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) );
} );
test.it( 'can update settings', () => {
const settingsArgs = { url: manager.getPageUrl( '/wp-admin/admin.php?page=wc-settings&tab=products&section=downloadable' ) };
const settings = new WPAdminWCSettingsProductsDownloadable( driver, settingsArgs );
assert.eventually.ok( settings.hasActiveTab( 'Products' ) );
assert.eventually.ok( settings.hasActiveSubTab( 'Downloadable products' ) );
settings.selectFileDownloadMethod( 'Redirect only' );
settings.checkDownloadsRequireLogin();
settings.checkGrantAccessAfterPayment();
settings.saveChanges();
assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) );
settings.selectFileDownloadMethod( 'Force downloads' );
settings.uncheckDownloadsRequireLogin();
settings.uncheckGrantAccessAfterPayment();
settings.saveChanges();
assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) );
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,109 +0,0 @@
import config from 'config';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import test from 'selenium-webdriver/testing';
import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
import { WPLogin } from 'wp-e2e-page-objects';
import { WPAdminWCSettingsTax, WPAdminWCSettingsTaxRates } from 'wc-e2e-page-objects';
chai.use( chaiAsPromised );
const assert = chai.assert;
let manager;
let driver;
test.describe( 'WooCommerce Tax Settings', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
driver = manager.getDriver();
helper.clearCookiesAndDeleteLocalStorage( driver );
} );
this.timeout( config.get( 'mochaTimeoutMs' ) );
// login
test.before( () => {
const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } );
wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) );
} );
test.it( 'can set tax options', () => {
const settingsArgs = { url: manager.getPageUrl( '/wp-admin/admin.php?page=wc-settings&tab=tax' ) };
const settings = new WPAdminWCSettingsTax( driver, settingsArgs );
assert.eventually.ok( settings.hasActiveTab( 'Tax' ) );
settings.selectPricesEnteredWithNoTax();
settings.selectCalculateTaxBasedOn( 'Customer shipping address' );
settings.selectShippingTaxClass( 'Standard' );
settings.uncheckRounding();
settings.selectDisplayPricesInTheShop( 'Excluding tax' );
settings.selectDisplayPricesDuringCartAndCheckout( 'Including tax' );
settings.selectDisplayTaxTotals( 'As a single total' );
settings.saveChanges();
assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) );
} );
test.it( 'can add tax classes', () => {
const settingsArgs = { url: manager.getPageUrl( '/wp-admin/admin.php?page=wc-settings&tab=tax' ) };
const settings = new WPAdminWCSettingsTax( driver, settingsArgs );
settings.removeAdditionalTaxClasses();
settings.saveChanges();
settings.addAdditionalTaxClass( 'Fancy' );
settings.saveChanges();
assert.eventually.ok( settings.hasSubTab( 'Fancy rates' ) );
} );
test.it( 'can set rate settings', () => {
const settingsArgs = { url: manager.getPageUrl( '/wp-admin/admin.php?page=wc-settings&tab=tax&section=fancy' ) };
const settings = new WPAdminWCSettingsTaxRates( driver, settingsArgs );
settings.insertRow();
settings.setCountryCode( 1, 'US' );
settings.setStateCode( 1, 'CA' );
settings.setRate( 1, '7.5' );
settings.setTaxName( 1, 'CA State Tax' );
settings.insertRow();
settings.setCountryCode( 2, 'US' );
settings.setRate( 2, '1.5' );
settings.setPriority( 2, '2' );
settings.setTaxName( 2, 'Federal Tax' );
settings.uncheckShipping( 2 );
settings.saveChanges();
settings.removeRow( 2 );
settings.saveChanges();
assert.eventually.ifError( helper.isEventuallyPresentAndDisplayed( driver, settings.getSelector( 2 ), 1000 ) );
} );
test.it( 'can remove tax classes', () => {
const settingsArgs = { url: manager.getPageUrl( '/wp-admin/admin.php?page=wc-settings&tab=tax' ) };
const settings = new WPAdminWCSettingsTax( driver, settingsArgs );
settings.removeAdditionalTaxClass( 'Fancy' );
settings.saveChanges();
assert.eventually.ifError( settings.hasSubTab( 'Fancy rates' ) );
} );
// take screenshot
test.afterEach( function() {
if ( this.currentTest.state === 'failed' ) {
helper.takeScreenshot( manager, this.currentTest );
}
} );
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -1,3 +0,0 @@
{
"url": "BASE_URL"
}

View File

@ -1,3 +0,0 @@
{
"url": "https://example.com/"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

View File

@ -1,14 +0,0 @@
const path = require('path');
const config = require('config');
const baseUrl = config.get('url');
describe('woocommerce screenshot tests', () => {
it('test my account page', async () => {
await page.goto(baseUrl+'/my-account/');
const imagePath = path.resolve(__dirname, './master-screenshots', 'my-account-logged-out.png');
const image = await page.screenshot({path: imagePath});
expect(image).toMatchImageSnapshot();
});
});