From 93fb486f469ecb03528878a7709f4e3cfa8a77fb Mon Sep 17 00:00:00 2001 From: James Tacker Date: Mon, 15 Apr 2019 09:19:05 -0700 Subject: [PATCH] updated exercise 2-4 --- exercise-guides/exercise2.md | 238 +++++++++++++++++++++++++++++------ exercise-guides/exercise3.md | 10 +- exercise-guides/exercise4.md | 75 +++-------- 3 files changed, 226 insertions(+), 97 deletions(-) diff --git a/exercise-guides/exercise2.md b/exercise-guides/exercise2.md index 8cc1eb5..29d6b20 100644 --- a/exercise-guides/exercise2.md +++ b/exercise-guides/exercise2.md @@ -3,25 +3,25 @@ ## Part One: Create a `LoginPage` 1. Checkout branch `02_create_page_objects`. 3. In the **`pages`** package, navigate to the class called **`LoginPage`** -4. Create a `visit` method in the `LoginPage` object: +4. Create the constructor for the page object: ``` - public LoginPage visit() { - driver.get("https://www.saucedemo.com"); - return this; + public LoginPage(WebDriver driver) { + this.driver = driver; } ``` -5. Create the constructor for the page object: +5. Create a `visit` method in the `LoginPage` object: ``` - public LoginPage(WebDriver driver) { - this.driver = driver; + public LoginPage visit() { + driver.get("https://www.saucedemo.com"); + return this; } ``` 6. Open **`LoginFeatureTest`** and import the **`LoginPage`** changes to replace **`driver.navigate().to("https://www.saucedemo.com")`** For Example: * Before - ``` - driver.navigate().to("https://www.saucedemo.com"); - ``` + ``` + driver.navigate().to("https://www.saucedemo.com"); + ``` * After ``` LoginPage LoginPage = new LoginPage(driver); @@ -34,47 +34,215 @@ ```
-## Part Two: Create `login()` Class Method +## Part Two: Create `login()` Method 1. Open **`LoginPage`** and create a new class method called `login()`. This method will return a new page object that represents the next page in the journey (i.e. `InventoryPage`) -2. Add the **`LoginPage.visit()`** action in place of **`driver.navigate().to("https://www.saucedemo.com")`** The method will also expect some String data for the credentials (`username` and `password`) input. For Example: - ``` - public InventoryPage login(String username, String password) - { - - } - ``` -3. In `LoginFeatureTest` copy line 55-73 and paste it into `LoginPage`. The `login()` method should now look like the following: +2. Add the **`LoginPage.visit()`** action in place of **`driver.navigate().to("https://www.saucedemo.com")`** The method will also expect some `String` data for the credentials (`username` and `password`). For Example: ``` public InventoryPage login(String username, String password) { String userField = "[data-test='username']"; String passField = "[data-test='password']"; String loginBtn = "[value='LOGIN']"; + } + ``` +3. Add the following Selenium commands in order to send the keystrokes: + ``` + // send username keystrokes + driver.findElement(By.cssSelector(userField)).sendKeys(username); - // send username keystrokes - driver.findElement(By.cssSelector(userField)) - .sendKeys(username); - - // send password keystrokes - driver.findElement(By.cssSelector(passField)) - .sendKeys(password); + // send password keystrokes + driver.findElement(By.cssSelector(passField)).sendKeys(password); - // click login button to submit keystrokes - driver.findElement(By.cssSelector(loginBtn)).click(); - return new InventoryPage(driver); - } + // click login button to submit keystrokes + driver.findElement(By.cssSelector(loginBtn)).click(); + return new InventoryPage(driver); ``` -4. Add the following to the `LoginFeatureTest`, add the following to the `ShouldBeAbleToLogin` method: +4. Open `LoginFeatureTest`, and add the following to the `ShouldBeAbleToLogin` method: ``` - String username = "standard_user"; - String password = "secret_sauce"; - loginPage.login(username, password); + import pages.LoginPage; + ... + @Test + public void ShouldBeAbleToLogin() { + + // wait 5 seconds + driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS) ; + //navigate to the url of the Sauce Labs Sample app + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); + + // Ignore the following selectors + String username = "standard_user"; + String password = "secret_sauce"; + loginPage.login(username, password); + Assert.assertEquals("https://www.saucedemo.com/inventory.html", driver.getCurrentUrl()); + } ``` -5. After the change, save and run `mvn test` to ensure the test still runs. +5. Save and run `mvn test` to ensure the test still executes: ``` mvn test -Dtest=LoginFeatureTest ``` + +
+ +## Part Three: Create Remaining Page Objects +1. Complete the `InventoryPage` object with the following class methods: + ``` + private final WebDriver driver; + + public InventoryPage(WebDriver driver) { + this.driver = driver; + } + + public void addBackpackToCart() { + String backpack = "div:nth-child(1) > div.pricebar > button"; + driver.findElement(By.cssSelector(backpack)).click(); + } + + public ShoppingCartPage goToShoppingCart() { + String cart = "#shopping_cart_container > a > svg"; + driver.findElement(By.cssSelector(cart)).click(); + return new ShoppingCartPage(driver); + } + ``` +2. Create the remainder page objects: + * `ShoppingCartPage` + * `ConfirmationPage` + * `CheckoutStepTwoPage` + * `CheckoutCompletePage` +3. Add the following methods to each respective page object: + * **`ShoppingCartPage`** + ``` + public class ShoppingCartPage { + private final WebDriver driver; + public ShoppingCartPage(WebDriver driver) { + this.driver = driver; + } + public CheckoutStepTwoPage checkout() { + String checkoutLink = "div.cart_footer > a.btn_action.checkout_button"; + driver.findElement(By.cssSelector(checkoutLink)).click(); + return new CheckoutStepTwoPage(driver); + } + } + ``` + * **`ConfirmationPage`** + ``` + public class ConfirmationPage { + private final WebDriver driver; + public ConfirmationPage(WebDriver driver) { + this.driver = driver; + } + + public CheckoutCompletePage finish() { + String finished =".btn_action.cart_button"; + driver.findElement(By.cssSelector(finished)).click(); + return new CheckoutCompletePage(driver); + } + } + ``` + * **`CheckoutStepTwoPage`** + ``` + public class CheckoutStepTwoPage { + private final WebDriver driver; + //TODO notice the duplication in all of page our classes + public CheckoutStepTwoPage(WebDriver driver) { + this.driver = driver; + } + + public ConfirmationPage fillOutInformation(String first, String last, String zip) { + String firstNameField = "[data-test='firstName']"; + String lastNameField = "[data-test='lastName']"; + String postalField= "[data-test='postalCode']"; + String continueLink = "[value='CONTINUE']"; + // proceed to shipping info (checkout step 1) + driver.findElement(By.cssSelector(firstNameField)).sendKeys(first); + driver.findElement(By.cssSelector(lastNameField)).sendKeys(last); + driver.findElement(By.cssSelector(postalField)).sendKeys(zip); + driver.findElement(By.cssSelector(continueLink)).click(); + return new ConfirmationPage(driver); + } + } + ``` + * **`CheckoutCompletePage`** + ``` + public class CheckoutCompletePage { + private final WebDriver driver; + //TODO more duplication + public CheckoutCompletePage(WebDriver driver) { + this.driver = driver; + } + + public boolean isLoaded() { + return driver.getCurrentUrl().contains("https://www.saucedemo.com/checkout-complete.html"); + } + } + ``` +4. Create a new test class called **`CheckoutFeatureTest`** with the following; + ``` + public class CheckoutFeatureTest { + protected WebDriver driver; + + @BeforeMethod + public void setUp(Method method) throws MalformedURLException + { + // Input your SauceLabs Credentials + String sauceUsername = System.getenv("SAUCE_USERNAME"); + String sauceAccessKey = System.getenv("SAUCE_ACCESS_KEY"); + + MutableCapabilities capabilities = new MutableCapabilities(); + + //sets browser to Firefox + capabilities.setCapability("browserName", "firefox"); + + //sets operating system to macOS version 10.13 + capabilities.setCapability("platform", "macOS 10.13"); + + //sets the browser version to 11.1 + capabilities.setCapability("version", "58.0"); + + //sets your test case name so that it shows up in Sauce Labs + capabilities.setCapability("name", method.getName()); + capabilities.setCapability("username", sauceUsername); + capabilities.setCapability("accessKey", sauceAccessKey); + + //instantiates a remote WebDriver object with your desired capabilities + driver = new RemoteWebDriver(new URL("https://ondemand.saucelabs.com/wd/hub"), capabilities); + } + @Test + public void ShouldBeAbleToCheckoutWithItems() { + // wait 5 seconds + driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS) ; + //navigate to the url of the Sauce Labs Sample app + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); + + // Ignore the following selectors + String username = "standard_user"; + String password = "secret_sauce"; + InventoryPage inventoryPage = loginPage.login(username, password); + + // Assert that the url is on the inventory page + //TODO fix this assertion later + Assert.assertEquals("https://www.saucedemo.com/inventory.html", driver.getCurrentUrl()); + inventoryPage.addBackpackToCart(); + ShoppingCartPage cart = inventoryPage.goToShoppingCart(); + CheckoutStepTwoPage stepTwoPage = cart.checkout(); + ConfirmationPage confirmationPage = stepTwoPage.fillOutInformation("first", "last", "zip"); + CheckoutCompletePage finalConfirmationPage = confirmationPage.finish(); + Assert.assertTrue(finalConfirmationPage.isLoaded()); + } + + @AfterMethod + public void teardown(ITestResult result) { + ((JavascriptExecutor)driver).executeScript("sauce:job-result=" + (result.isSuccess() ? "passed" : "failed")); + driver.quit(); + } + } + ``` +5. Run `mvn test` to ensure the following tests run correctly: + * **`CheckoutFeatureTest`** + * **`FullJourneyTest`** + * **`LoginFeatureTest`** 6. Use `git stash` or `git commit` to discard or save your changes. Checkout the next branch to proceed to the next exercise ``` git checkout 03_remove_duplication diff --git a/exercise-guides/exercise3.md b/exercise-guides/exercise3.md index 333e768..8977296 100644 --- a/exercise-guides/exercise3.md +++ b/exercise-guides/exercise3.md @@ -1,16 +1,20 @@ # Exercise 3: Remove Duplication 1. Checkout branch `03_remove_duplication`. -2. Open the new test class called **`CheckoutFeatureTest`** in `src > test > java > exercises`. -3. There is duplicate code that exists in **`LoginFeatureTest`**, specifically the `setup()` and `teardown()` methods. +2. Open **`CheckoutFeatureTest`** in `src > test > java > exercises`. There is duplicate code that exists in **`LoginFeatureTest`**, specifically the `setup()` and `teardown()` methods. 4. Create a `BaseTest` class that executes these prerequisite and postrequisite test actions. -5. Remove the `setup()` and `teardown()` methods from `LoginFeatureTest` and `CheckoutFeatureTest` and place them into `BaseTest` +5. Migrate the `setup()` and `teardown()` methods from `LoginFeatureTest` and `CheckoutFeatureTest` and place them into `BaseTest` 6. Back in `LoginFeatureTest` and `CheckoutFeatureTest`, extend `BaseTest` like so: ``` public class LoginFeatureTest extends BaseTest { ... } ``` +7. Also in `LoginFeatureTest` and `CheckoutFeatureTest` remove the following line: + ``` + protected WebDriver driver + ``` + as it's now redundant. 7. Delete `FullJourneyTest` and test the changes: ``` mvn test diff --git a/exercise-guides/exercise4.md b/exercise-guides/exercise4.md index 6927b1e..b421578 100644 --- a/exercise-guides/exercise4.md +++ b/exercise-guides/exercise4.md @@ -1,76 +1,33 @@ # Exercise 4: Configure Atomic Tests -## Part One: Create `CheckoutCompletePage` -1. Checkout the branch `04_configure_atomic_tests`. -2. In `src > test > java > pages`, create a new class called `CheckoutCompletePage` -3. Add the following: - ``` - public class CheckoutCompletePage { - private final WebDriver driver; - - public CheckoutCompletePage(WebDriver driver) { - this.driver = driver; - } +## Part One: Implement the `JavascriptExecutor` to Bypass Pages +1. Open **`ConfirmationPage`** and add the following class method: + ``` + public void setPageState() { + driver.navigate().refresh(); } ``` -4. Add a new class method called `IsLoaded()` to confirm the correct checkout page is loaded: +2. In **`setPageState()`** add the following + * **`JavaScriptExecutor`** command to bypass logging in through the **`LoginPage`** object: ``` - public boolean IsLoaded() - { - return driver.getCurrentUrl().contains("https://www.saucedemo.com/checkout-complete.html"); - } + ((JavascriptExecutor)driver).executeScript("window.sessionStorage.setItem('standard-username', 'standard-user')"); ``` - -
- -## Part Two: Modify `ConfirmationPage` -1. Open `ConfirmationPage` in `src > test > java > pages`. -2. Add the following class methods: + * **`JavaScriptExecutor`** command to bypass adding items to the cart through the **`InventoryPage`** object: ``` - public void visit() { - driver.get("https://www.saucedemo.com/checkout-step-two.html"); - } + ((JavascriptExecutor)driver).executeScript("window.sessionStorage.setItem('cart-contents', '[4,1]')"); ``` +3. Add a `Boolean` method called `hasItems()`: ``` public Boolean hasItems() { String cartBadge = "shopping_cart_badge"; return Integer.parseInt(driver.findElement(By.className(cartBadge)).getText()) > 0; } ``` - ``` - public CheckoutCompletePage FinishCheckout() - { - String finished =".btn_action.cart_button"; - driver.findElement(By.cssSelector(finished)).click(); - return new CheckoutCompletePage(driver); - } - ``` -3. Open **`CheckoutFeatureTest`** located in `src > test > java > exercises`. -4. You'll notice that the **`ShouldBeAbleToCheckout()`** class method steps through many pages to get to the checkout function. The existing test flow works like this: - * User logs in - * Adds some items to the cart - * Clicks the cart icon to proceed to checkout - -This approach is under-optimized because our tests shouldn't rely on the assertions of other tests and it's unecessary to travel through each individual page to reach that feature. Therefore if we're only testing features on a specific page, we can modify the page state using the **`JavaScriptExecutor`**.
- -## Part Three: Implement the `JavascriptExecutor` to Bypass Pages -1. Go back to **`ConfirmationPage`** and add the following class method: - ``` - public void setPageState() { - driver.navigate().refresh(); - } - ``` -2. In **`setPageState()`** add the following **`JavaScriptExecutor`** command to bypass logging in through the **`LoginPage`** object: - ``` - ((JavascriptExecutor)driver).executeScript("window.sessionStorage.setItem('standard-username', 'standard-user')"); - ``` -3. Then add another **`JavaScriptExecutor`** command to bypass adding items to the cart through the **`InventoryPage`** object: - ``` - ((JavascriptExecutor)driver).executeScript("window.sessionStorage.setItem('cart-contents', '[4,1]')"); - ``` -4. In **`CheckoutFeatureTest`**, delete the existing commands and add the following: + +## Part Two: Modify `CheckoutFeatureTest` +1. Open **`CheckoutFeatureTest`**, delete the existing commands, and add the following: ``` @Test public void ShouldBeAbleToCheckoutWithItems() { @@ -87,11 +44,11 @@ This approach is under-optimized because our tests shouldn't rely on the asserti Assert.assertTrue(completePage.IsLoaded()); } ``` -5. Save all and run the following command to ensure the build passes: +2. Save all and run the following command to ensure the build passes: ``` mvn test ``` -6. Use `git stash` or `git commit` to discard or save your changes. Checkout the next branch to proceed to the next exercise +3. Use `git stash` or `git commit` to discard or save your changes. Checkout the next branch to proceed to the next exercise ``` git checkout 05_create_base_page ``` \ No newline at end of file