Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions features/login.feature
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Feature: Login Feature

Scenario: Validate the login page title
# TODO: Fix this failing scenario
Then I should see the title "Labs Swag"
Then I should see the title "Swag Labs"

Scenario: Validate login error message
Then I will login as 'locked_out_user'
# TODO: Add a step to validate the error message received
Then I should see the error message "Epic sadface: Sorry, this user has been locked out."
11 changes: 7 additions & 4 deletions features/product.feature
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ Feature: Product Feature
# Create a datatable to validate the Price (high to low) and Price (low to high) sort options (top-right) using a Scenario Outline
Scenario Outline: Validate product sort by price <sort>
Then I will login as 'standard_user'
# TODO: Sort the items by <sort>
# TODO: Validate all 6 items are sorted correctly by price
Then I click on filter and choose "<sort_option>" and "<expected_order>"
Then I validate item order
Examples:
# TODO: extend the datatable to paramterize this test
| sort |
| sort_option | expected_order |
| Price | descending |
| Price | ascending |
| Name | descending |
| Name | ascending |
6 changes: 5 additions & 1 deletion features/purchase.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ Feature: Purchase Feature
Then I will login as 'standard_user'
Then I will add the backpack to the cart
# TODO: Select the cart (top-right)
Then I will click on shopping cart
# TODO: Select Checkout
Then I will click checkout
# TODO: Fill in the First Name, Last Name, and Zip/Postal Code
# TODO: Select Continue
# TODO: Select Finish
# TODO: Validate the text 'Thank you for your order!'
Then I will fill out and submit checkout form with 'Jackson' and 'Lei' and '1234'
# TODO: Validate the text 'Thank you for your order!'
Then I will see the message 'Thank you for your order!'
27 changes: 27 additions & 0 deletions pages/checkout.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Page, expect } from "@playwright/test"

export class Checkout {
private readonly page: Page
private readonly firstNameInput: string = '//input[@data-test="firstName"]'
private readonly lastNameInput: string = '//input[@data-test="lastName"]'
private readonly zipCodeInput: string = '//input[@data-test="postalCode"]'
private readonly continueButton: string = '//*[@data-test="continue"]'
private readonly finishButton: string = '//*[@data-test="finish"]'
private readonly completeText: string = '//*[@data-test="complete-header"]'

constructor(page: Page) {
this.page = page;
}
public async submitCheckoutForm(firstname: string, lastname: string, zipcode: string) {
await this.page.locator(this.firstNameInput).fill(firstname)
await this.page.locator(this.lastNameInput).fill(lastname)
await this.page.locator(this.zipCodeInput).fill(zipcode)
await this.page.locator(this.continueButton).click()
await this.page.locator(this.finishButton).click()
}

public async validateCompletedMessage(message: string) {
expect(message).toEqual(await this.page.locator(this.completeText).textContent())
}

}
8 changes: 7 additions & 1 deletion pages/login.page.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Page } from "@playwright/test"
import { expect, Page } from "@playwright/test"

export class Login {
private readonly page: Page
private readonly password: string = 'secret_sauce'
private readonly passwordField: string = 'input[id="password"]'
private readonly userNameField: string = 'input[id="user-name"]'
private readonly loginButton: string = 'input[id="login-button"]'
private readonly errorMessage: string = 'h3[data-test="error"]'

constructor(page: Page) {
this.page = page;
Expand All @@ -23,4 +24,9 @@ export class Login {
await this.page.locator(this.passwordField).fill(this.password)
await this.page.locator(this.loginButton).click()
}

public async validateErrorMessage(expectedErrorMessage: string) {
const actualErrorMessage = await this.page.locator(this.errorMessage).textContent();
expect(actualErrorMessage).toEqual(expectedErrorMessage);
}
}
49 changes: 48 additions & 1 deletion pages/product.page.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { Page } from "@playwright/test"
import { Page, expect } from "@playwright/test"

export class Product {
private readonly page: Page
private readonly addToCart: string = 'button[id="add-to-cart-sauce-labs-backpack"]'
private readonly shoppingCartLink: string = '//*[@data-test="shopping-cart-link"]'
private readonly checkoutButton: string = '//*[@data-test="checkout"]'
private readonly dropDownButton: string = '//*[@data-test="product-sort-container"]'
private readonly itemName: string = '//*[@data-test="inventory-item-name"]'
private readonly itemPrice: string = '//*[@data-test="inventory-item-price"]'

constructor(page: Page) {
this.page = page;
Expand All @@ -11,4 +16,46 @@ export class Product {
public async addBackPackToCart() {
await this.page.locator(this.addToCart).click()
}

public async clickShoppingCart() {
await this.page.locator(this.shoppingCartLink).click()
}

public async clickCheckout() {
await this.page.locator(this.checkoutButton).click()
}

public async selectFilterOption(sortOption: string, expectedOrder: string) {
if (sortOption == "Price" && expectedOrder == "descending") {
await this.page.locator(this.dropDownButton).selectOption("hilo")
} else if (sortOption == "Price" && expectedOrder == "ascending") {
await this.page.locator(this.dropDownButton).selectOption("lohi")
} else if (sortOption == "Name" && expectedOrder == "descending") {
await this.page.locator(this.dropDownButton).selectOption("za")
} else if (sortOption == "Name" && expectedOrder == "ascending") {
await this.page.locator(this.dropDownButton).selectOption("az")
}
}

public async validateItemOrder() {
const sortOption = await this.page.locator(this.dropDownButton).inputValue()
const actualNameOrder = await this.page.locator(this.itemName).allTextContents()
const itemPriceList = await this.page.locator(this.itemPrice).allTextContents()
if (sortOption == "az") {
const expectedNameOrder = [...actualNameOrder].sort((a,b) => a.localeCompare(b))
expect(actualNameOrder).toEqual(expectedNameOrder)
} else if (sortOption == "za") {
const expectedNameOrder = [...actualNameOrder].sort((a,b) => b.localeCompare(a))
expect(actualNameOrder).toEqual(expectedNameOrder)
} else if (sortOption == "lohi") {
const itemPriceListTransFormed = itemPriceList.map(price => parseFloat(price.replace(/[$,]/g, "")))
const expectedPriceOrder = [...itemPriceListTransFormed].sort((a,b) => a - b)
expect(itemPriceListTransFormed).toEqual(expectedPriceOrder)
} else if (sortOption == "hilo") {
const itemPriceListTransFormed = itemPriceList.map(price => parseFloat(price.replace(/[$,]/g, "")))
const expectedPriceOrder = [...itemPriceListTransFormed].sort((a,b) => b - a)
expect(itemPriceListTransFormed).toEqual(expectedPriceOrder)
}
}

}
7 changes: 6 additions & 1 deletion steps/login.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,10 @@ Then('I should see the title {string}', async (expectedTitle) => {
});

Then('I will login as {string}', async (userName) => {
await new Login(getPage()).loginAsUser(userName);
const loginPage = new Login(getPage());
await loginPage.loginAsUser(userName);
});

Then('I should see the error message {string}', async (expectedMessage) => {
await new Login(getPage()).validateErrorMessage(expectedMessage);
});
18 changes: 17 additions & 1 deletion steps/product.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,20 @@ import { Product } from '../pages/product.page';

Then('I will add the backpack to the cart', async () => {
await new Product(getPage()).addBackPackToCart();
});
});

Then('I will click on shopping cart', async () => {
await new Product(getPage()).clickShoppingCart();
})

Then('I will click checkout', async () => {
await new Product(getPage()).clickCheckout();
})

Then('I click on filter and choose {string} and {string}', async (sortOption, expectedOrder) => {
await new Product(getPage()).selectFilterOption(sortOption, expectedOrder)
})

Then('I validate item order', async () => {
await new Product(getPage()).validateItemOrder()
})
11 changes: 11 additions & 0 deletions steps/purchase.steps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Then } from '@cucumber/cucumber';
import { getPage } from '../playwrightUtilities';
import { Checkout } from '../pages/checkout.page';

Then('I will fill out and submit checkout form with {string} and {string} and {string}', async (firstname, lastname, zipcode) => {
await new Checkout(getPage()).submitCheckoutForm(firstname, lastname, zipcode);
})

Then('I will see the message {string}', async (message) => {
await new Checkout(getPage()).validateCompletedMessage(message)
})
Loading