From 26feb5d620421361c6197357ff58cd60dd2653e4 Mon Sep 17 00:00:00 2001 From: Akhila Thakur Date: Fri, 20 Mar 2026 15:04:34 -0500 Subject: [PATCH 1/4] fix: correct login page title assertion to 'Swag Labs' --- features/login.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/login.feature b/features/login.feature index fb9f1fa..17cddd3 100644 --- a/features/login.feature +++ b/features/login.feature @@ -5,7 +5,7 @@ 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' From d29bb341e453928006a00711fcbaf0d89e2109c6 Mon Sep 17 00:00:00 2001 From: Akhila Thakur Date: Fri, 20 Mar 2026 15:21:40 -0500 Subject: [PATCH 2/4] step added to check error on login page --- features/login.feature | 2 +- pages/login.page.ts | 7 +++++++ steps/login.steps.ts | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/features/login.feature b/features/login.feature index 17cddd3..5eac8c8 100644 --- a/features/login.feature +++ b/features/login.feature @@ -9,4 +9,4 @@ Feature: Login Feature Scenario: Validate login error message Then I will login as 'locked_out_user' - # TODO: Add a step to validate the error message received \ No newline at end of file + Then I should see the error message "entered username and password doesn't match" \ No newline at end of file diff --git a/pages/login.page.ts b/pages/login.page.ts index 5a01614..49c970b 100644 --- a/pages/login.page.ts +++ b/pages/login.page.ts @@ -23,4 +23,11 @@ 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 errorMessage = await this.page.locator('[data-test="error"]').innerText(); + if (errorMessage !== expectedMessage) { + throw new Error(`Expected error message to be "${expectedMessage}" but found "${errorMessage}"`); + } + } } \ No newline at end of file diff --git a/steps/login.steps.ts b/steps/login.steps.ts index c2aa0d8..0f146e4 100644 --- a/steps/login.steps.ts +++ b/steps/login.steps.ts @@ -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 the error message {string}', async (expectedMessage) => { + await new Login(getPage()).validateErrorMessage(expectedMessage); }); \ No newline at end of file From 279b4330a6d7f54b0a8ac4b7708626afa59c3942 Mon Sep 17 00:00:00 2001 From: Akhila Thakur Date: Fri, 20 Mar 2026 15:29:52 -0500 Subject: [PATCH 3/4] Added Purchase checkout feature page,feature steps --- features/login.feature | 2 +- features/purchase.feature | 18 +++++++-------- pages/checkout.page.ts | 46 +++++++++++++++++++++++++++++++++++++++ steps/checkout.steps.ts | 27 +++++++++++++++++++++++ 4 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 pages/checkout.page.ts create mode 100644 steps/checkout.steps.ts diff --git a/features/login.feature b/features/login.feature index 5eac8c8..4e20511 100644 --- a/features/login.feature +++ b/features/login.feature @@ -9,4 +9,4 @@ Feature: Login Feature Scenario: Validate login error message Then I will login as 'locked_out_user' - Then I should see the error message "entered username and password doesn't match" \ No newline at end of file + Then I should see the error message "Epic sadface: Sorry, this user has been locked out." \ No newline at end of file diff --git a/features/purchase.feature b/features/purchase.feature index 2863478..148ab94 100644 --- a/features/purchase.feature +++ b/features/purchase.feature @@ -3,12 +3,12 @@ Feature: Purchase Feature Background: Given I open the "https://www.saucedemo.com/" page - Scenario: Validate successful purchase text - Then I will login as 'standard_user' - Then I will add the backpack to the cart - # TODO: Select the cart (top-right) - # TODO: Select 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!' \ No newline at end of file + Scenario: Validate successful purchase text + Then I will login as 'standard_user' + Then I will add the backpack to the cart + Then select the cart + Then select Checkout + Then fill in "John" "Doe" and "12345" + Then select Continue + Then select Finish + Then should see the confirmation text "Thank you for your order!" \ No newline at end of file diff --git a/pages/checkout.page.ts b/pages/checkout.page.ts new file mode 100644 index 0000000..0431de6 --- /dev/null +++ b/pages/checkout.page.ts @@ -0,0 +1,46 @@ +import { Page } from "@playwright/test" + +export class Checkout { + private readonly page: Page + private readonly cartIcon: string = 'a.shopping_cart_link' + private readonly checkoutButton: string = 'button[id="checkout"]' + private readonly firstNameField: string = 'input[id="first-name"]' + private readonly lastNameField: string = 'input[id="last-name"]' + private readonly postalCodeField: string = 'input[id="postal-code"]' + private readonly continueButton: string = 'input[id="continue"]' + private readonly finishButton: string = 'button[id="finish"]' + private readonly confirmationHeader: string = 'h2.complete-header' + + constructor(page: Page) { + this.page = page; + } + + public async goToCart() { + await this.page.locator(this.cartIcon).click(); + } + + public async selectCheckout() { + await this.page.locator(this.checkoutButton).click(); + } + + public async fillInDetails(firstName: string, lastName: string, postalCode: string) { + await this.page.locator(this.firstNameField).fill(firstName); + await this.page.locator(this.lastNameField).fill(lastName); + await this.page.locator(this.postalCodeField).fill(postalCode); + } + + 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 confirmationText = await this.page.locator(this.confirmationHeader).innerText(); + if (confirmationText !== expectedText) { + throw new Error(`Expected confirmation text to be "${expectedText}" but found "${confirmationText}"`); + } + } +} diff --git a/steps/checkout.steps.ts b/steps/checkout.steps.ts new file mode 100644 index 0000000..c33949e --- /dev/null +++ b/steps/checkout.steps.ts @@ -0,0 +1,27 @@ +import { Then } from '@cucumber/cucumber'; +import { getPage } from '../playwrightUtilities'; +import { Checkout } from '../pages/checkout.page'; + +Then('select the cart', async () => { + await new Checkout(getPage()).goToCart(); +}); + +Then('select Checkout', async () => { + await new Checkout(getPage()).selectCheckout(); +}); + +Then('fill in {string} {string} and {string}', async (firstName: string, lastName: string, postalCode: string) => { + await new Checkout(getPage()).fillInDetails(firstName, lastName, postalCode); +}); + +Then('select Continue', async () => { + await new Checkout(getPage()).selectContinue(); +}); + +Then('select Finish', async () => { + await new Checkout(getPage()).selectFinish(); +}); + +Then('should see the confirmation text {string}', async (expectedText: string) => { + await new Checkout(getPage()).validateConfirmationText(expectedText); +}); From e5582c005a35a51d3a6423dc652d8b36918e4266 Mon Sep 17 00:00:00 2001 From: Akhila Thakur Date: Fri, 20 Mar 2026 15:50:02 -0500 Subject: [PATCH 4/4] added the product sort by price steps --- features/product.feature | 14 +++++++------- pages/product.page.ts | 18 ++++++++++++++++++ steps/product.steps.ts | 8 ++++++++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/features/product.feature b/features/product.feature index 8a7ceab..cd8d880 100644 --- a/features/product.feature +++ b/features/product.feature @@ -3,11 +3,11 @@ Feature: Product Feature Background: Given I open the "https://www.saucedemo.com/" page - # 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 - Then I will login as 'standard_user' - # TODO: Sort the items by - # TODO: Validate all 6 items are sorted correctly by price + Scenario Outline: Validate product sort by price + Then I will login as 'standard_user' + Then sort the items by "" + Then all items are sorted correctly by "" Examples: - # TODO: extend the datatable to paramterize this test - | sort | \ No newline at end of file + | sort | + | Price (low to high) | + | Price (high to low) | \ No newline at end of file diff --git a/pages/product.page.ts b/pages/product.page.ts index 14bedb1..e1da034 100644 --- a/pages/product.page.ts +++ b/pages/product.page.ts @@ -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 = 'select[data-test="product-sort-container"]' + private readonly itemPrices: string = '.inventory_item_price' constructor(page: Page) { this.page = page; @@ -11,4 +13,20 @@ export class Product { public async addBackPackToCart() { await this.page.locator(this.addToCart).click() } + + public async sortBy(sortOption: string) { + await this.page.locator(this.sortDropdown).selectOption({ label: sortOption }); + } + + public async validateSortedByPrice(sortOption: string) { + const priceElements = await this.page.locator(this.itemPrices).allInnerTexts(); + const prices = priceElements.map(p => parseFloat(p.replace('$', ''))); + + const isAscending = sortOption === 'Price (low to high)'; + const sorted = [...prices].sort((a, b) => isAscending ? a - b : b - a); + + if (JSON.stringify(prices) !== JSON.stringify(sorted)) { + throw new Error(`Expected prices to be sorted by "${sortOption}" but found: ${prices.join(', ')}`); + } + } } \ No newline at end of file diff --git a/steps/product.steps.ts b/steps/product.steps.ts index bb52fb9..49c1f11 100644 --- a/steps/product.steps.ts +++ b/steps/product.steps.ts @@ -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('sort the items by {string}', async (sortOption: string) => { + await new Product(getPage()).sortBy(sortOption); +}); + +Then('all items are sorted correctly by {string}', async (sortOption: string) => { + await new Product(getPage()).validateSortedByPrice(sortOption); }); \ No newline at end of file