Skip to content

Commit

Permalink
Merge pull request #13397 from woocommerce/e2e-testing
Browse files Browse the repository at this point in the history
E2E frontend testing
  • Loading branch information
mikejolley committed Mar 30, 2017
2 parents c83e725 + 2cb861b commit d79b1ed
Show file tree
Hide file tree
Showing 13 changed files with 687 additions and 2 deletions.
9 changes: 9 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"presets": [
"es2015",
"stage-2"
],
"plugins": [
"add-module-exports"
]
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ tests/cli/vendor
# Unit tests
/tmp
/tests/bin/tmp
/tests/e2e-tests/config/local-*.json

# Logs
/logs
Expand Down
14 changes: 14 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,12 @@ module.exports = function( grunt ) {
'cd apigen',
'php hook-docs.php'
].join( '&&' )
},
e2e_test: {
command: 'npm run --silent test:single tests/e2e-tests/' + grunt.option( 'file' )
},
e2e_tests: {
command: 'npm run --silent test'
}
},

Expand Down Expand Up @@ -325,4 +331,12 @@ module.exports = function( grunt ) {
'default',
'makepot'
]);

grunt.registerTask( 'e2e-tests', [
'shell:e2e_tests'
]);

grunt.registerTask( 'e2e-test', [
'shell:e2e_test'
]);
};
22 changes: 20 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
},
"license": "GPL-3.0+",
"main": "Gruntfile.js",
"scripts": {
"test": "cross-env NODE_CONFIG_DIR='./tests/e2e-tests/config' BABEL_ENV=commonjs mocha \"tests/e2e-tests\" --compilers js:babel-register --recursive",
"test:single": "cross-env NODE_CONFIG_DIR='./tests/e2e-tests/config' BABEL_ENV=commonjs mocha --compilers js:babel-register"
},
"devDependencies": {
"grunt": "~1.0.1",
"grunt-checktextdomain": "~1.0.0",
Expand All @@ -24,10 +28,24 @@
"grunt-wp-i18n": "~0.5.4",
"grunt-rtlcss": "2.0.1",
"grunt-contrib-concat": "1.0.1",
"node-bourbon": "~4.2.3"
"node-bourbon": "~4.2.3",
"config": "^1.24.0",
"babel": "^6.5.2",
"babel-cli": "^6.14.0",
"babel-eslint": "^7.0.0",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-preset-es2015": "^6.14.0",
"babel-preset-stage-2": "^6.13.0",
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
"cross-env": "^3.0.0",
"istanbul": "^1.0.0-alpha",
"mocha": "^3.0.2",
"chromedriver": "^2.25.0",
"wc-e2e-page-objects": "0.2.2"
},
"engines": {
"node": ">=0.8.0",
"node": ">=6.9.4",
"npm": ">=1.1.0"
}
}
110 changes: 110 additions & 0 deletions tests/e2e-tests/cart-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
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() {
test.before( 'open browser', 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( 'Flying Ninja' ), true );
assert.eventually.equal( shopPage.addProductToCart( 'Happy Ninja' ), true );

const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
assert.eventually.equal( cartPage.hasItem( 'Flying Ninja' ), true );
assert.eventually.equal( cartPage.hasItem( 'Happy Ninja' ), 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( 'Flying Ninja' ), true );

const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
assert.eventually.equal( cartPage.hasItem( 'Flying Ninja', { qty: 2 } ), true );
assert.eventually.equal( cartPage.hasItem( 'Happy Ninja', { qty: 1 } ), true );
} );

test.it( 'should updates qty when updated via qty input', () => {
const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
cartPage.getItem( 'Flying Ninja', { qty: 2 } ).setQty( 4 );
cartPage.update();
cartPage.getItem( 'Happy Ninja', { qty: 1 } ).setQty( 3 );
cartPage.update();

assert.eventually.equal( cartPage.hasItem( 'Flying Ninja', { qty: 4 } ), true );
assert.eventually.equal( cartPage.hasItem( 'Happy Ninja', { 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( 'Flying Ninja', { qty: 4 } ).remove();
cartPage.getItem( 'Happy Ninja', { 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( 'Flying Ninja' ), true );

const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
assert.eventually.equal(
cartPage.hasItem( 'Flying Ninja', { qty: 1 } ),
true,
'Cart item "Flying Ninja" with qty 1 is not displayed'
);

assert.eventually.equal(
cartPage.hasSubtotal( '12.00' ),
true,
'Cart totals does not display subtotal of 12.00'
);

cartPage.getItem( 'Flying Ninja', { qty: 1 } ).setQty( 2 );
cartPage.update();

assert.eventually.equal(
cartPage.hasSubtotal( '24.00' ),
true,
'Cart totals does not display subtotal of 24.00'
);
} );

test.it( 'should go to the checkout page when "Proceed to Chcekout" 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'
);
} );

test.after( 'quit browser', () => {
manager.quitBrowser();
} );
} );
154 changes: 154 additions & 0 deletions tests/e2e-tests/checkout-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
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() {
test.before( 'open browser', 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 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( 'Flying Ninja', 'Happy Ninja' );

const checkoutPage = guest.openCheckout();
assert.eventually.ok( Helper.waitTillUIBlockNotPresent( driver ) );

const orderReview = checkoutPage.components.orderReview;
assertOrderItem( orderReview, 'Flying Ninja', { qty: '1', total: '$12.00' } );
assertOrderItem( orderReview, 'Happy Ninja', { qty: '1', total: '$18.00' } );
assert.eventually.ok( orderReview.hasSubtotal( '$30.00' ), 'Could not find subtotal $30.00' );
} );

test.it( 'allows customer to choose available payment methods', () => {
const guest = new GuestCustomerFlow( driver, { baseUrl: config.get( 'url' ) } );
guest.fromShopAddProductsToCart( 'Flying Ninja', 'Happy Ninja' );

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( 'Flying Ninja', 'Happy Ninja' );

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( 'Flying Ninja', 'Happy Ninja' );

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( 'Flying Ninja', 'Happy Ninja' );

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' );
checkoutPage.selectPaymentMethod( 'Cash on delivery' );
checkoutPage.placeOrder();
Helper.waitTillUIBlockNotPresent( driver );

const orderReceivedPage = new CheckoutOrderReceivedPage( driver, { visit: false } );

assert.eventually.ok(
orderReceivedPage.hasText( 'Order received' )
);
} );

test.after( 'quit browser', () => {
manager.quitBrowser();
} );
} );
15 changes: 15 additions & 0 deletions tests/e2e-tests/config/default.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"url": "http://example.com",
"users": {
"admin": {
"username": "",
"password": ""
},
"customer": {
"username": "",
"password": ""
}
},
"startBrowserTimeoutMs": 30000,
"mochaTimeoutMs": 120000
}
9 changes: 9 additions & 0 deletions tests/e2e-tests/config/local-sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"url": "http://local.wordpress.dev/",
"users": {
"admin": {
"username": "admin",
"password": "password"
}
}
}
Loading

0 comments on commit d79b1ed

Please sign in to comment.