Breaking News

Automate Amazon: Initializing Login and Cart

This post is sixth of a series of nine. Need to go back to the beginning?

While drafting the tests to handle adding products to the shopping cart, I came across two problems:

  • I kept on on finding that I was logged into my personal Amazon.com account instead of the test account. 
  • From one session to the next, Amazon kept remembering what I had in my shopping cart the test before. 
Before the test is run, we need to initialize the login session, and clear all items found in the cart.


Please Note:  Using the GUI is the WORST possible way to initialize the cart or the login. It is far better to use some behind-the-scenes method the automated test could call in the @BeforeClass method to be used during setup of the test.

We are writing this functionality this way only because I can't think of any other way besides do it how I have outlined. Have a better way? Thoughts? Please add to the comments.

I haven't been an automated tester for long. Feel free to give me pointers!

What our Directory Structure Will Look Like


For this blog entry, we will be expanding upon the what we already had, so the directory structure will remain the same, except for a new page object called ShoppingCartPage.

src/test/java
  • actions
    • OrderActions
  • base
    • LoadProperties
  • enums
    • Products
    • Url
  • pages
    • HomePage
    • SignInPage
    • ProductPage
    • ShoppingCartPage
  • pojo
    • Book
  • properties
    • user.properties
  • testcases
    • PurchaseOrderTest
  • utils
    • CommonUtils
    • DriverUtils

Initialize the Login

Initializing the Login is simple. When I am signed into http://www.amazon.com/, I see on the horizontal navigation bar, "Hello, Thomas / Your Account". When you hover your cursor over that area, and scroll to the bottom, you can see "Not Thomas? Sign Out". 

By clicking on the link, you are directed to http://www.amazon.com//gp/flex/sign-out.html. Before you start your test, you can go to this link and whether or not you are logged in, you can sign out. 

With this information, we can update our PurchaseOrderTest, our OrderActions, and Url enum.

PurchaseOrderTest Addition:
 orderActions.initializeLogin();  

OrderActions Addition:
   public void initializeLogin(){  
System.out.println("INITIALIZING: Signing out, if needed.\n");
signOut();
}
public void signOut(){
HomePage homePage = new HomePage();
homePage.signOutWithSignOutLink();
}

HomePage Addition:
   public void signOutWithSignOutLink(){  
String url = Url.BASEURL.getURL() + Url.SIGNOUT.getURL();
navigateToURL(url);
}

Url Enum now looks like:
 public enum Url {  
PRODUCT_SECTION("/gp/product"),
BASEURL("http://www.amazon.com"),
SIGNOUT("/gp/flex/sign-out.html");
String url;
Url(String url){
this.url = url;
}
public String getURL() {
return url;
}
}

... Could this be done all in one method? Definitely! But by abstracting things out, it makes the code a lot easier to read, and a lot easier to find what classes you need to add to.

Initialize the Shopping Cart

Initializing the Shopping Cart is a bit more complex. It involves:

  • Check if the Shopping Cart icon already lists '0': Looking at the shopping cart icon in the horizontal navigation bar, you can see that the value isn't a graphic. It is just a number in a string that we can get and check if the value is already '0'.
  • If not '0', go to the Shopping Cart: Click on the Shopping Cart icon to go to the Shopping Cart. 
  • Get All Delete Buttons: Gather up all the web elements that are a delete button. 
  • Click all Delete Buttons: One by one, get the delete button, and click on it, removing the item from the cart.
If we wanted to make this more robust, we could check that at the end of the process that the cart is empty. With this first pass, we are going to leave it as is. 

PurchaseOrderTest Addition:
 @Test()  
public void test_createPurchaseOrderForSingleProduct(){
String username = LoadProperties.user.getProperty("tester23.username");
String password = LoadProperties.user.getProperty("tester23.password");
OrderActions orderActions = new OrderActions();
orderActions.initializeLogin();
orderActions.navigateToHomePage();
orderActions.loginAs(username, password);
orderActions.initializeCart();
}


  • First, we make sure that all users are logged out.
  • Then, we log in with our test user.
  • We navigate to the home page (http://www.amazon.com/)
  • We use the LoginAs method to log in. 
  • Once we are logged in, we can use the initializeCart method in OrderActions.

OrderActions Additions:
   public void initializeCart(){  
System.out.println("INITIALIZING: Deleting all Items in Cart.\n");
deleteAllItemsIfAnyFromCart();
}
public void deleteAllItemsIfAnyFromCart(){
HomePage homePage = new HomePage();
ShoppingCartPage shoppingCartPage = new ShoppingCartPage();
String itemsInCart = homePage.getNumberOfItemsListedInShoppingCartIcon();
if (!itemsInCart.equals("0")){
homePage.selectShoppingCartIcon();
shoppingCartPage.deleteAllItemsInCart();
} else {
System.out.println("\t* There are already '0' items in the Shopping Cart.");
}
}


HomePage, what it now looks like:
 public class HomePage extends CommonUtils {  
private final By YOUR_ACCOUNT = By.id("nav-link-yourAccount");
private final By SHOPPING_CART_ICON = By.cssSelector("#nav-cart");
private final By SHOPPING_CART_COUNT = By.cssSelector("#nav-cart > #nav-cart-count");
public HomePage(){
}
public void navigateToHomePage() {
String url = Url.BASEURL.getURL();
System.out.println("Navigating to Amazon.com: " + url);
navigateToURL(url);
}
public void navigateToSignInPage(){
System.out.println("HOME_PAGE: Selecting [YOUR_ACCOUNT] in navigation bar.");
scrollToThenClick(YOUR_ACCOUNT);
System.out.println("HOME_PAGE: Navigating to the SIGNIN_PAGE.\n");
}
public void signOutWithSignOutLink(){
String url = Url.BASEURL.getURL() + Url.SIGNOUT.getURL();
navigateToURL(url);
}
public void selectShoppingCartIcon(){
click(SHOPPING_CART_ICON);
}
public String getNumberOfItemsListedInShoppingCartIcon(){
return getElementText(SHOPPING_CART_COUNT);
}
}

Note that the #nav-cart-count is actually a child of #nav-cart. You need to call the main element, what I dubbed the "YOUR_ACCOUNT" web element, then get the child element.


Create a new ShoppingCartPage:
1:  import java.util.List;  
2: /**
3: * Created by tmaher on 12/21/2015.
4: */
5: public class ShoppingCartPage extends CommonUtils {
6: private final By SHOPPING_CART_HEADER = By.cssSelector("h1");
7: private final By DELETE_BUTTONS = By.cssSelector("input[value='Delete']");
8: private final String SHOPPING_CART_EMPTY_MSG = "Your Shopping Cart is empty.";
9: public void verifyOnShoppingCartPage(){
10: String url = getCurrentURL();
11: System.out.println("SHOPPING_CART_PAGE: Verifying that we are on SHOPPING_CART_PAGE.");
12: if (!url.contains("cart")){
13: throw new TestException("ERROR: Not on SHOPPING_CART_PAGE! URL: " + url);
14: }
15: }
16: public String getShoppingCartMessage(){
17: return getElementText(SHOPPING_CART_HEADER);
18: }
19: boolean checkIfShoppingCartHeaderListsEmptyMessage(){
20: String actualMessage = getShoppingCartMessage();
21: return (actualMessage.equals(SHOPPING_CART_EMPTY_MSG));
22: }
23: public void deleteAllItemsInCart(){
24: List deleteButtons = getElements(DELETE_BUTTONS);
25: for ( WebElement button : deleteButtons ){
26: button.click();
27: }
28: }
29: }

With the deleteAllItemsInCart method, we can get all the delete button items, and click every one of them in the list. 

CommonUtils methods used:
   public List getElements(By Selector) {  
waitForElementToBeVisible(Selector);
try {
return _driver.findElements(Selector);
} catch (Exception e) {
throw new NoSuchElementException(String.format("The following element did not display: [%s] ", Selector.toString()));
}
}


... In the next blog post we can finally add the product to the Shopping Cart Review page and check that the values are what is expected.


Happy coding!




NEXT: Writing a Shopping Cart Test


-T.J. Maher
 Sr. QA Engineer, Fitbit
 Boston, MA

// Automated tester for [ 9 ] month and counting!

Please note: 'Adventures in Automation' is a personal blog about automated testing. It is not an official blog of Fitbit.com