Autoplay



Transcripted Summary

# End to End Test with Page Model

Inside our test folder, we can create a new file and rename it E2ETest.js.

Inside this test, we will start by:

  1. Opening the web application

  2. Click on Register

  3. Create a new account

  4. Searching about the product, for example, Apple Mac Pro

  5. Go to the product details then change the quantity or the product in the cart

  6. Add to cart

  7. Go to the shopping cart

  8. Click on the checkout

  9. Continue with completing this form for placing order

  10. Verify that order is placed successfully


import { ClientFunction } from 'testcafe';
import homepage from '../pages/HomePage';
import registerpage from '../pages/RegisterPage';
import searchresults from '../pages/SearchResultPage'
import productdetails from '../pages/ProductDetailsPage'
import cartpage from '../pages/CartPage'
import checkoutpage from '../pages/CheckoutPage'
import myorderpage from '../pages/MyOrdersPage'

const URL = 'https://demo.nopcommerce.com/';
const getURL = ClientFunction(() => window.location.href);
var randomNumber = Math.floor(Math.random() * 10000);
var userEmail = 'moataz'+randomNumber+'@nabil.com';

fixture `E2E Fixture`
    .page(URL);
 
test('Assert home page', async t => {
    await t
    .expect(getURL()).eql(URL)
    .takeScreenshot()
    .expect(homepage.subtitleHeader.exists).ok()
});

test("Place Order E2E Tests", async (t) => {
    await t
    .maximizeWindow()
    .click(homepage.RegisterLink)
    .expect(getURL()).contains('register')
    .click(registerpage.GenderOption)
    .typeText(registerpage.FirstName,'Moataz')
    .typeText(registerpage.LastName,'Nabil')
    .typeText(registerpage.Email,userEmail)
    .typeText(registerpage.Password,'123456')
    .typeText(registerpage.ConfirmPassword,'123456')
    .click(registerpage.RegisterButton)
    .expect(registerpage.SuccessfullMessage.exists).ok();

In our end to end test, I just add import ClientFunction because we need to continue with verifying the ClientFunction or the window.location or the current URL contains the correct URL.

And we imported all the page object classes that we need. For example, homepage, registerpage, searchresults, productdetails, cartpage, checkoutpage, and myorderpage.

Here we have also the random number for adding it to the userEmail.

We have a fixture - E2E Fixture and inside the fixture, we have the first test to assert the homepage is displayed.

Also, we are taking a screenshot.

Then we are placing the order, but we will start by maximizing the window and then clicking on the register link and insert all the data for registration.

Then after the registration, we can start searching for the products from the search bar.

Here we can add await and we can add homepage.search(), and with the search, we need to add the product as a parameter.

So the product will be, for example, we will select Apple, and also we can select the product that we need to add from the search bar.

We can get the title of the product "Apple MacBook Pro 13-inch" and this is the text for the search().

Then we need to add a semicolon after this line and on the previous line.

After that, we can add await again with t. We can just start to continue with this one.

For continuing with this step, we need to add one additional page object.

In our case, if we copy this product name and go to the website and paste it in the search box and click enter - this is our scenario.

Here we have our search result. In the search result, we need to verify that this product is displayed and then we need to click on the product name.

So we need to add one additional page object for the search result.

In our project, we need to go to the pages, and after that, we can add SearchResultPage.js.


import { Selector } from 'testcafe';

class SearchResultPage {
    
constructor(){
    this.productItem = Selector('div.product-item')
    this.productTitle = Selector('a').withText('Apple MacBook Pro 13-inch')
  }
}

export default new SearchResultPage();

Inside this page, we have two elements.

We have the product item. We need to verify that the product item is displayed and also, we can click on the product name to go to the product details.

Then, here we can add this part - import Selector and we have two elements.

productItem, which is a div.product-item and we need to expect or to verify that it is displayed.

And after that, productTitle with a and including Apple MacBook Pro 13-inch - this is the text for that product.

Then we can go back to our test.

Under await we can just click() on the searchresults.productTitle - we have already the SearchResultPage imported here, so from the search result, we need to verify the productTitle.

So we need to click on the product title, and after that we can .expect() - we can verify that getURL - and this is a method - .contains() the product name 'apple-macbook-pro-13-inch.


import { ClientFunction } from 'testcafe';
import homepage from '../pages/HomePage';
import registerpage from '../pages/RegisterPage';
import searchresults from '../pages/SearchResultPage'
import productdetails from '../pages/ProductDetailsPage'
import cartpage from '../pages/CartPage'
import checkoutpage from '../pages/CheckoutPage'
import myorderpage from '../pages/MyOrdersPage'

const URL = 'https://demo.nopcommerce.com/';
const getURL = ClientFunction(() => window.location.href);
var randomNumber = Math.floor(Math.random() * 10000);
var userEmail = 'moataz'+randomNumber+'@nabil.com';

fixture`E2E Fixture`
    .page(URL);
 
test('Assert home page', async t => {
    await t
    .expect(getURL()).eql(URL)
    .takeScreenshot()
    .expect(homepage.subtitleHeader.exists).ok()
});

test("Place Order E2E Tests", async (t) => {
    await t
    .maximizeWindow()
    .click(homepage.RegisterLink)
    .expect(getURL()).contains('register')
    .click(registerpage.GenderOption)
    .typeText(registerpage.FirstName,'Moataz')
    .typeText(registerpage.LastName,'Nabil')
    .typeText(registerpage.Email,userEmail)
    .typeText(registerpage.Password,'123456')
    .typeText(registerpage.ConfirmPassword,'123456')
    .click(registerpage.RegisterButton)
    .expect(registerpage.SuccessfullMessage.exists).ok();
    await homepage.search('Apple MacBook Pro 13-inch');
    await t
    .click(searchresults.productTitle)
    .expect(getURL()).contains('apple-macbook-pro-13-inch')
});

After that, we can continue to verify that the product price is displayed, and then we can change the quantity and add it to the cart.


import { ClientFunction } from 'testcafe';
import homepage from '../pages/HomePage';
import registerpage from '../pages/RegisterPage';
import searchresults from '../pages/SearchResultPage'
import productdetails from '../pages/ProductDetailsPage'
import cartpage from '../pages/CartPage'
import checkoutpage from '../pages/CheckoutPage'
import myorderpage from '../pages/MyOrdersPage'

const URL = 'https://demo.nopcommerce.com/';
const getURL = ClientFunction(() => window.location.href);
var randomNumber = Math.floor(Math.random() * 10000);
var userEmail = 'moataz'+randomNumber+'@nabil.com';

fixture`E2E Fixture`
    .page(URL);
 
test('Assert home page', async t => {
    await t
    .expect(getURL()).eql(URL)
    .takeScreenshot()
    .expect(homepage.subtitleHeader.exists).ok()
});

test("Place Order E2E Tests", async (t) => {
    await t
    .maximizeWindow()
    .click(homepage.RegisterLink)
    .expect(getURL()).contains('register')
    .click(registerpage.GenderOption)
    .typeText(registerpage.FirstName,'Moataz')
    .typeText(registerpage.LastName,'Nabil')
    .typeText(registerpage.Email,userEmail)
    .typeText(registerpage.Password,'123456')
    .typeText(registerpage.ConfirmPassword,'123456')
    .click(registerpage.RegisterButton)
    .expect(registerpage.SuccessfullMessage.exists).ok();
    await homepage.search('Apple MacBook Pro 13-inch');
    await t
    .click(searchresults.productTitle)
    .expect(getURL()).contains('apple-macbook-pro-13-inch')
    .expect(productdetails.productPrice.exists).ok()
    .selectText(productdetails.prductQuantity).pressKey("delete")
    .typeText(productdetails.prductQuantity,'3')
    .click(productdetails.addToCart)
    .expect(productdetails.successMessage.exists).ok()
    .wait(3000)
});

After we click on the product title, now we are in the ProductDetailsPage.

So we are expecting that the productdetails.productPrice.exists with the value because here we add the value as a hard-coded value in ProductDetailsPage with withText().

And after that, we can selectText - for example - productdetails.prductQuantity and the .pressKey("delete") - so here we need to delete the value.

Here, by default, it adds 2, because this is the product minimum quantity, but we need to delete this one - so we need to click the delete button.

After that, we can add our quantity. So in our case, we will add 3.

So, we need to delete first and after that, we can add 3 as a quantity, and then .click() on productdetails.addToCart.

Then .expect() the success message or the notification is displayed and we need to wait until it's not displayed, and then after that, we can click on the shopping cart and then go to the checkout page.


import { ClientFunction } from 'testcafe';
import homepage from '../pages/HomePage';
import registerpage from '../pages/RegisterPage';
import searchresults from '../pages/SearchResultPage'
import productdetails from '../pages/ProductDetailsPage'
import cartpage from '../pages/CartPage'
import checkoutpage from '../pages/CheckoutPage'
import myorderpage from '../pages/MyOrdersPage'

const URL = 'https://demo.nopcommerce.com/';
const getURL = ClientFunction(() => window.location.href);
var randomNumber = Math.floor(Math.random() * 10000);
var userEmail = 'moataz'+randomNumber+'@nabil.com';

fixture`E2E Fixture`
    .page(URL);
 
test('Assert home page', async t => {
    await t
    .expect(getURL()).eql(URL)
    .takeScreenshot()
    .expect(homepage.subtitleHeader.exists).ok()
});

test("Place Order E2E Tests", async (t) => {
    await t
    .maximizeWindow()
    .click(homepage.RegisterLink)
    .expect(getURL()).contains('register')
    .click(registerpage.GenderOption)
    .typeText(registerpage.FirstName,'Moataz')
    .typeText(registerpage.LastName,'Nabil')
    .typeText(registerpage.Email,userEmail)
    .typeText(registerpage.Password,'123456')
    .typeText(registerpage.ConfirmPassword,'123456')
    .click(registerpage.RegisterButton)
    .expect(registerpage.SuccessfullMessage.exists).ok();
    await homepage.search('Apple MacBook Pro 13-inch');
    await t
    .click(searchresults.productTitle)
    .expect(getURL()).contains('apple-macbook-pro-13-inch')
    .expect(productdetails.productPrice.exists).ok()
    .selectText(productdetails.prductQuantity).pressKey("delete")
    .typeText(productdetails.prductQuantity,'3')
    .click(productdetails.addToCart)
    .expect(productdetails.successMessage.exists).ok()
    .wait(3000)
    .click(homepage.CartLink)
    .click(cartpage.termsLabel)
    .click(cartpage.checkoutBtn)
    .expect(getURL()).contains('checkout');
});

After that, we .click() on the CartLink, then we are accepting the termsLabel, because for example, if we click on "Add to cart", then we wait for the notification to disappear, and then we can go to the "Shopping cart", and to continue with the checkout, we need to just check or click on the "I agree" checkbox.

So here we are, .click() on the termsLabel, and then click on the checkoutBtn.

Then, we are asserting that the current URL contains "checkout".

After that, we will continue with the cart - so here we can click on the "Checkout", then we need to fill out our data.

For example, if you go to "Checkout as a guest", we need to fill all the data like the billing address, shipping address, payment method, payment information, and confirm the order.

So the next step is that we need to fill this from the page object class.

Because we're already using the registered account, we don't need to go with the guest checkout.


import { ClientFunction } from 'testcafe';
import homepage from '../pages/HomePage';
import registerpage from '../pages/RegisterPage';
import searchresults from '../pages/SearchResultPage'
import productdetails from '../pages/ProductDetailsPage'
import cartpage from '../pages/CartPage'
import checkoutpage from '../pages/CheckoutPage'
import myorderpage from '../pages/MyOrdersPage'

const URL = 'https://demo.nopcommerce.com/';
const getURL = ClientFunction(() => window.location.href);
var randomNumber = Math.floor(Math.random() * 10000);
var userEmail = 'moataz'+randomNumber+'@nabil.com';

fixture`E2E Fixture`
    .page(URL);
 
test('Assert home page', async t => {
    await t
    .expect(getURL()).eql(URL)
    .takeScreenshot()
    .expect(homepage.subtitleHeader.exists).ok()
});

test("Place Order E2E Tests", async (t) => {
    await t
    .maximizeWindow()
    .click(homepage.RegisterLink)
    .expect(getURL()).contains('register')
    .click(registerpage.GenderOption)
    .typeText(registerpage.FirstName,'Moataz')
    .typeText(registerpage.LastName,'Nabil')
    .typeText(registerpage.Email,userEmail)
    .typeText(registerpage.Password,'123456')
    .typeText(registerpage.ConfirmPassword,'123456')
    .click(registerpage.RegisterButton)
    .expect(registerpage.SuccessfullMessage.exists).ok();
    await homepage.search('Apple MacBook Pro 13-inch');
    await t
    .click(searchresults.productTitle)
    .expect(getURL()).contains('apple-macbook-pro-13-inch')
    .expect(productdetails.productPrice.exists).ok()
    .selectText(productdetails.prductQuantity).pressKey("delete")
    .typeText(productdetails.prductQuantity,'3')
    .click(productdetails.addToCart)
    .expect(productdetails.successMessage.exists).ok()
    .wait(3000)
    .click(homepage.CartLink)
    .click(cartpage.termsLabel)
    .click(cartpage.checkoutBtn)
    .expect(getURL()).contains('checkout');
    await checkoutpage.selectCountry('Germany');
    await t
        .takeScreenshot()
        .typeText(checkoutpage.cityTxt,'Berlin')
        .typeText(checkoutpage.addressTxt,'108 ddd test')
        .typeText(checkoutpage.zipTxt,'123456')
        .typeText(checkoutpage.phoneTxt,'332434345')
        .click(checkoutpage.continueBtn)
        .click(checkoutpage.nextDayOption)
        .click(checkoutpage.nextShippingBtn)
        .click(checkoutpage.nextPaymentBtn)
        .click(checkoutpage.nextConfirmBtn)
        .click(checkoutpage.confirmOrderBtn)
        .expect(checkoutpage.orderConfirmationMessage.exists).ok()
        .click(checkoutpage.viewOrderDetailsLink)
});

Here we are selecting the country - "Germany" from the dropdown list.

After that, we are taking a screenshot just to verify that we are on the correct page.

Then we are adding the cityTxt, addressTxt, zipTxt, phoneTxt, and click on the "Continue" button,

Then click on the nextDayOption, nextShippingBtn, nextPaymentBtn, nextConfirmBtn.

And after that, we are clicking the confirmOrderBtn just to place the order.

And then expect that the order confirmation message is displayed or exists and contains "Your order has been successfully processed!".

After that, we are clicking on viewOrderDetailsLink view order details, which contains the text "Click here for order details".

Then after that, we need to click on "My account" and go to "My orders" and then check that the order is displayed there.


import { ClientFunction } from 'testcafe';
import homepage from '../pages/HomePage';
import registerpage from '../pages/RegisterPage';
import searchresults from '../pages/SearchResultPage'
import productdetails from '../pages/ProductDetailsPage'
import cartpage from '../pages/CartPage'
import checkoutpage from '../pages/CheckoutPage'
import myorderpage from '../pages/MyOrdersPage'

const URL = 'https://demo.nopcommerce.com/';
const getURL = ClientFunction(() => window.location.href);
var randomNumber = Math.floor(Math.random() * 10000);
var userEmail = 'moataz'+randomNumber+'@nabil.com';

fixture`E2E Fixture`
    .page(URL);
 
test('Assert home page', async t => {
    await t
    .expect(getURL()).eql(URL)
    .takeScreenshot()
    .expect(homepage.subtitleHeader.exists).ok()
});

test("Place Order E2E Tests", async (t) => {
    await t
    .maximizeWindow()
    .click(homepage.RegisterLink)
    .expect(getURL()).contains('register')
    .click(registerpage.GenderOption)
    .typeText(registerpage.FirstName,'Moataz')
    .typeText(registerpage.LastName,'Nabil')
    .typeText(registerpage.Email,userEmail)
    .typeText(registerpage.Password,'123456')
    .typeText(registerpage.ConfirmPassword,'123456')
    .click(registerpage.RegisterButton)
    .expect(registerpage.SuccessfullMessage.exists).ok();
    await homepage.search('Apple MacBook Pro 13-inch');
    await t
    .click(searchresults.productTitle)
    .expect(getURL()).contains('apple-macbook-pro-13-inch')
    .expect(productdetails.productPrice.exists).ok()
    .selectText(productdetails.prductQuantity).pressKey("delete")
    .typeText(productdetails.prductQuantity,'3')
    .click(productdetails.addToCart)
    .expect(productdetails.successMessage.exists).ok()
    .wait(3000)
    .click(homepage.CartLink)
    .click(cartpage.termsLabel)
    .click(cartpage.checkoutBtn)
    .expect(getURL()).contains('checkout');
    await checkoutpage.selectCountry('Germany');
    await t
        .takeScreenshot()
        .typeText(checkoutpage.cityTxt,'Berlin')
        .typeText(checkoutpage.addressTxt,'108 ddd test')
        .typeText(checkoutpage.zipTxt,'123456')
        .typeText(checkoutpage.phoneTxt,'332434345')
        .click(checkoutpage.continueBtn)
        .click(checkoutpage.nextDayOption)
        .click(checkoutpage.nextShippingBtn)
        .click(checkoutpage.nextPaymentBtn)
        .click(checkoutpage.nextConfirmBtn)
        .click(checkoutpage.confirmOrderBtn)
        .expect(checkoutpage.orderConfirmationMessage.exists).ok()
        .click(checkoutpage.viewOrderDetailsLink)
        .click(homepage.MyAccountLink)
        .click(myorderpage.orders);
});

So we just added two more steps with homepage.MyAccountLink - just to .click() on "My account" and then click on "My orders".

In "My orders", we can verify that the order is displayed, or we can add any data or any steps that we can confirm that the test or the end to end scenario is covered now with TestCafe and the page object.

We still have one test remaining - we need to change the currency on our website.

We will add the 'Change Currency Test', and then we can continue with our test.

So here, we just need to add await and from homepage.changeCurrency, and here we need to pass the currency as a parameter and we can change it to 'Euro'.

And after that maybe we can add one step to take a screenshot just to check that the currency has changed or we can just check any item and then change it with this current value.


import { ClientFunction } from 'testcafe';
import homepage from '../pages/HomePage';
import registerpage from '../pages/RegisterPage';
import searchresults from '../pages/SearchResultPage'
import productdetails from '../pages/ProductDetailsPage'
import cartpage from '../pages/CartPage'
import checkoutpage from '../pages/CheckoutPage'
import myorderpage from '../pages/MyOrdersPage'

const URL = 'https://demo.nopcommerce.com/';
const getURL = ClientFunction(() => window.location.href);
var randomNumber = Math.floor(Math.random() * 10000);
var userEmail = 'moataz'+randomNumber+'@nabil.com';

fixture`E2E Fixture`
    .page(URL);
 
test('Assert home page', async t => {
    await t
    .expect(getURL()).eql(URL)
    .takeScreenshot()
    .expect(homepage.subtitleHeader.exists).ok()
});

test("Place Order E2E Tests", async (t) => {
    await t
    .maximizeWindow()
    .click(homepage.RegisterLink)
    .expect(getURL()).contains('register')
    .click(registerpage.GenderOption)
    .typeText(registerpage.FirstName,'Moataz')
    .typeText(registerpage.LastName,'Nabil')
    .typeText(registerpage.Email,userEmail)
    .typeText(registerpage.Password,'123456')
    .typeText(registerpage.ConfirmPassword,'123456')
    .click(registerpage.RegisterButton)
    .expect(registerpage.SuccessfullMessage.exists).ok();
    await homepage.search('Apple MacBook Pro 13-inch');
    await t
    .click(searchresults.productTitle)
    .expect(getURL()).contains('apple-macbook-pro-13-inch')
    .expect(productdetails.productPrice.exists).ok()
    .selectText(productdetails.prductQuantity).pressKey("delete")
    .typeText(productdetails.prductQuantity,'3')
    .click(productdetails.addToCart)
    .expect(productdetails.successMessage.exists).ok()
    .wait(3000)
    .click(homepage.CartLink)
    .click(cartpage.termsLabel)
    .click(cartpage.checkoutBtn)
    .expect(getURL()).contains('checkout');
    await checkoutpage.selectCountry('Germany');
    await t
        .takeScreenshot()
        .typeText(checkoutpage.cityTxt,'Berlin')
        .typeText(checkoutpage.addressTxt,'108 ddd test')
        .typeText(checkoutpage.zipTxt,'123456')
        .typeText(checkoutpage.phoneTxt,'332434345')
        .click(checkoutpage.continueBtn)
        .click(checkoutpage.nextDayOption)
        .click(checkoutpage.nextShippingBtn)
        .click(checkoutpage.nextPaymentBtn)
        .click(checkoutpage.nextConfirmBtn)
        .click(checkoutpage.confirmOrderBtn)
        .expect(checkoutpage.orderConfirmationMessage.exists).ok()
        .click(checkoutpage.viewOrderDetailsLink)
        .click(homepage.MyAccountLink)
        .click(myorderpage.orders);
});

test("Change Currency Test", async (t) => {
    await homepage.changeCurrency('Euro')
});

So now it's time to run our tests and to check what happened during our scenario.

From the command line, we can run:


testcafe chrome test/E2ETest.js

We can run all tests with just test, or we can just specify that we need to run the E2ETest.

So we will click "Enter" and TestCafe will run the server and run our test and we will check the results - if we have any problem we can fix, or our tests will run successfully.

Here, we'll maximize the windows, then click on that register test.

After that, we search about the product, click enter, go to the product, or the search results.

Go to the product details, remove the values from the quantity textbox, and then click add to cart.

Then we are waiting here until this notification is not displayed or dimmed.

Then click on the Shopping cart, click on the agree checkbox, then fill the data.

Here we are filling in the city... click on Continue, select the Payment method, Payment information, and then click the Confirm button.

Then we click on the view order details - go to My account, click my Orders, and also change currency - is passed.

So here we have three test cases and also we have screenshots.

So we can just verify that the first test is running successfully, and the second one also - here we are in the place order screen, so we can confirm that we are on the correct page.



Now, after we finish our implementation, we will find that we covered all the test cases that we added at the beginning:

  • User registration

  • User login

  • Change currency

  • Search for product

  • Add the product to cart

  • Checkout with the registered user

  • Place an order



Resources



Quiz

The quiz for this chapter can be found in 7.7