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
15 changes: 15 additions & 0 deletions features/cart.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Feature: Cart Feature

Background:
Given I open the "https://www.saucedemo.com/" page

Scenario: Validate cart item count after adding product
Then I will login as 'standard_user'
Then I will add the backpack to the cart
Then I should see "1" item in the cart badge

Scenario: Validate cart is empty after removing product
Then I will login as 'standard_user'
Then I will add the backpack to the cart
Then I will remove the backpack from the cart
Then the cart badge should not be visible
8 changes: 5 additions & 3 deletions features/login.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ Feature: Login Feature
Given I open the "https://www.saucedemo.com/" page

Scenario: Validate the login page title
# TODO: Fix this failing scenario
Then I should see the title "Labs Swag"
# TODO: Fix this failing scenario -fixed
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-added
Then I should see 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 the items by "<sort>"
# TODO: Validate all 6 items are sorted correctly by price
Then I should see all 6 items sorted by price "<order>"
Examples:
# TODO: extend the datatable to paramterize this test
| sort |
| sort | order |
| Price (low to high) | asc |
| Price (high to low) | desc |
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 cart
# TODO: Select Checkout
Then I will select checkout
# TODO: Fill in the First Name, Last Name, and Zip/Postal Code
Then I will fill in checkout info with first name "Ashwitha" last name "Vollem" and zip "12345"
# TODO: Select Continue
Then I will select continue
# TODO: Select Finish
# TODO: Validate the text 'Thank you for your order!'
Then I will select finish
# TODO: Validate the text 'Thank you for your order!'
Then I should see the order confirmation text "Thank you for your order!"
2 changes: 1 addition & 1 deletion package-lock.json

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

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

export class Cart {
private readonly page: Page
private readonly cartBadge: string = '[data-test="shopping-cart-badge"]'
private readonly removeBackpack: string = '[data-test="remove-sauce-labs-backpack"]';

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

public async validateCartBadgeCount(expectedCount: string) {
const badgeText = await this.page.locator(this.cartBadge).textContent();
if (badgeText?.trim() !== expectedCount) {
throw new Error(`Expected cart badge to show "${expectedCount}" but found "${badgeText?.trim()}"`);
}
}

public async removeBackpackFromCart() {
await this.page.locator(this.removeBackpack).click();
}

public async validateCartBadgeNotVisible() {
const isVisible = await this.page.locator(this.cartBadge).isVisible();
if (isVisible) {
throw new Error('Expected cart badge to not be visible but it is visible');
}
}
}
7 changes: 7 additions & 0 deletions pages/login.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export class Login {
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 validateErrorMessage(expectedMessage: string) {
const errorText = await this.page.locator(this.errorMessage).textContent();
if (errorText?.trim() !== expectedMessage) {
throw new Error(`Expected error message to be "${expectedMessage}" but found "${errorText?.trim()}"`);
}
}
}
22 changes: 22 additions & 0 deletions pages/product.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { 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 sortDropdown: string = '[data-test="product-sort-container"]';
private readonly itemPrices: string = '[data-test="inventory-item-price"]';

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

public async sortItemsBy(sortOption: string) {
await this.page.locator(this.sortDropdown).selectOption({ label: sortOption });
}

public async validateItemsSortedByPrice(order: string) {
const priceElements = await this.page.locator(this.itemPrices).allTextContents();
if (priceElements.length !== 6) {
throw new Error(`Expected 6 items but found ${priceElements.length}`);
}
const prices = priceElements.map(p => parseFloat(p.replace('$', '')));
for (let i = 0; i < prices.length - 1; i++) {
if (order === 'asc' && prices[i] > prices[i + 1]) {
throw new Error(`Items are not sorted by price (low to high). Found ${prices[i]} before ${prices[i + 1]}`);
}
if (order === 'desc' && prices[i] < prices[i + 1]) {
throw new Error(`Items are not sorted by price (high to low). Found ${prices[i]} before ${prices[i + 1]}`);
}
}
}
}
46 changes: 46 additions & 0 deletions pages/purchase.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Page } from "@playwright/test"

export class Purchase {
private readonly page: Page
private readonly cartIcon: string = '[data-test="shopping-cart-link"]'
private readonly checkoutButton: string = '[data-test="checkout"]'
private readonly firstNameField: string = '[data-test="firstName"]'
private readonly lastNameField: string = '[data-test="lastName"]'
private readonly zipCodeField: string = '[data-test="postalCode"]'
private readonly continueButton: string = '[data-test="continue"]'
private readonly finishButton: string = '[data-test="finish"]'
private readonly confirmationText: string = '[data-test="complete-header"]'

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

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

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

public async fillCheckoutInfo(firstName: string, lastName: string, zip: string) {
await this.page.locator(this.firstNameField).fill(firstName);
await this.page.locator(this.lastNameField).fill(lastName);
await this.page.locator(this.zipCodeField).fill(zip);
}

public async selectContinue() {
await this.page.locator(this.continueButton).click();
}

public async selectFinish() {
await this.page.locator(this.finishButton).click();
}

public async validateConfirmationText(expectedText: string) {
const text = await this.page.locator(this.confirmationText).textContent();
if (text?.trim() !== expectedText) {
throw new Error(`Expected confirmation text to be "${expectedText}" but found "${text?.trim()}"`);
}
}
}
15 changes: 15 additions & 0 deletions steps/cart.steps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Then } from '@cucumber/cucumber';
import { getPage } from '../playwrightUtilities';
import { Cart } from '../pages/cart.page';

Then('I should see {string} item in the cart badge', async (expectedCount) => {
await new Cart(getPage()).validateCartBadgeCount(expectedCount);
});

Then('I will remove the backpack from the cart', async () => {
await new Cart(getPage()).removeBackpackFromCart();
});

Then('the cart badge should not be visible', async () => {
await new Cart(getPage()).validateCartBadgeNotVisible();
});
11 changes: 9 additions & 2 deletions steps/common.steps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { Given } from "@cucumber/cucumber";
import { Given, Then} from "@cucumber/cucumber";
import { getPage } from "../playwrightUtilities";

Given('I open the {string} page', async (url) => {
await getPage().goto(url);
});
});

Then('I should see the title {string}', async (expectedTitle: string) => {
const pageTitle = await getPage().title();
if (pageTitle !== expectedTitle) {
throw new Error(`Expected title to be "${expectedTitle}" but found "${pageTitle}"`);
}
});
9 changes: 6 additions & 3 deletions steps/login.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import { Then } from '@cucumber/cucumber';
import { getPage } from '../playwrightUtilities';
import { Login } from '../pages/login.page';

Then('I should see the title {string}', async (expectedTitle) => {
await new Login(getPage()).validateTitle(expectedTitle);
});
// Then('I should see the title {string}', async (expectedTitle) => {
// await new Login(getPage()).validateTitle(expectedTitle);
// });

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

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

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

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

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

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

Then('I will fill in checkout info with first name {string} last name {string} and zip {string}', async (firstName, lastName, zip) => {
await new Purchase(getPage()).fillCheckoutInfo(firstName, lastName, zip);
});

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

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

Then('I should see the order confirmation text {string}', async (expectedText) => {
await new Purchase(getPage()).validateConfirmationText(expectedText);
});