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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ It is not expected that you complete every task, however, please give your best

You will be scored based on your ability to complete the following tasks:

- [ ] Install and setup this repository on your personal computer
- [X] Install and setup this repository on your personal computer
- [ ] Complete the automation tasks listed below

### Tasks
- [ ] Modify the scenario 'Validate the login page title' from [login.feature](features/login.feature#8) which runs but fails. Determine the cause of the failure and update the scenario to pass in the test
- [ ] Extend the scenario 'Validate login error message' from [login.feature](features/login.feature#10) which runs and passes but is missing a step. Extend the scenario to validate the error message received.
- [ ] Modify and extend the 'Validate successful purchase text' from [purchase.feature](features/purchase.feature#6) with steps for each comment listed. Consider writing a new steps.ts file along with an appropriate page.ts
- [X] Modify the scenario 'Validate the login page title' from [login.feature](features/login.feature#8) which runs but fails. Determine the cause of the failure and update the scenario to pass in the test
- [X] Extend the scenario 'Validate login error message' from [login.feature](features/login.feature#10) which runs and passes but is missing a step. Extend the scenario to validate the error message received.
- [X] Modify and extend the 'Validate successful purchase text' from [purchase.feature](features/purchase.feature#6) with steps for each comment listed. Consider writing a new steps.ts file along with an appropriate page.ts
- [ ] Modify and extend the 'Validate product sort by price sort' from [product.feature](features/product.feature#6) with steps for each comment listed. Utilize the Scenario Outline and Examples table to parameterize the test
- [ ] Extend the testing coverage with anything you believe would be beneficial
5 changes: 3 additions & 2 deletions features/login.feature
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ 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
# TODO: Add a step to validate the error message received
Then I should see an the error message 'Epic sadface: Sorry, this user has been locked out.'
6 changes: 5 additions & 1 deletion features/product.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ Feature: Product Feature
Scenario Outline: Validate product sort by price <sort>
Then I will login as 'standard_user'
# TODO: Sort the items by <sort>
Then I will sort items by '<sort>'
# TODO: Validate all 6 items are sorted correctly by price
Then the items should be sorted by price '<sort>'
Examples:
# TODO: extend the datatable to paramterize this test
| sort |
| sort |
| high to low |
| low to high |
8 changes: 7 additions & 1 deletion features/purchase.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ 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 select the link to the cart
# TODO: Select Checkout
Then I will click checkout
# TODO: Fill in the First Name, Last Name, and Zip/Postal Code
Then I will complete the checkout form
# TODO: Select Continue
Then I will click continue
# TODO: Select Finish
# TODO: Validate the text 'Thank you for your order!'
Then I will click finish
# TODO: Validate the text 'Thank you for your order!'
Then I should see the order complete message 'Thank you for your order!'
42 changes: 23 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
"devDependencies": {
"@cucumber/cucumber": "^10.0.1",
"@cucumber/pretty-formatter": "^1.0.0",
"@playwright/test": "^1.40.1",
"@playwright/test": "^1.58.2",
"@types/node": "^20.10.3",
"cucumber-html-reporter": "^7.1.1",
"ts-node": "^10.9.1",
"typescript": "^5.3.2"
},
"dependencies": {
"playwright": "^1.58.2"
}
}
9 changes: 8 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 = '[data-test="error"]'

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

public async loginErrorMessage(expectedMessage:string){
const errorMessage = await this.page.locator(this.errorMessage).innerText()
expect(errorMessage).toBe(expectedMessage)

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

export class Product {
private readonly page: Page
private readonly addToCart: string = 'button[id="add-to-cart-sauce-labs-backpack"]'
private readonly cartLink: string = '[data-test="shopping-cart-link"]'
private readonly sortDropdownContainer: string = '[data-test="product-sort-container"]'
private readonly itemPrice: string = '[data-test="inventory-item-price"]'


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

public async selectCart(){
await this.page.locator(this.cartLink).click()
}

public async sortByPrice(sort: string) {
const value = sort === 'low to high' ? 'lohi' : 'hilo'
await this.page.locator(this.sortDropdownContainer).selectOption(value)
}

public async validatePriceSorting(sort: string) {
const itemsPrices = await this.page.locator(this.itemPrice).allInnerTexts()
const prices = itemsPrices.map(p => parseFloat(p.replace('$', '')))
const sorted = [...prices].sort((a, b) => sort === 'low to high' ? a - b : b - a)
expect(prices).toEqual(sorted)
}


}
45 changes: 45 additions & 0 deletions pages/purchase.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { expect, Page } from "@playwright/test"

export class Purchase {
private readonly page: Page
private readonly firstName: string = 'Testy'
private readonly lastName: string = 'McTester'
private readonly zipcode: string = '12345'
private readonly firstNameField: string = 'input[id="first-name"]'
private readonly lastNameField: string = 'input[id="last-name"]'
private readonly zipcodeField: string = 'input[id="postal-code"]'
private readonly cartCheckoutButton: string = 'button[id="checkout"]'
private readonly checkoutContinueButton: string = 'input[id="continue"]'
private readonly finishCheckoutButton: string = 'button[id="finish"]'
private readonly orderCompleteText: string = '[data-test="complete-header"]'



constructor(page: Page) {
this.page = page;
}

public async selectCheckout(){
await this.page.locator(this.cartCheckoutButton).click()
}

public async completeCheckoutForm() {
await this.page.locator(this.firstNameField).fill(this.firstName)
await this.page.locator(this.lastNameField).fill(this.lastName)
await this.page.locator(this.zipcodeField).fill(this.zipcode)
}

public async continueCheckout() {
await this.page.locator(this.checkoutContinueButton).click()
}

public async finishCheckout() {
await this.page.locator(this.finishCheckoutButton).click()
}

public async seeOrderCompleteStatus(expectedMessage: string){
const orderCompleteMessage = await this.page.locator(this.orderCompleteText).innerText()
expect(orderCompleteMessage).toBe(expectedMessage)

}
}
4 changes: 4 additions & 0 deletions steps/login.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ Then('I should see the title {string}', async (expectedTitle) => {

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

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

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

Then('I will select the link to the cart', async () => {
await new Product(getPage()).selectCart();
});

Then('I will sort items by {string}', async (sort: string) => {
await new Product(getPage()).sortByPrice(sort);
});

Then('the items should be sorted by price {string}', async (sort: string) => {
await new Product(getPage()).validatePriceSorting(sort);
});
26 changes: 26 additions & 0 deletions steps/purchase.steps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Then } from '@cucumber/cucumber';
import { getPage } from '../playwrightUtilities';
import { Purchase } from '../pages/purchase.page';


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


Then('I will complete the checkout form', async () => {
await new Purchase(getPage()).completeCheckoutForm();
});


Then('I will click continue', async () => {
await new Purchase(getPage()).continueCheckout();
});

Then('I will click finish', async () => {
await new Purchase(getPage()).finishCheckout();
});

Then ('I should see the order complete message {string}', async (expectedMessage) => {
await new Purchase(getPage()).seeOrderCompleteStatus(expectedMessage)
})
Loading