From cad3393097ecdbb6f57d35d600652cf9e834a9ce Mon Sep 17 00:00:00 2001 From: siva3212 Date: Mon, 1 Jun 2026 14:23:23 -0500 Subject: [PATCH] Cpmpleted playwright cucmber assessment --- features/login.feature | 6 +-- features/product.feature | 20 +++++---- features/purchase.feature | 12 ++--- package-lock.json | 2 +- pages/login.page.ts | 9 +++- pages/product.page.ts | 93 ++++++++++++++++++++++++++++++++++++++- playwrightUtilities.ts | 4 +- steps/login.steps.ts | 3 ++ steps/product.steps.ts | 48 +++++++++++++++++++- 9 files changed, 172 insertions(+), 25 deletions(-) diff --git a/features/login.feature b/features/login.feature index fb9f1fa5..16fcf8f6 100644 --- a/features/login.feature +++ b/features/login.feature @@ -4,9 +4,9 @@ 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" + 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 \ No newline at end of file + Then I should see the login error message "Epic sadface: Sorry, this user has been locked out." + \ No newline at end of file diff --git a/features/product.feature b/features/product.feature index 8a7ceab9..e4a9c719 100644 --- a/features/product.feature +++ b/features/product.feature @@ -1,13 +1,15 @@ Feature: Product Feature - Background: +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 - Examples: - # TODO: extend the datatable to paramterize this test - | sort | \ No newline at end of file +Scenario Outline: Validate product sort by price + +Then I will login as 'standard_user' +Then I sort products by "" +Then I validate products are sorted correctly by "" + +Examples: +| sort | +| Price (low to high) | +| Price (high to low) | \ No newline at end of file diff --git a/features/purchase.feature b/features/purchase.feature index 28634789..a70ef277 100644 --- a/features/purchase.feature +++ b/features/purchase.feature @@ -6,9 +6,9 @@ Feature: Purchase Feature 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 + Then I select the cart + Then I select checkout + Then I fill checkout information + Then I select continue + Then I select finish + Then I should see purchase success message "Thank you for your order!" \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b90d7c6c..b5c47aa5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "Playwright-Project", + "name": "Playwright-Cucumber-Exercise", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/pages/login.page.ts b/pages/login.page.ts index 5a01614b..4431b713 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() } -} \ No newline at end of file + public async validateErrorMessage(expectedMessage: string) { + const errorMessage = await this.page.locator('[data-test="error"]').textContent(); + + if (errorMessage !== expectedMessage) { + throw new Error(`Expected error message to be ${expectedMessage} but found ${errorMessage}`); + } +} +} diff --git a/pages/product.page.ts b/pages/product.page.ts index 14bedb1b..04ff5711 100644 --- a/pages/product.page.ts +++ b/pages/product.page.ts @@ -1,14 +1,103 @@ 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 addToCart: string = + 'button[id="add-to-cart-sauce-labs-backpack"]' + + private readonly cart: string = + '.shopping_cart_link' + + private readonly checkout: string = + '#checkout' + + private readonly firstName: string = + '#first-name' + + private readonly lastName: string = + '#last-name' + + private readonly zipCode: string = + '#postal-code' + + private readonly continueBtn: string = + '#continue' + + private readonly finishBtn: string = + '#finish' + + private readonly successText: string = + '.complete-header' constructor(page: Page) { - this.page = page; + this.page = page } public async addBackPackToCart() { await this.page.locator(this.addToCart).click() } + + public async selectCart() { + await this.page.locator(this.cart).click() + } + + public async selectCheckout() { + await this.page.locator(this.checkout).click() + } + + public async fillCheckoutInformation() { + const firstName = 'Siva' + const lastName = 'Test' + const zip = '12345' + + await this.page.locator(this.firstName).fill(firstName) + await this.page.locator(this.lastName).fill(lastName) + await this.page.locator(this.zipCode).fill(zip) + } + + public async selectContinue() { + await this.page.locator(this.continueBtn).click() + } + + public async selectFinish() { + await this.page.locator(this.finishBtn).click() + } + + public async validateSuccessMessage(expected: string) { + const actual = await this.page.locator(this.successText).textContent() + + if (actual !== expected) { + throw new Error(`Expected ${expected} but found ${actual}`) + } + } + + public async sortProductsBy(sort: string) { + await this.page + .locator('.product_sort_container') + .selectOption({ label: sort }) + } + + public async validateProductsSortedByPrice(sort: string) { + const prices = await this.page + .locator('.inventory_item_price') + .allTextContents() + + const values = prices.map(price => + Number(price.replace('$', '')) + ) + + const expected = [...values] + + if (sort === 'Price (low to high)') { + expected.sort((a, b) => a - b) + } else { + expected.sort((a, b) => b - a) + } + + if (JSON.stringify(values) !== JSON.stringify(expected)) { + throw new Error(`Products not sorted correctly for ${sort}`) + } + } } \ No newline at end of file diff --git a/playwrightUtilities.ts b/playwrightUtilities.ts index 93244a29..69a787fc 100644 --- a/playwrightUtilities.ts +++ b/playwrightUtilities.ts @@ -6,7 +6,9 @@ const DEFAULT_TIMEOUT = 30000; export const initializeBrowser = async () => { if (!browser) { - browser = await chromium.launch({ headless: false }); + browser = await chromium.launch({ + channel: "chrome" +}); } }; diff --git a/steps/login.steps.ts b/steps/login.steps.ts index c2aa0d80..99cb5104 100644 --- a/steps/login.steps.ts +++ b/steps/login.steps.ts @@ -8,4 +8,7 @@ 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 login error message {string}', async function (message) { + await new Login(getPage()).validateErrorMessage(message); }); \ No newline at end of file diff --git a/steps/product.steps.ts b/steps/product.steps.ts index bb52fb98..54935b5f 100644 --- a/steps/product.steps.ts +++ b/steps/product.steps.ts @@ -3,5 +3,49 @@ import { getPage } from '../playwrightUtilities'; import { Product } from '../pages/product.page'; Then('I will add the backpack to the cart', async () => { - await new Product(getPage()).addBackPackToCart(); -}); \ No newline at end of file + await new Product(getPage()).addBackPackToCart(); +}); + +Then('I select the cart', async () => { + await new Product(getPage()).selectCart(); +}); + +Then('I select checkout', async () => { + await new Product(getPage()).selectCheckout(); +}); + +Then('I fill checkout information', async () => { + await new Product(getPage()).fillCheckoutInformation(); +}); + +Then('I select continue', async () => { + await new Product(getPage()).selectContinue(); +}); + +Then('I select finish', async () => { + await new Product(getPage()).selectFinish(); +}); + +Then( + 'I should see purchase success message {string}', + async (message) => { + await new Product(getPage()) + .validateSuccessMessage(message); + } +); + +Then( + 'I sort products by {string}', + async (sort) => { + await new Product(getPage()) + .sortProductsBy(sort); + } +); + +Then( + 'I validate products are sorted correctly by {string}', + async (sort) => { + await new Product(getPage()) + .validateProductsSortedByPrice(sort); + } +); \ No newline at end of file