From ab2bf6cd64c4c6a2f0d2b46b064e59565ecfc458 Mon Sep 17 00:00:00 2001 From: Alphabin Date: Thu, 28 Aug 2025 17:08:14 +0530 Subject: [PATCH 01/25] Initial commit: Playwright tests with TestDino integration --- .github/workflows/test.yml | 26 ++++++++++++++------------ playwright.config.js | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 47f397f..645dcff 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,6 +5,8 @@ name: Run Playwright tests on: + push: # runs on every push + pull_request: # runs on new PRs or PR updates schedule: - cron: '30 3 * * 1-5' workflow_dispatch: @@ -29,17 +31,17 @@ jobs: node-version: '18' - name: Create .env file run: | - echo "USERNAME=${{ secrets.USERNAME }}" >> .env - echo "USERNAME1=${{ secrets.USERNAME1 }}" >> .env - echo "PASSWORD=${{ secrets.PASSWORD }}" >> .env - echo "NEW_PASSWORD=${{ secrets.NEW_PASSWORD }}" >> .env - echo "FIRST_NAME=${{ secrets.FIRST_NAME }}" >> .env - echo "STREET_NAME=${{ secrets.STREET_NAME }}" >> .env - echo "CITY=${{ secrets.CITY }}" >> .env - echo "STATE=${{ secrets.STATE }}" >> .env - echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env - echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env - + echo "USERNAME=${{ secrets.USERNAME }}" >> .env + echo "PASSWORD=${{ secrets.PASSWORD }}" >> .env + echo "PASSWORD=${{ secrets.PASSWORD }}" >> .env + echo "NEW_PASSWORD=${{ secrets.NEW_PASSWORD }}" >> .env + echo "FIRST_NAME=${{ secrets.FIRST_NAME }}" >> .env + echo "STREET_NAME=${{ secrets.STREET_NAME }}" >> .env + echo "CITY=${{ secrets.CITY }}" >> .env + echo "STATE=${{ secrets.STATE }}" >> .env + echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env + echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env + - name: Cache npm dependencies uses: actions/cache@v3 with: @@ -111,6 +113,6 @@ jobs: - name: Send TestDino report run: | npx --yes tdpw ./playwright-report \ - --token="trx_production_75deca4b6fbb32963853ca189506496d60835761c32e54fd9f6787b00c86158f" \ + --token="trx_production_b0b86d5f044ecfa1d02cbdfa2f9d644dd7e4889912e0494b802abfe8f251db8e" \ --upload-html \ --verbose \ No newline at end of file diff --git a/playwright.config.js b/playwright.config.js index c3dd637..f6c3911 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -24,7 +24,7 @@ export default defineConfig({ use: { baseURL: 'https://demo.alphabin.co/', - headless: false, + headless: true, trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'retain-on-failure', From b96de44a114b9cf02f741dd129d795caaecc4462 Mon Sep 17 00:00:00 2001 From: testdino Date: Fri, 29 Aug 2025 15:27:55 +0530 Subject: [PATCH 02/25] Initial commit --- pages/AllPages.js | 3 + pages/CartPage.js | 4 ++ pages/ContactUsPage.js | 40 +++++++++++ pages/HomePage.js | 22 +++++- pages/ProductDetailsPage.js | 52 ++++++++++++++- tests/example.spec.js | 130 +++++++++++++++++++++++++++++++++++- 6 files changed, 248 insertions(+), 3 deletions(-) create mode 100644 pages/ContactUsPage.js diff --git a/pages/AllPages.js b/pages/AllPages.js index f9f7c91..c4c22f0 100644 --- a/pages/AllPages.js +++ b/pages/AllPages.js @@ -9,6 +9,7 @@ import CheckoutPage from "./CheckoutPage"; import OrderPage from "./OrderPage"; // Import OrderPage import UserPage from "./UserPage"; // Import UserPage import OrderDetailsPage from "./OrderDetailsPage"; +import ContactUsPage from "./ContactUsPage"; class AllPages { constructor(page) { @@ -24,6 +25,8 @@ class AllPages { this.orderPage = new OrderPage(page); // Instantiate OrderPage this.userPage = new UserPage(page); // Instantiate UserPage this.orderDetailsPage = new OrderDetailsPage(page); + this.contactUsPage = new ContactUsPage(page); + } } diff --git a/pages/CartPage.js b/pages/CartPage.js index 9de37c5..c04f233 100644 --- a/pages/CartPage.js +++ b/pages/CartPage.js @@ -124,6 +124,10 @@ class CartPage extends BasePage{ await this.page.waitForTimeout(2000); await this.page.locator(this.locators.checkoutButton).click({ force: true }); } + + async verifyIncreasedQuantity(expectedQuantity) { + await expect(this.page.locator(this.locators.cartItemQuantity)).toHaveText(expectedQuantity); + } } export default CartPage; \ No newline at end of file diff --git a/pages/ContactUsPage.js b/pages/ContactUsPage.js new file mode 100644 index 0000000..5053db5 --- /dev/null +++ b/pages/ContactUsPage.js @@ -0,0 +1,40 @@ +import BasePage from './BasePage.js'; +import { expect } from '@playwright/test'; + +class ContactUsPage extends BasePage{ + + /** + * @param {import('@playwright/test').Page} page + */ + constructor(page) { + super(page); + this.page = page; + } + + locators = { + contactUsBtn: `[data-testid="header-menu-contact-us"]`, + contactUsTitle: `[data-testid="contact-us-heading"]`, + firstNameInput: `[data-testid="contact-us-first-name-input"]`, + lastNameInput: `[data-testid="contact-us-last-name-input"]`, + subjectInput: `[data-testid="contact-us-subject-input"]`, + messageInput: `[data-testid="contact-us-message-input"]`, + sendMessageBtn: `//button[@data-testid="contact-us-submit-button"]`, + successMessage: `[data-testid="contact-us-success-message"]` + } + + async assertContactUsTitle() { + await expect(this.page.locator(this.locators.contactUsTitle)).toHaveText('Contact Us'); + } + + async fillContactUsForm() { + await this.page.fill(this.locators.firstNameInput, 'John'); + await this.page.fill(this.locators.lastNameInput, 'Doe'); + await this.page.fill(this.locators.subjectInput, 'Test Subject'); + await this.page.fill(this.locators.messageInput, 'This is a test message.'); + await this.page.click(this.locators.sendMessageBtn); + } + async verifySuccessContactUsFormSubmission() { + await expect(this.page.locator(this.locators.successMessage)).toBeVisible(); + } +} +export default ContactUsPage; \ No newline at end of file diff --git a/pages/HomePage.js b/pages/HomePage.js index 72c55b3..593898a 100644 --- a/pages/HomePage.js +++ b/pages/HomePage.js @@ -23,7 +23,8 @@ class HomePage extends BasePage{ AddCartNotification: `div[role="status"][aria-live="polite"]:has-text("Added to the cart")`, priceRangeSlider2 : `[data-testid="all-products-price-range-input-1"]`, priceRangeSlider1 : `[data-testid="all-products-price-range-input-0"]`, - filterButton : `[data-testid="all-products-filter-toggle"]` + filterButton : `[data-testid="all-products-filter-toggle"]`, + aboutUsTitle: `[data-testid="about-us-title"]`, } } @@ -88,6 +89,25 @@ class HomePage extends BasePage{ return this.page.locator(this.locators.navbar.showNowButton); } + async clickOnContactUsLink() { + await this.getContactUsNav().click(); + } + + async clickBackToHomeButton() { + await this.getHomeNav().click(); + } + + async assertHomePage() { + await expect(this.page.locator(this.locators.navbar.homeNav)).toBeVisible({ timeout: 10000 }); + } + + async clickAboutUsNav() { + await this.getAboutUsNav().click(); + } + + async assertAboutUsTitle() { + await expect(this.page.locator(this.locators.navbar.aboutUsTitle)).toBeVisible({ timeout: 10000 }); + } } export default HomePage; \ No newline at end of file diff --git a/pages/ProductDetailsPage.js b/pages/ProductDetailsPage.js index 1256cbf..748b3ef 100644 --- a/pages/ProductDetailsPage.js +++ b/pages/ProductDetailsPage.js @@ -17,7 +17,16 @@ class ProductDetailsPage extends BasePage{ addToCartButton: 'ADD TO CART', headerCartIcon: 'header-cart-icon', productAdditionalInfoTab : `[data-testid="additional-info-tab"]`, - productReviewsTab : `[data-testid="reviews-tab"]` + productReviewsTab : `[data-testid="reviews-tab"]`, + writeReviewBtn: `//button[@data-testid="write-review-button"]`, + yourNameInput: `[data-testid="review-form-name-input"]`, + emailInput: `[data-testid="review-form-email-input"]`, + ratingStars: `[data-testid="review-form-rating-4"]`, + reviewTitleInput: `[data-testid="review-form-title-input"]`, + giveYourOpinionInput: `[data-testid="review-form-review-input"]`, + submitBtn: `[data-testid="review-form-submit-button"]`, + editReviewBtn: `[data-testid="edit-review-button"]`, + deleteReviewBtn: `[data-testid="delete-review-button"]` } @@ -85,6 +94,47 @@ class ProductDetailsPage extends BasePage{ async clickCartIcon() { await this.getCartIcon().click(); } + + async clickOnWriteAReviewBtn() { + await this.page.locator(this.locators.writeReviewBtn).click(); + } + + async fillReviewForm() { + await this.page.fill(this.locators.yourNameInput, 'John Doe'); + await this.page.fill(this.locators.emailInput, 'testing@gmail.com'); + await this.page.click(this.locators.ratingStars); + await this.page.fill(this.locators.reviewTitleInput, 'Great Product'); + await this.page.fill(this.locators.giveYourOpinionInput, 'This product exceeded my expectations. Highly recommend!'); + await this.page.click(this.locators.submitBtn); + } + async assertSubmittedReview({ name, title, opinion }) { + await this.page.waitForTimeout(3000); // Wait for 1 second to ensure the form is ready + await expect(this.page.locator(`text=${name}`)).toBeVisible(); + await expect(this.page.locator(`text=${title}`)).toBeVisible(); + await expect(this.page.locator(`text=${opinion}`)).toBeVisible(); + } + + async clickOnEditReviewBtn() { + await this.page.locator(this.locators.editReviewBtn).click(); + } + + async updateReviewForm() { + await this.page.waitForTimeout(3000); // Wait for 1 second to ensure the form is ready + await this.page.fill(this.locators.reviewTitleInput, 'Updated Review Title'); + await this.page.fill(this.locators.giveYourOpinionInput, 'This is an updated review opinion.'); + await this.page.click(this.locators.submitBtn); + } + + async assertUpdatedReview({ title, opinion }) { + await this.page.waitForTimeout(3000); // Wait for 1 second to ensure the form is ready + await expect(this.page.locator(`text=${title}`)).toBeVisible(); + await expect(this.page.locator(`text=${opinion}`)).toBeVisible(); + } + + async clickOnDeleteReviewBtn() { + await this.page.locator(this.locators.deleteReviewBtn).click(); + await this.page.keyboard.press('Enter'); + } } export default ProductDetailsPage; \ No newline at end of file diff --git a/tests/example.spec.js b/tests/example.spec.js index cf0e23f..bb9660a 100644 --- a/tests/example.spec.js +++ b/tests/example.spec.js @@ -461,4 +461,132 @@ test('Verify That a New User Can Successfully Complete the Journey from Registra await allPages.checkoutPage.clickOnPlaceOrder(); await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); }) -}); \ No newline at end of file +}); + +test('Verify that the new user is able to Sign Up, Log In, and Navigate to the Home Page Successfully', async () => { + const email = `test+${Date.now()}@test.com`; + const firstName = 'Test'; + const lastName = 'User'; + + await test.step('Verify that user can register successfully', async () => { + await allPages.loginPage.clickOnUserProfileIcon(); + await allPages.loginPage.validateSignInPage(); + await allPages.loginPage.clickOnSignupLink(); + await allPages.signupPage.assertSignupPage(); + await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); + await allPages.signupPage.verifySuccessSignUp(); + }) + + await test.step('Verify that user can login successfully', async () => { + await allPages.loginPage.validateSignInPage(); + await allPages.loginPage.login(email, process.env.PASSWORD); + await allPages.loginPage.verifySuccessSignIn(); + await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); + }) +}) + +test('Verify that user is able to fill Contact Us page successfully', async () => { + await login(); + await allPages.homePage.clickOnContactUsLink(); + await allPages.contactUsPage.assertContactUsTitle(); + await allPages.contactUsPage.fillContactUsForm(); + await allPages.contactUsPage.verifySuccessContactUsFormSubmission(); +}); + +test('Verify that user is able to submit a product review ', async () => { + await test.step('Login as existing user and navigate to a product', async () => { + await login(); + }) + + await test.step('Navigate to all product section and select a product', async () => { + await allPages.homePage.clickOnShopNowButton(); + await allPages.allProductsPage.assertAllProductsTitle(); + await allPages.allProductsPage.clickNthProduct(1); + }) + + await test.step('Submit a product review and verify submission', async () => { + await allPages.productDetailsPage.clickOnReviewsTab(); + await allPages.productDetailsPage.assertReviewsTab(); + + await allPages.productDetailsPage.clickOnWriteAReviewBtn(); + await allPages.productDetailsPage.fillReviewForm(); + await allPages.productDetailsPage.assertSubmittedReview({ + name: 'John Doe', + title: 'Great Product', + opinion: 'This product exceeded my expectations. Highly recommend!' + }); + }) +}); + +test('Verify that user can edit and delete a product review', async () => { + await test.step('Login as existing user and navigate to a product', async () => { + await login(); + }) + + await test.step('Navigate to all product section and select a product', async () => { + await allPages.homePage.clickOnShopNowButton(); + await allPages.allProductsPage.assertAllProductsTitle(); + await allPages.allProductsPage.clickNthProduct(1); + }) + + await test.step('Submit a product review and verify submission', async () => { + await allPages.productDetailsPage.clickOnReviewsTab(); + await allPages.productDetailsPage.assertReviewsTab(); + + await allPages.productDetailsPage.clickOnWriteAReviewBtn(); + await allPages.productDetailsPage.fillReviewForm(); + await allPages.productDetailsPage.assertSubmittedReview({ + name: 'John Doe', + title: 'Great Product', + opinion: 'This product exceeded my expectations. Highly recommend!' + }); + }) + + await test.step('Edit the submitted review and verify changes', async () => { + await allPages.productDetailsPage.clickOnEditReviewBtn(); + await allPages.productDetailsPage.updateReviewForm(); + await allPages.productDetailsPage.assertUpdatedReview({ + title: 'Updated Review Title', + opinion: 'This is an updated review opinion.' + }) + }); + + await test.step('Delete the submitted review and verify deletion', async () => { + await allPages.productDetailsPage.clickOnDeleteReviewBtn(); + }) +}); + +test('Verify that user can purchase multiple quantities in a single order', async () => { + const productName = 'GoPro HERO10 Black'; + await login(); + await allPages.inventoryPage.clickOnShopNowButton(); + await allPages.inventoryPage.clickOnAllProductsLink(); + await allPages.inventoryPage.searchProduct(productName); + await allPages.inventoryPage.verifyProductTitleVisible(productName); + await allPages.inventoryPage.clickOnAddToCartIcon(); + + await allPages.cartPage.clickOnCartIcon(); + await allPages.cartPage.verifyCartItemVisible(productName); + await allPages.cartPage.clickIncreaseQuantityButton(); + await allPages.cartPage.verifyIncreasedQuantity('3'); + await allPages.cartPage.clickOnCheckoutButton(); + await allPages.checkoutPage.verifyCheckoutTitle(); + await allPages.checkoutPage.verifyProductInCheckout(productName); + await allPages.checkoutPage.selectCashOnDelivery(); + await allPages.checkoutPage.verifyCashOnDeliverySelected(); + await allPages.checkoutPage.clickOnPlaceOrder(); + await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); +}); + +test('Verify that all the navbar are working properly', async () => { + await login(); + await allPages.homePage.clickBackToHomeButton(); + // await allPages.homePage.assertHomePage(); + await allPages.homePage.clickAllProductsNav(); + await allPages.allProductsPage.assertAllProductsTitle(); + await allPages.homePage.clickOnContactUsLink(); + await allPages.contactUsPage.assertContactUsTitle(); + await allPages.homePage.clickAboutUsNav(); + await allPages.homePage.assertAboutUsTitle(); +}); + From 199dffdb1f0037ec8bc275abac9660db2c086303 Mon Sep 17 00:00:00 2001 From: testdino Date: Fri, 29 Aug 2025 15:31:39 +0530 Subject: [PATCH 03/25] Initial commit --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 645dcff..520ce78 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,8 +19,8 @@ jobs: strategy: fail-fast: false matrix: - shardIndex: [1,2,3] - shardTotal: [2] + shardIndex: [1,2,3,4,5] + shardTotal: [5] steps: - uses: actions/checkout@v4 From 97516ee7f89fae87ff6f431e793905435520d065 Mon Sep 17 00:00:00 2001 From: testdino Date: Fri, 29 Aug 2025 16:58:45 +0530 Subject: [PATCH 04/25] Initial commit --- README.md | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e3adf5e..4d0c48f 100644 --- a/README.md +++ b/README.md @@ -1 +1,97 @@ -# alphabin-demo-test-playwright \ No newline at end of file +# alphabin-demo-test-playwright + +Automated end-to-end tests for [Alphabin Demo](https://demo.alphabin.co/) using [Playwright](https://playwright.dev/). + +--- + +## Project Structure + +- `pages/` — Page Object Models +- `tests/` — Test specifications +- `playwright.config.js` — Playwright configuration +- `playwright-report/` — HTML test reports +- `.github/workflows/test.yml` — CI/CD pipeline + +--- + +## Prerequisites + +- [Node.js](https://nodejs.org/) v16+ +- [npm](https://www.npmjs.com/) + +--- + +## Installation + +```sh +npm install +``` + +--- + +## Local Test Execution + +Run all tests: +```sh +npx playwright test +``` + +View the HTML report: +```sh +npx playwright show-report +``` + +--- + +## Testdino Integration + +[Testdino](https://testdino.com/) enables cloud-based Playwright reporting. + +### Local Execution + +After your tests complete and the report is generated in `playwright-report`, upload it to Testdino: + +```sh +npx --yes tdpw ./playwright-report --token="your-token" --upload-html +``` + +Replace the token above with your own Testdino API key. + +See all available commands: +```sh +npx tdpw --help +``` + +--- + +## CI/CD Pipeline Integration + +### GitHub Actions + +Add the following step to your workflow after tests and report generation: + +```yaml +- name: Send Testdino report + run: | + npx --yes tdpw ./playwright-report --token="trx_production_035e6ed4a1a2be1f5a10eb45b837afa25b2740cc8b94ff8baca31ee3fe5e2d15" --upload-html +``` + +Ensure your API key is correctly placed in the command. + +--- + +## Continuous Integration + +Automated test runs and report merging are configured in `.github/workflows/test.yml`. + +--- + +## Contributing + +Pull requests and issues are welcome! + +--- + +## License + +MIT \ No newline at end of file From 776fe529aec05e2c0c721cdec70df15c79ad5413 Mon Sep 17 00:00:00 2001 From: testdino Date: Fri, 29 Aug 2025 18:12:11 +0530 Subject: [PATCH 05/25] added more test cases --- pages/CartPage.js | 21 +++++++++++++++++++++ playwright.config.js | 2 +- tests/example.spec.js | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/pages/CartPage.js b/pages/CartPage.js index c04f233..5b667b8 100644 --- a/pages/CartPage.js +++ b/pages/CartPage.js @@ -1,3 +1,4 @@ +import { start } from 'repl'; import BasePage from './BasePage.js'; import { expect } from '@playwright/test'; @@ -29,6 +30,9 @@ class CartPage extends BasePage{ checkoutButton: '[data-testid="checkout-button"]', viewCartButton: '[data-testid="view-cart-button"]', shoppingCartIcon: `[data-testid="header-cart-icon"]`, + deleteItemButton: '[aria-label="Remove item"]', + cartEmpty: `[data-testid="empty-cart"]`, + startShoppingButton: `[data-testid="continue-shopping-btn"]` } async assertYourCartTitle() { @@ -128,6 +132,23 @@ class CartPage extends BasePage{ async verifyIncreasedQuantity(expectedQuantity) { await expect(this.page.locator(this.locators.cartItemQuantity)).toHaveText(expectedQuantity); } + + async clickOnDeleteProductIcon() { + await this.page.locator(this.locators.deleteItemButton).click(); + } + + async verifyCartItemDeleted() { + await expect(this.page.locator(this.locators.cartItemName)).toHaveCount(0); + } + + async verifyEmptyCartMessage() { + await expect(this.page.locator(this.locators.cartEmpty)).toBeVisible(); + } + + async clickOnStartShoppingButton() { + await this.page.locator(this.locators.startShoppingButton).click(); + } + } export default CartPage; \ No newline at end of file diff --git a/playwright.config.js b/playwright.config.js index f6c3911..c3dd637 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -24,7 +24,7 @@ export default defineConfig({ use: { baseURL: 'https://demo.alphabin.co/', - headless: true, + headless: false, trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'retain-on-failure', diff --git a/tests/example.spec.js b/tests/example.spec.js index bb9660a..9f96433 100644 --- a/tests/example.spec.js +++ b/tests/example.spec.js @@ -590,3 +590,20 @@ test('Verify that all the navbar are working properly', async () => { await allPages.homePage.assertAboutUsTitle(); }); +test.only('Verify that user is able to delete selected product from cart', async () => { + const productName = 'GoPro HERO10 Black'; + await login(); + await allPages.inventoryPage.clickOnShopNowButton(); + await allPages.inventoryPage.clickOnAllProductsLink(); + await allPages.inventoryPage.searchProduct(productName); + await allPages.inventoryPage.verifyProductTitleVisible(productName); + await allPages.inventoryPage.clickOnAddToCartIcon(); + + await allPages.cartPage.clickOnCartIcon(); + await allPages.cartPage.verifyCartItemVisible(productName); + await allPages.cartPage.clickOnDeleteProductIcon(); + await allPages.cartPage.verifyCartItemDeleted(productName); + await allPages.cartPage.verifyEmptyCartMessage(); + await allPages.cartPage.clickOnStartShoppingButton(); + await allPages.allProductsPage.assertAllProductsTitle(); +}); \ No newline at end of file From 7382bcc80f2655924cae02c1453f174f65642cb4 Mon Sep 17 00:00:00 2001 From: testing Date: Fri, 12 Sep 2025 12:45:59 +0530 Subject: [PATCH 06/25] changes applied in the playwright.config file --- README.md | 22 +++++++++++++++++----- playwright.config.js | 11 +++++++---- tests/example.spec.js | 2 +- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 4d0c48f..95c8154 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# alphabin-demo-test-playwright +# Ecommerce demo store - Playwright (javascript) tests -Automated end-to-end tests for [Alphabin Demo](https://demo.alphabin.co/) using [Playwright](https://playwright.dev/). +Automated end-to-end tests for Ecommerce demo store using [Playwright](https://playwright.dev/). --- @@ -47,12 +47,24 @@ npx playwright show-report [Testdino](https://testdino.com/) enables cloud-based Playwright reporting. +> **Important:** +> Make sure your `playwright.config.js` includes both the HTML and JSON reporters. +> The HTML report and JSON report must be available for Testdino to process your test results. + +Example configuration: +```js +reporter: [ + ['html', { outputFolder: 'playwright-report', open: 'never' }], + ['json', { outputFile: './playwright-report/report.json' }], +] +``` + ### Local Execution After your tests complete and the report is generated in `playwright-report`, upload it to Testdino: ```sh -npx --yes tdpw ./playwright-report --token="your-token" --upload-html +npx --yes tdpw ./playwright-report --token="YOUR_TESTDINO_API_KEY" --upload-html ``` Replace the token above with your own Testdino API key. @@ -73,7 +85,7 @@ Add the following step to your workflow after tests and report generation: ```yaml - name: Send Testdino report run: | - npx --yes tdpw ./playwright-report --token="trx_production_035e6ed4a1a2be1f5a10eb45b837afa25b2740cc8b94ff8baca31ee3fe5e2d15" --upload-html + npx --yes tdpw ./playwright-report --token="YOUR_TESTDINO_API_KEY" --upload-html ``` Ensure your API key is correctly placed in the command. @@ -94,4 +106,4 @@ Pull requests and issues are welcome! ## License -MIT \ No newline at end of file +MIT diff --git a/playwright.config.js b/playwright.config.js index c3dd637..4b7761d 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -10,9 +10,7 @@ export default defineConfig({ retries: isCI ? 1 : 0, workers: isCI ? 1 : 1, - timeout: 60 * 1000, // ⏱️ each test fails after 1 min - // In CI we only show a list reporter. The workflow sets --reporter=blob. - // Locally you also get HTML and JSON. + timeout: 60 * 1000, reporter: [ ['html', { outputFolder: 'playwright-report', @@ -24,7 +22,7 @@ export default defineConfig({ use: { baseURL: 'https://demo.alphabin.co/', - headless: false, + headless: true, trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'retain-on-failure', @@ -35,5 +33,10 @@ export default defineConfig({ name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, ], + }); \ No newline at end of file diff --git a/tests/example.spec.js b/tests/example.spec.js index 9f96433..8119a0a 100644 --- a/tests/example.spec.js +++ b/tests/example.spec.js @@ -590,7 +590,7 @@ test('Verify that all the navbar are working properly', async () => { await allPages.homePage.assertAboutUsTitle(); }); -test.only('Verify that user is able to delete selected product from cart', async () => { +test('Verify that user is able to delete selected product from cart', async () => { const productName = 'GoPro HERO10 Black'; await login(); await allPages.inventoryPage.clickOnShopNowButton(); From 7e5bc7d9e1543a9ab280dc3083f278c052cba67f Mon Sep 17 00:00:00 2001 From: testing Date: Fri, 12 Sep 2025 15:05:35 +0530 Subject: [PATCH 07/25] changes applied in the playwright.config file --- .github/workflows/test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 520ce78..c9d55ea 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -112,7 +112,7 @@ jobs: - name: Send TestDino report run: | - npx --yes tdpw ./playwright-report \ - --token="trx_production_b0b86d5f044ecfa1d02cbdfa2f9d644dd7e4889912e0494b802abfe8f251db8e" \ - --upload-html \ - --verbose \ No newline at end of file + npx --yes tdpw ./playwright-report \ + --token="${{ secrets.TESTDINO_TOKEN }}" \ + --upload-html \ + --verbose \ No newline at end of file From 92cc7d0c0e4f6e6ac94bce014940800a4012ed20 Mon Sep 17 00:00:00 2001 From: testing Date: Fri, 12 Sep 2025 16:02:00 +0530 Subject: [PATCH 08/25] updated the yml by adding multiple browser --- .github/workflows/test.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c9d55ea..ef586ad 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,6 +21,7 @@ jobs: matrix: shardIndex: [1,2,3,4,5] shardTotal: [5] + browser: [chromium, firefox] # ✅ added browsers here steps: - uses: actions/checkout@v4 @@ -29,11 +30,11 @@ jobs: uses: actions/setup-node@v3 with: node-version: '18' + - name: Create .env file run: | echo "USERNAME=${{ secrets.USERNAME }}" >> .env echo "PASSWORD=${{ secrets.PASSWORD }}" >> .env - echo "PASSWORD=${{ secrets.PASSWORD }}" >> .env echo "NEW_PASSWORD=${{ secrets.NEW_PASSWORD }}" >> .env echo "FIRST_NAME=${{ secrets.FIRST_NAME }}" >> .env echo "STREET_NAME=${{ secrets.STREET_NAME }}" >> .env @@ -55,14 +56,14 @@ jobs: npm ci npx playwright install --with-deps - - name: Run shard ${{ matrix.shardIndex }} - run: npx playwright test --project=chromium --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + - name: Run shard ${{ matrix.shardIndex }} on ${{ matrix.browser }} + run: npx playwright test --project=${{ matrix.browser }} --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - name: Upload blob report if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: - name: blob-report-${{ matrix.shardIndex }} + name: blob-report-${{ matrix.browser }}-${{ matrix.shardIndex }} path: ./blob-report retention-days: 1 @@ -115,4 +116,4 @@ jobs: npx --yes tdpw ./playwright-report \ --token="${{ secrets.TESTDINO_TOKEN }}" \ --upload-html \ - --verbose \ No newline at end of file + --verbose From 4dd014fd11378f47bf08c2a1f63ace85b1576c51 Mon Sep 17 00:00:00 2001 From: testing Date: Fri, 12 Sep 2025 16:43:57 +0530 Subject: [PATCH 09/25] updated the yml by adding multiple browser --- .github/workflows/test.yml | 58 ++++++++++++++++++++++++++++---------- playwright.config.js | 22 +++++++++++++-- tests/example.spec.js | 40 +++++++++++++------------- 3 files changed, 82 insertions(+), 38 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ef586ad..a18c768 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,12 +1,9 @@ # .github/workflows/playwright-daily.yml -# Runs Playwright test shards every day at **11 : 42 AM IST** (06 : 12 UTC) -# plus anytime you trigger it manually from the Actions tab. - name: Run Playwright tests on: - push: # runs on every push - pull_request: # runs on new PRs or PR updates + push: + pull_request: schedule: - cron: '30 3 * * 1-5' workflow_dispatch: @@ -19,9 +16,40 @@ jobs: strategy: fail-fast: false matrix: - shardIndex: [1,2,3,4,5] - shardTotal: [5] - browser: [chromium, firefox] # ✅ added browsers here + include: + # Chromium → 25% (5 tests, 2 shards) + - browser: chromium + shardIndex: 1 + shardTotal: 8 + - browser: chromium + shardIndex: 2 + shardTotal: 8 + + # Firefox → 25% (5 tests, 2 shards) + - browser: firefox + shardIndex: 3 + shardTotal: 8 + - browser: firefox + shardIndex: 4 + shardTotal: 8 + + # WebKit → 25% (5 tests, 2 shards) + - browser: webkit + shardIndex: 5 + shardTotal: 8 + - browser: webkit + shardIndex: 6 + shardTotal: 8 + + # Android → 10% (2 tests, 1 shard) + - browser: 'Pixel 5' + shardIndex: 7 + shardTotal: 8 + + # iOS → 10% (2 tests, 1 shard) + - browser: 'iPhone 13' + shardIndex: 8 + shardTotal: 8 steps: - uses: actions/checkout@v4 @@ -42,7 +70,7 @@ jobs: echo "STATE=${{ secrets.STATE }}" >> .env echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env - + - name: Cache npm dependencies uses: actions/cache@v3 with: @@ -57,7 +85,7 @@ jobs: npx playwright install --with-deps - name: Run shard ${{ matrix.shardIndex }} on ${{ matrix.browser }} - run: npx playwright test --project=${{ matrix.browser }} --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + run: npx playwright test --project="${{ matrix.browser }}" --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - name: Upload blob report if: ${{ !cancelled() }} @@ -70,7 +98,7 @@ jobs: merge-reports: name: Merge Reports needs: run-tests - if: always() # run even if some shards fail + if: always() runs-on: ubuntu-latest steps: @@ -113,7 +141,7 @@ jobs: - name: Send TestDino report run: | - npx --yes tdpw ./playwright-report \ - --token="${{ secrets.TESTDINO_TOKEN }}" \ - --upload-html \ - --verbose + npx --yes tdpw ./playwright-report \ + --token="${{ secrets.TESTDINO_TOKEN }}" \ + --upload-html \ + --verbose diff --git a/playwright.config.js b/playwright.config.js index 4b7761d..f6d55df 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -16,7 +16,7 @@ export default defineConfig({ outputFolder: 'playwright-report', open: 'never' }], - ['blob', { outputDir: 'blob-report' }], // Use blob reporter + ['blob', { outputDir: 'blob-report' }], // Blob reporter for merging ['json', { outputFile: './playwright-report/report.json' }], ], @@ -32,11 +32,27 @@ export default defineConfig({ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, + grep: /@chromium/, // only run tests tagged @chromium }, { name: 'firefox', use: { ...devices['Desktop Firefox'] }, + grep: /@firefox/, // only run tests tagged @firefox + }, + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + grep: /@webkit/, // only run tests tagged @webkit + }, + { + name: 'android', + use: { ...devices['Pixel 5'] }, + grep: /@android/, // only run tests tagged @android + }, + { + name: 'ios', + use: { ...devices['iPhone 12'] }, + grep: /@ios/, // only run tests tagged @ios }, ], - -}); \ No newline at end of file +}); diff --git a/tests/example.spec.js b/tests/example.spec.js index 8119a0a..184ddb5 100644 --- a/tests/example.spec.js +++ b/tests/example.spec.js @@ -28,19 +28,19 @@ async function logout() { await allPages.loginPage.clickOnLogoutButton(); } -test('Verify that user can login and logout successfully', async () => { +test('Verify that user can login and logout successfully @chromium', async () => { await login(); await logout(); }); -test('Verify that user can update personal information', async () => { +test('Verify that user can update personal information @chromium', async () => { await login(); await allPages.userPage.clickOnUserProfileIcon(); await allPages.userPage.updatePersonalInfo(); await allPages.userPage.verifyPersonalInfoUpdated(); }); -test('Verify that User Can Add, Edit, and Delete Addresses after Logging In', async () => { +test('Verify that User Can Add, Edit, and Delete Addresses after Logging In @chromium', async () => { await login(); await test.step('Verify that user is able to add address successfully', async () => { @@ -62,7 +62,7 @@ test('Verify that User Can Add, Edit, and Delete Addresses after Logging In', as }); }); -test('Verify that user can change password successfully', async () => { +test('Verify that user can change password successfully @chromium', async () => { await test.step('Login with existing password', async () => { await login1(); }); @@ -88,7 +88,7 @@ test('Verify that user can change password successfully', async () => { }) }); -test('Verify that the New User is able to add Addresses in the Address section', async () => { +test('Verify that the New User is able to add Addresses in the Address section @chromium', async () => { await login(); await allPages.userPage.clickOnUserProfileIcon(); await allPages.userPage.clickOnAddressTab(); @@ -97,7 +97,7 @@ test('Verify that the New User is able to add Addresses in the Address section', await allPages.userPage.fillAddressForm(); }); -test('Verify that User Can Complete the Journey from Login to Order Placement', async () => { +test('Verify that User Can Complete the Journey from Login to Order Placement @firefox', async () => { const productName = 'GoPro HERO10 Black'; await login(); await allPages.inventoryPage.clickOnShopNowButton(); @@ -117,7 +117,7 @@ test('Verify that User Can Complete the Journey from Login to Order Placement', await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); }); -test('Verify user can place and cancel an order', async () => { +test('Verify user can place and cancel an order @firefox', async () => { const productName = 'GoPro HERO10 Black'; const productPriceAndQuantity = '₹49,999 × 1'; const productQuantity = '1'; @@ -175,7 +175,7 @@ test('Verify user can place and cancel an order', async () => { }) }); -test('Verify that a New User Can Successfully Complete the Journey from Registration to a Single Order Placement', async () => { +test('Verify that a New User Can Successfully Complete the Journey from Registration to a Single Order Placement @firefox', async () => { // fresh test data const email = `test+${Date.now()}@test.com`; const firstName = 'Test'; @@ -287,7 +287,7 @@ test('Verify that a New User Can Successfully Complete the Journey from Registra }); }); -test('Verify that user add product to cart before logging in and then complete order after logging in', async () => { +test('Verify that user add product to cart before logging in and then complete order after logging in @firefox', async () => { await test.step('Navigate and add product to cart before logging in', async () => { await allPages.homePage.clickOnShopNowButton(); await allPages.homePage.clickProductImage(); @@ -307,7 +307,7 @@ test('Verify that user add product to cart before logging in and then complete o }) }); -test('Verify that user can filter products by price range', async () => { +test('Verify that user can filter products by price range @firefox', async () => { await login(); await allPages.homePage.clickOnShopNowButton(); await allPages.homePage.clickOnFilterButton(); @@ -315,7 +315,7 @@ test('Verify that user can filter products by price range', async () => { await allPages.homePage.clickOnFilterButton(); }); -test('Verify if user can add product to wishlist, moves it to card and then checks out', async () => { +test('Verify if user can add product to wishlist, moves it to card and then checks out @webkit', async () => { await login(); await test.step('Add product to wishlistand then add to cart', async () => { @@ -339,7 +339,7 @@ test('Verify if user can add product to wishlist, moves it to card and then chec }); -test('Verify new user views and cancels an order in my orders', async () => { +test('Verify new user views and cancels an order in my orders @webkit', async () => { const email = `test+${Date.now()}@test.com`; const firstName = 'Test'; const lastName = 'User'; @@ -397,7 +397,7 @@ test('Verify new user views and cancels an order in my orders', async () => { }); }); -test('Verify That a New User Can Successfully Complete the Journey from Registration to a Multiple Order Placement', async () => { +test('Verify That a New User Can Successfully Complete the Journey from Registration to a Multiple Order Placement @webkit', async () => { const email = `test+${Date.now()}@test.com`; const firstName = 'Test'; const lastName = 'User'; @@ -463,7 +463,7 @@ test('Verify That a New User Can Successfully Complete the Journey from Registra }) }); -test('Verify that the new user is able to Sign Up, Log In, and Navigate to the Home Page Successfully', async () => { +test('Verify that the new user is able to Sign Up, Log In, and Navigate to the Home Page Successfully @webkit', async () => { const email = `test+${Date.now()}@test.com`; const firstName = 'Test'; const lastName = 'User'; @@ -485,7 +485,7 @@ test('Verify that the new user is able to Sign Up, Log In, and Navigate to the H }) }) -test('Verify that user is able to fill Contact Us page successfully', async () => { +test('Verify that user is able to fill Contact Us page successfully @webkit', async () => { await login(); await allPages.homePage.clickOnContactUsLink(); await allPages.contactUsPage.assertContactUsTitle(); @@ -493,7 +493,7 @@ test('Verify that user is able to fill Contact Us page successfully', async () = await allPages.contactUsPage.verifySuccessContactUsFormSubmission(); }); -test('Verify that user is able to submit a product review ', async () => { +test('Verify that user is able to submit a product review @andriod', async () => { await test.step('Login as existing user and navigate to a product', async () => { await login(); }) @@ -518,7 +518,7 @@ test('Verify that user is able to submit a product review ', async () => { }) }); -test('Verify that user can edit and delete a product review', async () => { +test('Verify that user can edit and delete a product review @andriod', async () => { await test.step('Login as existing user and navigate to a product', async () => { await login(); }) @@ -556,7 +556,7 @@ test('Verify that user can edit and delete a product review', async () => { }) }); -test('Verify that user can purchase multiple quantities in a single order', async () => { +test('Verify that user can purchase multiple quantities in a single order @ios', async () => { const productName = 'GoPro HERO10 Black'; await login(); await allPages.inventoryPage.clickOnShopNowButton(); @@ -578,7 +578,7 @@ test('Verify that user can purchase multiple quantities in a single order', asyn await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); }); -test('Verify that all the navbar are working properly', async () => { +test('Verify that all the navbar are working properly @ios', async () => { await login(); await allPages.homePage.clickBackToHomeButton(); // await allPages.homePage.assertHomePage(); @@ -590,7 +590,7 @@ test('Verify that all the navbar are working properly', async () => { await allPages.homePage.assertAboutUsTitle(); }); -test('Verify that user is able to delete selected product from cart', async () => { +test('Verify that user is able to delete selected product from cart @chromium', async () => { const productName = 'GoPro HERO10 Black'; await login(); await allPages.inventoryPage.clickOnShopNowButton(); From 311253583215502d06631fbfe3abeba87047fbc1 Mon Sep 17 00:00:00 2001 From: testing Date: Fri, 12 Sep 2025 17:55:29 +0530 Subject: [PATCH 10/25] updated the yml by adding multiple browser --- .github/workflows/test.yml | 83 ++++++++++++++++++-------------------- tests/example.spec.js | 4 +- 2 files changed, 41 insertions(+), 46 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a18c768..4b91e32 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,9 +1,12 @@ # .github/workflows/playwright-daily.yml +# Runs Playwright test shards every day at **11 : 42 AM IST** (06 : 12 UTC) +# plus anytime you trigger it manually from the Actions tab. + name: Run Playwright tests on: - push: - pull_request: + push: # runs on every push + pull_request: # runs on new PRs or PR updates schedule: - cron: '30 3 * * 1-5' workflow_dispatch: @@ -17,39 +20,31 @@ jobs: fail-fast: false matrix: include: - # Chromium → 25% (5 tests, 2 shards) - - browser: chromium - shardIndex: 1 - shardTotal: 8 - - browser: chromium - shardIndex: 2 - shardTotal: 8 - - # Firefox → 25% (5 tests, 2 shards) - - browser: firefox - shardIndex: 3 - shardTotal: 8 - - browser: firefox - shardIndex: 4 - shardTotal: 8 - - # WebKit → 25% (5 tests, 2 shards) - - browser: webkit - shardIndex: 5 - shardTotal: 8 - - browser: webkit - shardIndex: 6 - shardTotal: 8 - - # Android → 10% (2 tests, 1 shard) - - browser: 'Pixel 5' - shardIndex: 7 - shardTotal: 8 - - # iOS → 10% (2 tests, 1 shard) - - browser: 'iPhone 13' - shardIndex: 8 - shardTotal: 8 + # chromium → shards 1-5 (5 runs) + - { project: chromium, shardIndex: 1, shardTotal: 20 } + - { project: chromium, shardIndex: 2, shardTotal: 20 } + - { project: chromium, shardIndex: 3, shardTotal: 20 } + - { project: chromium, shardIndex: 4, shardTotal: 20 } + - { project: chromium, shardIndex: 5, shardTotal: 20 } + # firefox → shards 6-10 (5 runs) + - { project: firefox, shardIndex: 6, shardTotal: 20 } + - { project: firefox, shardIndex: 7, shardTotal: 20 } + - { project: firefox, shardIndex: 8, shardTotal: 20 } + - { project: firefox, shardIndex: 9, shardTotal: 20 } + - { project: firefox, shardIndex: 10, shardTotal: 20 } + # webkit → shards 11-15 (5 runs) + - { project: webkit, shardIndex: 11, shardTotal: 20 } + - { project: webkit, shardIndex: 12, shardTotal: 20 } + - { project: webkit, shardIndex: 13, shardTotal: 20 } + - { project: webkit, shardIndex: 14, shardTotal: 20 } + - { project: webkit, shardIndex: 15, shardTotal: 20 } + # android → shards 16-17 (2 runs) + - { project: android, shardIndex: 16, shardTotal: 20 } + - { project: android, shardIndex: 17, shardTotal: 20 } + # ios → shards 18-20 (3 runs) + - { project: ios, shardIndex: 18, shardTotal: 20 } + - { project: ios, shardIndex: 19, shardTotal: 20 } + - { project: ios, shardIndex: 20, shardTotal: 20 } steps: - uses: actions/checkout@v4 @@ -70,7 +65,7 @@ jobs: echo "STATE=${{ secrets.STATE }}" >> .env echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env - + - name: Cache npm dependencies uses: actions/cache@v3 with: @@ -84,21 +79,21 @@ jobs: npm ci npx playwright install --with-deps - - name: Run shard ${{ matrix.shardIndex }} on ${{ matrix.browser }} - run: npx playwright test --project="${{ matrix.browser }}" --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + - name: Run shard ${{ matrix.shardIndex }} on ${{ matrix.project }} + run: npx playwright test --project=${{ matrix.project }} --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - name: Upload blob report if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: - name: blob-report-${{ matrix.browser }}-${{ matrix.shardIndex }} + name: blob-report-${{ matrix.project }}-${{ matrix.shardIndex }} path: ./blob-report retention-days: 1 merge-reports: name: Merge Reports needs: run-tests - if: always() + if: always() # run even if some shards fail runs-on: ubuntu-latest steps: @@ -141,7 +136,7 @@ jobs: - name: Send TestDino report run: | - npx --yes tdpw ./playwright-report \ - --token="${{ secrets.TESTDINO_TOKEN }}" \ - --upload-html \ - --verbose + npx --yes tdpw ./playwright-report \ + --token="${{ secrets.TESTDINO_TOKEN }}" \ + --upload-html \ + --verbose diff --git a/tests/example.spec.js b/tests/example.spec.js index 184ddb5..81553dc 100644 --- a/tests/example.spec.js +++ b/tests/example.spec.js @@ -493,7 +493,7 @@ test('Verify that user is able to fill Contact Us page successfully @webkit', as await allPages.contactUsPage.verifySuccessContactUsFormSubmission(); }); -test('Verify that user is able to submit a product review @andriod', async () => { +test('Verify that user is able to submit a product review @android', async () => { await test.step('Login as existing user and navigate to a product', async () => { await login(); }) @@ -590,7 +590,7 @@ test('Verify that all the navbar are working properly @ios', async () => { await allPages.homePage.assertAboutUsTitle(); }); -test('Verify that user is able to delete selected product from cart @chromium', async () => { +test('Verify that user is able to delete selected product from cart @ios', async () => { const productName = 'GoPro HERO10 Black'; await login(); await allPages.inventoryPage.clickOnShopNowButton(); From a1357e7f5271bfe03e95fea33027a6a3c05cec6a Mon Sep 17 00:00:00 2001 From: testing Date: Fri, 12 Sep 2025 18:15:16 +0530 Subject: [PATCH 11/25] updated the yml by adding multiple browser --- .github/workflows/test.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4b91e32..d88861b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ on: jobs: run-tests: - name: Run Playwright shards + name: Run ${{ matrix.project }} shard ${{ matrix.shardIndex }}/20 runs-on: ubuntu-latest strategy: @@ -77,7 +77,10 @@ jobs: - name: Install deps + browsers run: | npm ci - npx playwright install --with-deps + npx playwright install --with-deps chromium firefox webkit + + - name: List Playwright projects (debug) + run: npx playwright list --projects | cat - name: Run shard ${{ matrix.shardIndex }} on ${{ matrix.project }} run: npx playwright test --project=${{ matrix.project }} --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} From 4e30306a2b062c72ebb94ab97286649fd75db1d1 Mon Sep 17 00:00:00 2001 From: testing Date: Fri, 12 Sep 2025 18:28:43 +0530 Subject: [PATCH 12/25] changes applied in the playwright.config file --- .github/workflows/test.yml | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d88861b..c4aa02c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,38 +13,14 @@ on: jobs: run-tests: - name: Run ${{ matrix.project }} shard ${{ matrix.shardIndex }}/20 + name: Run shard ${{ matrix.shardIndex }}/5 runs-on: ubuntu-latest strategy: fail-fast: false matrix: - include: - # chromium → shards 1-5 (5 runs) - - { project: chromium, shardIndex: 1, shardTotal: 20 } - - { project: chromium, shardIndex: 2, shardTotal: 20 } - - { project: chromium, shardIndex: 3, shardTotal: 20 } - - { project: chromium, shardIndex: 4, shardTotal: 20 } - - { project: chromium, shardIndex: 5, shardTotal: 20 } - # firefox → shards 6-10 (5 runs) - - { project: firefox, shardIndex: 6, shardTotal: 20 } - - { project: firefox, shardIndex: 7, shardTotal: 20 } - - { project: firefox, shardIndex: 8, shardTotal: 20 } - - { project: firefox, shardIndex: 9, shardTotal: 20 } - - { project: firefox, shardIndex: 10, shardTotal: 20 } - # webkit → shards 11-15 (5 runs) - - { project: webkit, shardIndex: 11, shardTotal: 20 } - - { project: webkit, shardIndex: 12, shardTotal: 20 } - - { project: webkit, shardIndex: 13, shardTotal: 20 } - - { project: webkit, shardIndex: 14, shardTotal: 20 } - - { project: webkit, shardIndex: 15, shardTotal: 20 } - # android → shards 16-17 (2 runs) - - { project: android, shardIndex: 16, shardTotal: 20 } - - { project: android, shardIndex: 17, shardTotal: 20 } - # ios → shards 18-20 (3 runs) - - { project: ios, shardIndex: 18, shardTotal: 20 } - - { project: ios, shardIndex: 19, shardTotal: 20 } - - { project: ios, shardIndex: 20, shardTotal: 20 } + shardIndex: [1,2,3,4,5] + shardTotal: [5] steps: - uses: actions/checkout@v4 @@ -82,14 +58,14 @@ jobs: - name: List Playwright projects (debug) run: npx playwright list --projects | cat - - name: Run shard ${{ matrix.shardIndex }} on ${{ matrix.project }} - run: npx playwright test --project=${{ matrix.project }} --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + - name: Run shard ${{ matrix.shardIndex }} + run: npx playwright test --grep="@chromium|@firefox|@webkit|@android|@ios" --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - name: Upload blob report if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: - name: blob-report-${{ matrix.project }}-${{ matrix.shardIndex }} + name: blob-report-${{ matrix.shardIndex }} path: ./blob-report retention-days: 1 From 9d0753dc1ce105683be9be7f7b908a95be25e576 Mon Sep 17 00:00:00 2001 From: testing Date: Mon, 22 Sep 2025 15:11:31 +0530 Subject: [PATCH 13/25] Updated playwright config --- playwright.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright.config.js b/playwright.config.js index f6d55df..9750e70 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -22,7 +22,7 @@ export default defineConfig({ use: { baseURL: 'https://demo.alphabin.co/', - headless: true, + headless: false, trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'retain-on-failure', From ed4872aa83f629aef0446bb18451c9d734e9bcec Mon Sep 17 00:00:00 2001 From: TestDino Date: Tue, 10 Feb 2026 12:21:21 +0530 Subject: [PATCH 14/25] Updated the workflow file with new updates --- .github/workflows/test.yml | 220 ++++++++++----- playwright.config.js | 13 +- tests/delete-api.spec.js | 47 ++++ tests/example.spec.js | 553 ++++++++++++++++++------------------- tests/get-users.spec.js | 164 +++++++++++ tests/visual.spec.js | 23 ++ 6 files changed, 661 insertions(+), 359 deletions(-) create mode 100644 tests/delete-api.spec.js create mode 100644 tests/get-users.spec.js create mode 100644 tests/visual.spec.js diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c4aa02c..70ea782 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,14 +1,131 @@ -# .github/workflows/playwright-daily.yml -# Runs Playwright test shards every day at **11 : 42 AM IST** (06 : 12 UTC) -# plus anytime you trigger it manually from the Actions tab. +# # .github/workflows/playwright-daily.yml +# # Runs Playwright test shards every day at **11 : 42 AM IST** (06 : 12 UTC) +# # plus anytime you trigger it manually from the Actions tab. + +# name: Run Playwright tests + +# on: +# push: # runs on every push +# pull_request: # runs on new PRs or PR updates +# schedule: +# - cron: '30 3 * * 1-5' +# workflow_dispatch: + +# jobs: +# run-tests: +# name: Run shard ${{ matrix.shardIndex }}/5 +# runs-on: ubuntu-latest + +# strategy: +# fail-fast: false +# matrix: +# shardIndex: [1,2,3,4,5] +# shardTotal: [5] + +# steps: +# - uses: actions/checkout@v4 + +# - name: Setup Node.js 18.x +# uses: actions/setup-node@v3 +# with: +# node-version: '18' + +# - name: Create .env file +# run: | +# echo "USERNAME=${{ secrets.USERNAME }}" >> .env +# echo "PASSWORD=${{ secrets.PASSWORD }}" >> .env +# echo "NEW_PASSWORD=${{ secrets.NEW_PASSWORD }}" >> .env +# echo "FIRST_NAME=${{ secrets.FIRST_NAME }}" >> .env +# echo "STREET_NAME=${{ secrets.STREET_NAME }}" >> .env +# echo "CITY=${{ secrets.CITY }}" >> .env +# echo "STATE=${{ secrets.STATE }}" >> .env +# echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env +# echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env + +# - name: Cache npm dependencies +# uses: actions/cache@v3 +# with: +# path: ~/.npm +# key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} +# restore-keys: | +# ${{ runner.os }}-node- + +# - name: Install deps + browsers +# run: | +# npm ci +# npx playwright install --with-deps chromium firefox webkit + +# - name: List Playwright projects (debug) +# run: npx playwright list --projects | cat + +# - name: Run shard ${{ matrix.shardIndex }} +# run: npx playwright test --grep="@chromium|@firefox|@webkit|@android|@ios" --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + +# - name: Upload blob report +# if: ${{ !cancelled() }} +# uses: actions/upload-artifact@v4 +# with: +# name: blob-report-${{ matrix.shardIndex }} +# path: ./blob-report +# retention-days: 1 + +# merge-reports: +# name: Merge Reports +# needs: run-tests +# if: always() # run even if some shards fail +# runs-on: ubuntu-latest + +# steps: +# - uses: actions/checkout@v4 + +# - name: Setup Node.js 18.x +# uses: actions/setup-node@v3 +# with: +# node-version: '18' + +# - name: Cache npm dependencies +# uses: actions/cache@v3 +# with: +# path: ~/.npm +# key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} +# restore-keys: | +# ${{ runner.os }}-node- + +# - name: Install deps + browsers +# run: | +# npm ci +# npx playwright install --with-deps + +# - name: Download all blob reports +# uses: actions/download-artifact@v4 +# with: +# path: ./all-blob-reports +# pattern: blob-report-* +# merge-multiple: true + +# - name: Merge HTML & JSON reports +# run: npx playwright merge-reports --config=playwright.config.js ./all-blob-reports + +# - name: Upload combined report +# uses: actions/upload-artifact@v4 +# with: +# name: Playwright Test Report +# path: ./playwright-report +# retention-days: 14 + +# - name: Send TestDino report +# run: | +# npx --yes tdpw ./playwright-report \ +# --token="${{ secrets.TESTDINO_TOKEN }}" \ +# --upload-html \ +# --verbose + name: Run Playwright tests on: - push: # runs on every push - pull_request: # runs on new PRs or PR updates - schedule: - - cron: '30 3 * * 1-5' + push: + pull_request: workflow_dispatch: jobs: @@ -19,17 +136,20 @@ jobs: strategy: fail-fast: false matrix: - shardIndex: [1,2,3,4,5] + shardIndex: [1, 2, 3, 4, 5] shardTotal: [5] steps: - - uses: actions/checkout@v4 + - name: Checkout repo + uses: actions/checkout@v4 - - name: Setup Node.js 18.x - uses: actions/setup-node@v3 + # ✅ Required Node version + - name: Setup Node.js 20.x + uses: actions/setup-node@v4 with: - node-version: '18' + node-version: '20' + # ✅ Required env variables for tests - name: Create .env file run: | echo "USERNAME=${{ secrets.USERNAME }}" >> .env @@ -41,7 +161,8 @@ jobs: echo "STATE=${{ secrets.STATE }}" >> .env echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env - + + # ✅ Cache npm dependencies - name: Cache npm dependencies uses: actions/cache@v3 with: @@ -50,72 +171,27 @@ jobs: restore-keys: | ${{ runner.os }}-node- - - name: Install deps + browsers + # ✅ Install dependencies + TestDino (.tgz) + Playwright browsers + - name: Install dependencies & browsers run: | - npm ci + npm install + npm install --save-dev @testdino/playwright@latest npx playwright install --with-deps chromium firefox webkit - - name: List Playwright projects (debug) - run: npx playwright list --projects | cat - - - name: Run shard ${{ matrix.shardIndex }} - run: npx playwright test --grep="@chromium|@firefox|@webkit|@android|@ios" --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + # ✅ Run Playwright shard with TestDino + - name: Run Playwright shard with TestDino + env: + TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }} + run: | + npx playwright test \ + --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} \ + --grep "@chromium|@firefox|@webkit|@android|@ios|@api" \ + # ✅ Upload blob report (needed for merge) - name: Upload blob report if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: name: blob-report-${{ matrix.shardIndex }} path: ./blob-report - retention-days: 1 - - merge-reports: - name: Merge Reports - needs: run-tests - if: always() # run even if some shards fail - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup Node.js 18.x - uses: actions/setup-node@v3 - with: - node-version: '18' - - - name: Cache npm dependencies - uses: actions/cache@v3 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Install deps + browsers - run: | - npm ci - npx playwright install --with-deps - - - name: Download all blob reports - uses: actions/download-artifact@v4 - with: - path: ./all-blob-reports - pattern: blob-report-* - merge-multiple: true - - - name: Merge HTML & JSON reports - run: npx playwright merge-reports --config=playwright.config.js ./all-blob-reports - - - name: Upload combined report - uses: actions/upload-artifact@v4 - with: - name: Playwright Test Report - path: ./playwright-report - retention-days: 14 - - - name: Send TestDino report - run: | - npx --yes tdpw ./playwright-report \ - --token="${{ secrets.TESTDINO_TOKEN }}" \ - --upload-html \ - --verbose + retention-days: 1 \ No newline at end of file diff --git a/playwright.config.js b/playwright.config.js index 9750e70..a8e812d 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -7,8 +7,8 @@ export default defineConfig({ testDir: './tests', fullyParallel: true, forbidOnly: isCI, - retries: isCI ? 1 : 0, - workers: isCI ? 1 : 1, + retries: isCI ? 1 : 1, + workers: isCI ? 5 : 5, timeout: 60 * 1000, reporter: [ @@ -16,14 +16,15 @@ export default defineConfig({ outputFolder: 'playwright-report', open: 'never' }], - ['blob', { outputDir: 'blob-report' }], // Blob reporter for merging + ['blob', { outputDir: 'blob-report' }], ['json', { outputFile: './playwright-report/report.json' }], + ['@testdino/playwright', { token: process.env.TESTDINO_TOKEN }], ], use: { - baseURL: 'https://demo.alphabin.co/', - headless: false, - trace: 'on-first-retry', + baseURL: 'https://storedemo.testdino.com/', + headless: true, + trace: 'on', screenshot: 'only-on-failure', video: 'retain-on-failure', }, diff --git a/tests/delete-api.spec.js b/tests/delete-api.spec.js new file mode 100644 index 0000000..41a61c1 --- /dev/null +++ b/tests/delete-api.spec.js @@ -0,0 +1,47 @@ +// @ts-check +import { expect, test } from '@playwright/test'; + +// Base API URL - adjust this to match your actual API endpoint +const API_BASE_URL = process.env.API_BASE_URL || 'https://dummyjson.com'; +const USERS_ENDPOINT = '/users'; + +test.describe('DELETE User API', () => { + + test('Remove user 1', { tag: '@api' }, async ({ request }) => { + const userId = 1; + const response = await request.delete(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}`); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toHaveProperty('id', userId); + expect(body).toHaveProperty('isDeleted', true); + }); + + test('Remove user twice', { tag: '@api' }, async ({ request }) => { + const userId = 2; + + // First deletion + const response1 = await request.delete(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}`); + expect(response1.status()).toBe(200); + const body1 = await response1.json(); + expect(body1).toHaveProperty('id', userId); + + const response2 = await request.delete(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}`); + expect(response2.status()).toBe(200); + const body2 = await response2.json(); + expect(body2).toHaveProperty('id', userId); + }); + + test('Validate body is returned', { tag: '@api' }, async ({ request }) => { + const userId = 3; + const response = await request.delete(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}`); + + expect(response.status()).toBe(200); + const body = await response.json(); + + // Validate response body structure + expect(body).toBeInstanceOf(Object); + expect(body).toHaveProperty('id'); + expect(typeof body.id).toBe('number'); + }); +}); diff --git a/tests/example.spec.js b/tests/example.spec.js index 81553dc..c2a66c6 100644 --- a/tests/example.spec.js +++ b/tests/example.spec.js @@ -28,20 +28,20 @@ async function logout() { await allPages.loginPage.clickOnLogoutButton(); } -test('Verify that user can login and logout successfully @chromium', async () => { +test('Verify that user can login and logout successfully', { tag: '@android' }, async () => { await login(); await logout(); }); -test('Verify that user can update personal information @chromium', async () => { - await login(); +test('Verify that user can update personal information', { tag: '@webkit' }, async () => { + // await login(); await allPages.userPage.clickOnUserProfileIcon(); - await allPages.userPage.updatePersonalInfo(); - await allPages.userPage.verifyPersonalInfoUpdated(); + // await allPages.userPage.updatePersonalInfo(); + // await allPages.userPage.verifyPersonalInfoUpdated(); }); -test('Verify that User Can Add, Edit, and Delete Addresses after Logging In @chromium', async () => { - await login(); +test('Verify that User Can Add, Edit, and Delete Addresses after Logging In', { tag: '@chromium' }, async () => { + // await login(); await test.step('Verify that user is able to add address successfully', async () => { await allPages.userPage.clickOnUserProfileIcon(); @@ -62,9 +62,9 @@ test('Verify that User Can Add, Edit, and Delete Addresses after Logging In @chr }); }); -test('Verify that user can change password successfully @chromium', async () => { +test('Verify that user can change password successfully', { tag: '@firefox' }, async () => { await test.step('Login with existing password', async () => { - await login1(); + // await login1(); }); await test.step('Change password and verify login with new password', async () => { @@ -88,36 +88,27 @@ test('Verify that user can change password successfully @chromium', async () => }) }); -test('Verify that the New User is able to add Addresses in the Address section @chromium', async () => { - await login(); - await allPages.userPage.clickOnUserProfileIcon(); - await allPages.userPage.clickOnAddressTab(); - await allPages.userPage.clickOnAddAddressButton(); - await allPages.userPage.checkAddNewAddressMenu(); - await allPages.userPage.fillAddressForm(); -}); - -test('Verify that User Can Complete the Journey from Login to Order Placement @firefox', async () => { +test('Verify that User Can Complete the Journey from Login to Order Placement', { tag: '@webkit' }, async () => { const productName = 'GoPro HERO10 Black'; - await login(); + // await login(); await allPages.inventoryPage.clickOnShopNowButton(); await allPages.inventoryPage.clickOnAllProductsLink(); await allPages.inventoryPage.searchProduct(productName); await allPages.inventoryPage.verifyProductTitleVisible(productName); await allPages.inventoryPage.clickOnAddToCartIcon(); - await allPages.cartPage.clickOnCartIcon(); - await allPages.cartPage.verifyCartItemVisible(productName); - await allPages.cartPage.clickOnCheckoutButton(); - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.verifyProductInCheckout(productName); - await allPages.checkoutPage.selectCashOnDelivery(); - await allPages.checkoutPage.verifyCashOnDeliverySelected(); - await allPages.checkoutPage.clickOnPlaceOrder(); - await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await allPages.cartPage.clickOnCartIcon(); + // await allPages.cartPage.verifyCartItemVisible(productName); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.verifyProductInCheckout(productName); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCashOnDeliverySelected(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); }); -test('Verify user can place and cancel an order @firefox', async () => { +test('Verify user can place and cancel an order', { tag: '@webkit' }, async () => { const productName = 'GoPro HERO10 Black'; const productPriceAndQuantity = '₹49,999 × 1'; const productQuantity = '1'; @@ -125,57 +116,57 @@ test('Verify user can place and cancel an order @firefox', async () => { const orderStatusCanceled = 'Canceled'; await test.step('Verify that user can login successfully', async () => { - await login(); + // await login(); await allPages.inventoryPage.clickOnAllProductsLink(); await allPages.inventoryPage.searchProduct(productName); await allPages.inventoryPage.verifyProductTitleVisible(productName); await allPages.inventoryPage.clickOnAddToCartIcon(); }) - await test.step('Add product to cart and checkout', async () => { - await allPages.cartPage.clickOnCartIcon(); - await allPages.cartPage.verifyCartItemVisible(productName); - await allPages.cartPage.clickOnCheckoutButton(); - }) - - await test.step('Place order and click on continue shopping', async () => { - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.verifyProductInCheckout(productName); - await allPages.checkoutPage.selectCashOnDelivery(); - await allPages.checkoutPage.verifyCashOnDeliverySelected(); - await allPages.checkoutPage.clickOnPlaceOrder(); - await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); - await allPages.checkoutPage.verifyOrderItemName(productName); - await allPages.inventoryPage.clickOnContinueShopping(); - }) - - await test.step('Verify order in My Orders', async () => { - await allPages.loginPage.clickOnUserProfileIcon(); - await allPages.orderPage.clickOnMyOrdersTab(); - await allPages.orderPage.verifyMyOrdersTitle(); - await allPages.orderPage.clickOnPaginationButton(2); - await allPages.orderPage.verifyProductInOrderList(productName); - await allPages.orderPage.verifyPriceAndQuantityInOrderList(productPriceAndQuantity); - await allPages.orderPage.verifyOrderStatusInList(orderStatusProcessing, productName); - await allPages.orderPage.clickOnPaginationButton(1); - await allPages.orderPage.clickViewDetailsButton(1); - await allPages.orderPage.verifyOrderDetailsTitle(); - await allPages.orderPage.verifyOrderSummary(productName, productQuantity, '₹49,999', orderStatusProcessing); - }) - - await test.step('Cancel order and verify status is updated to Canceled', async () => { - await allPages.orderPage.clickCancelOrderButton(2); - await allPages.orderPage.confirmCancellation(); - await allPages.orderPage.verifyCancellationConfirmationMessage(); - await allPages.orderPage.verifyMyOrdersCount(); - await allPages.orderPage.clickOnMyOrdersTab(); - await allPages.orderPage.verifyMyOrdersTitle(); - await allPages.orderPage.clickOnPaginationButton(2); - await allPages.orderPage.verifyOrderStatusInList(orderStatusCanceled, productName); - }) + // await test.step('Add product to cart and checkout', async () => { + // await allPages.cartPage.clickOnCartIcon(); + // await allPages.cartPage.verifyCartItemVisible(productName); + // await allPages.cartPage.clickOnCheckoutButton(); + // }) + + // await test.step('Place order and click on continue shopping', async () => { + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.verifyProductInCheckout(productName); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCashOnDeliverySelected(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await allPages.checkoutPage.verifyOrderItemName(productName); + // await allPages.inventoryPage.clickOnContinueShopping(); + // }) + + // await test.step('Verify order in My Orders', async () => { + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.orderPage.clickOnMyOrdersTab(); + // await allPages.orderPage.verifyMyOrdersTitle(); + // await allPages.orderPage.clickOnPaginationButton(2); + // await allPages.orderPage.verifyProductInOrderList(productName); + // await allPages.orderPage.verifyPriceAndQuantityInOrderList(productPriceAndQuantity); + // await allPages.orderPage.verifyOrderStatusInList(orderStatusProcessing, productName); + // await allPages.orderPage.clickOnPaginationButton(1); + // await allPages.orderPage.clickViewDetailsButton(1); + // await allPages.orderPage.verifyOrderDetailsTitle(); + // await allPages.orderPage.verifyOrderSummary(productName, productQuantity, '₹49,999', orderStatusProcessing); + // }) + + // await test.step('Cancel order and verify status is updated to Canceled', async () => { + // await allPages.orderPage.clickCancelOrderButton(2); + // await allPages.orderPage.confirmCancellation(); + // await allPages.orderPage.verifyCancellationConfirmationMessage(); + // await allPages.orderPage.verifyMyOrdersCount(); + // await allPages.orderPage.clickOnMyOrdersTab(); + // await allPages.orderPage.verifyMyOrdersTitle(); + // await allPages.orderPage.clickOnPaginationButton(2); + // await allPages.orderPage.verifyOrderStatusInList(orderStatusCanceled, productName); + // }) }); -test('Verify that a New User Can Successfully Complete the Journey from Registration to a Single Order Placement @firefox', async () => { +test('Verify that a New User Can Successfully Complete the Journey from Registration to a Single Order Placement', { tag: '@firefox' }, async () => { // fresh test data const email = `test+${Date.now()}@test.com`; const firstName = 'Test'; @@ -185,21 +176,21 @@ test('Verify that a New User Can Successfully Complete the Journey from Registra let productPrice; let productReviewCount; - await test.step('Verify that user can register successfully', async () => { - await allPages.loginPage.clickOnUserProfileIcon(); - await allPages.loginPage.validateSignInPage(); - await allPages.loginPage.clickOnSignupLink(); - await allPages.signupPage.assertSignupPage(); - await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); - await allPages.signupPage.verifySuccessSignUp(); - }) - - await test.step('Verify that user can login successfully', async () => { - await allPages.loginPage.validateSignInPage(); - await allPages.loginPage.login(email, process.env.PASSWORD); - await allPages.loginPage.verifySuccessSignIn(); - await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); - }) + // await test.step('Verify that user can register successfully', async () => { + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.clickOnSignupLink(); + // await allPages.signupPage.assertSignupPage(); + // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); + // await allPages.signupPage.verifySuccessSignUp(); + // }) + + // await test.step('Verify that user can login successfully', async () => { + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.login(email, process.env.PASSWORD); + // await allPages.loginPage.verifySuccessSignIn(); + // await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); + // }) await test.step('Navigate to all product and add to wishlist section', async () => { await allPages.homePage.clickAllProductsNav(); @@ -220,103 +211,103 @@ test('Verify that a New User Can Successfully Complete the Journey from Registra }) await test.step('Add product to cart, add new address and checkout', async () => { - await allPages.productDetailsPage.clickAddToCartButton(); - - await allPages.productDetailsPage.clickCartIcon(); - await allPages.cartPage.assertYourCartTitle(); - await expect(allPages.cartPage.getCartItemName()).toContainText(productName, { timeout: 10000 }); - await expect(allPages.cartPage.getCartItemPrice()).toContainText(productPrice); - await expect(allPages.cartPage.getCartItemQuantity()).toContainText('1'); - await allPages.cartPage.clickIncreaseQuantityButton(); - await expect(allPages.cartPage.getCartItemQuantity()).toContainText('2'); - - const cleanPrice = productPrice.replace(/[₹,]/g, ''); - const priceValue = parseFloat(cleanPrice) * 2; - await expect(allPages.cartPage.getTotalValue()).toContainText( - priceValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') - ); - await allPages.cartPage.clickOnCheckoutButton(); - - // Fill shipping address and save - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.fillShippingAddress( - firstName, email, 'New York', 'New York', '123 Main St', '10001', 'United States' - ); - await allPages.checkoutPage.clickSaveAddressButton(); - await allPages.checkoutPage.assertAddressAddedToast(); - - // COD, verify summary, place order - await allPages.checkoutPage.selectCashOnDelivery(); - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.assertOrderSummaryTitle(); - await expect(allPages.checkoutPage.getOrderSummaryImage()).toBeVisible(); - await expect(allPages.checkoutPage.getOrderSummaryProductName()).toContainText(productName); - await allPages.checkoutPage.verifyProductInCheckout(productName); - await expect(allPages.checkoutPage.getOrderSummaryProductQuantity()).toContainText('2'); - await expect(allPages.checkoutPage.getOrderSummaryProductPrice()).toContainText(productPrice); - - const subtotalValue = parseFloat(cleanPrice) * 2; - const formattedSubtotal = subtotalValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); - await expect(await allPages.checkoutPage.getOrderSummarySubtotalValue()).toContain(formattedSubtotal); - await expect(allPages.checkoutPage.getOrderSummaryShippingValue()).toContainText('Free'); - await allPages.checkoutPage.clickOnPlaceOrder(); - - // Order details and return to home - await allPages.orderDetailsPage.assertOrderDetailsTitle(); - await allPages.orderDetailsPage.assertOrderPlacedName(); - await allPages.orderDetailsPage.assertOrderPlacedMessage(); - await allPages.orderDetailsPage.assertOrderPlacedDate(); - await allPages.orderDetailsPage.assertOrderInformationTitle(); - await allPages.orderDetailsPage.assertOrderConfirmedTitle(); - await allPages.orderDetailsPage.assertOrderConfirmedMessage(); - await allPages.orderDetailsPage.assertShippingDetailsTitle(); - await allPages.orderDetailsPage.assertShippingEmailValue(email); - await allPages.orderDetailsPage.assertPaymentMethodAmount(formattedSubtotal); - await allPages.orderDetailsPage.assertDeliveryAddressLabel(); - await allPages.orderDetailsPage.assertDeliveryAddressValue(); - await allPages.orderDetailsPage.assertContinueShoppingButton(); - - await allPages.orderDetailsPage.assertOrderSummaryTitle(); - await allPages.orderDetailsPage.assertOrderSummaryProductName(productName); - await allPages.orderDetailsPage.assertOrderSummaryProductQuantity('2'); - await allPages.orderDetailsPage.assertOrderSummaryProductPrice(productPrice); - await allPages.orderDetailsPage.assertOrderSummarySubtotalValue(formattedSubtotal); - await allPages.orderDetailsPage.assertOrderSummaryShippingValue('Free'); - await allPages.orderDetailsPage.assertOrderSummaryTotalValue(formattedSubtotal); - await allPages.orderDetailsPage.clickBackToHomeButton(); + // await allPages.productDetailsPage.clickAddToCartButton(); + + // await allPages.productDetailsPage.clickCartIcon(); + // await allPages.cartPage.assertYourCartTitle(); + // await expect(allPages.cartPage.getCartItemName()).toContainText(productName, { timeout: 10000 }); + // await expect(allPages.cartPage.getCartItemPrice()).toContainText(productPrice); + // await expect(allPages.cartPage.getCartItemQuantity()).toContainText('1'); + // await allPages.cartPage.clickIncreaseQuantityButton(); + // await expect(allPages.cartPage.getCartItemQuantity()).toContainText('2'); + + // const cleanPrice = productPrice.replace(/[₹,]/g, ''); + // const priceValue = parseFloat(cleanPrice) * 2; + // await expect(allPages.cartPage.getTotalValue()).toContainText( + // priceValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') + // ); + // await allPages.cartPage.clickOnCheckoutButton(); + + // // Fill shipping address and save + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.fillShippingAddress( + // firstName, email, 'New York', 'New York', '123 Main St', '10001', 'United States' + // ); + // await allPages.checkoutPage.clickSaveAddressButton(); + // await allPages.checkoutPage.assertAddressAddedToast(); + + // // COD, verify summary, place order + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.assertOrderSummaryTitle(); + // await expect(allPages.checkoutPage.getOrderSummaryImage()).toBeVisible(); + // await expect(allPages.checkoutPage.getOrderSummaryProductName()).toContainText(productName); + // await allPages.checkoutPage.verifyProductInCheckout(productName); + // await expect(allPages.checkoutPage.getOrderSummaryProductQuantity()).toContainText('2'); + // await expect(allPages.checkoutPage.getOrderSummaryProductPrice()).toContainText(productPrice); + + // const subtotalValue = parseFloat(cleanPrice) * 2; + // const formattedSubtotal = subtotalValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); + // await expect(await allPages.checkoutPage.getOrderSummarySubtotalValue()).toContain(formattedSubtotal); + // await expect(allPages.checkoutPage.getOrderSummaryShippingValue()).toContainText('Free'); + // await allPages.checkoutPage.clickOnPlaceOrder(); + + // // Order details and return to home + // await allPages.orderDetailsPage.assertOrderDetailsTitle(); + // await allPages.orderDetailsPage.assertOrderPlacedName(); + // await allPages.orderDetailsPage.assertOrderPlacedMessage(); + // await allPages.orderDetailsPage.assertOrderPlacedDate(); + // await allPages.orderDetailsPage.assertOrderInformationTitle(); + // await allPages.orderDetailsPage.assertOrderConfirmedTitle(); + // await allPages.orderDetailsPage.assertOrderConfirmedMessage(); + // await allPages.orderDetailsPage.assertShippingDetailsTitle(); + // await allPages.orderDetailsPage.assertShippingEmailValue(email); + // await allPages.orderDetailsPage.assertPaymentMethodAmount(formattedSubtotal); + // await allPages.orderDetailsPage.assertDeliveryAddressLabel(); + // await allPages.orderDetailsPage.assertDeliveryAddressValue(); + // await allPages.orderDetailsPage.assertContinueShoppingButton(); + + // await allPages.orderDetailsPage.assertOrderSummaryTitle(); + // await allPages.orderDetailsPage.assertOrderSummaryProductName(productName); + // await allPages.orderDetailsPage.assertOrderSummaryProductQuantity('2'); + // await allPages.orderDetailsPage.assertOrderSummaryProductPrice(productPrice); + // await allPages.orderDetailsPage.assertOrderSummarySubtotalValue(formattedSubtotal); + // await allPages.orderDetailsPage.assertOrderSummaryShippingValue('Free'); + // await allPages.orderDetailsPage.assertOrderSummaryTotalValue(formattedSubtotal); + // await allPages.orderDetailsPage.clickBackToHomeButton(); }); }); -test('Verify that user add product to cart before logging in and then complete order after logging in @firefox', async () => { +test('Verify that user add product to cart before logging in and then complete order after logging in', { tag: '@chromium' }, async () => { await test.step('Navigate and add product to cart before logging in', async () => { await allPages.homePage.clickOnShopNowButton(); await allPages.homePage.clickProductImage(); await allPages.homePage.clickAddToCartButton(); await allPages.homePage.validateAddCartNotification(); - await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.loginPage.clickOnUserProfileIcon(); }) await test.step('Login and complete order', async () => { - await login(); - await allPages.cartPage.clickOnCartIcon(); - await allPages.cartPage.clickOnCheckoutButton(); - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.selectCashOnDelivery(); - await allPages.checkoutPage.verifyCashOnDeliverySelected(); - await allPages.checkoutPage.clickOnPlaceOrder(); - await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await login(); + // await allPages.cartPage.clickOnCartIcon(); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCashOnDeliverySelected(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); }) }); -test('Verify that user can filter products by price range @firefox', async () => { - await login(); +test('Verify that user can filter products by price range', { tag: '@chromium' }, async () => { + // await login(); await allPages.homePage.clickOnShopNowButton(); await allPages.homePage.clickOnFilterButton(); await allPages.homePage.AdjustPriceRangeSlider('10000', '20000'); await allPages.homePage.clickOnFilterButton(); }); -test('Verify if user can add product to wishlist, moves it to card and then checks out @webkit', async () => { - await login(); +test('Verify if user can add product to wishlist, moves it to card and then checks out', { tag: '@webkit' }, async () => { + // await login(); await test.step('Add product to wishlistand then add to cart', async () => { await allPages.homePage.clickOnShopNowButton(); @@ -328,39 +319,39 @@ test('Verify if user can add product to wishlist, moves it to card and then chec }) await test.step('Checkout product added to cart', async () => { - await allPages.cartPage.clickOnCartIcon(); - await allPages.cartPage.clickOnCheckoutButton(); - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.selectCashOnDelivery(); - await allPages.checkoutPage.verifyCashOnDeliverySelected(); - await allPages.checkoutPage.clickOnPlaceOrder(); - await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await allPages.cartPage.clickOnCartIcon(); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCashOnDeliverySelected(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); }) }); -test('Verify new user views and cancels an order in my orders @webkit', async () => { +test('Verify new user views and cancels an order in my orders', { tag: '@webkit' }, async () => { const email = `test+${Date.now()}@test.com`; const firstName = 'Test'; const lastName = 'User'; let productName= `Rode NT1-A Condenser Mic`; - await test.step('Verify that user can register successfully', async () => { - await allPages.loginPage.clickOnUserProfileIcon(); - await allPages.loginPage.validateSignInPage(); - await allPages.loginPage.clickOnSignupLink(); - await allPages.signupPage.assertSignupPage(); - await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); - await allPages.signupPage.verifySuccessSignUp(); - }) - - await test.step('Verify that user can login successfully', async () => { - await allPages.loginPage.validateSignInPage(); - await allPages.loginPage.login(email, process.env.PASSWORD); - await allPages.loginPage.verifySuccessSignIn(); - await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); - }) + // await test.step('Verify that user can register successfully', async () => { + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.clickOnSignupLink(); + // await allPages.signupPage.assertSignupPage(); + // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); + // await allPages.signupPage.verifySuccessSignUp(); + // }) + + // await test.step('Verify that user can login successfully', async () => { + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.login(email, process.env.PASSWORD); + // await allPages.loginPage.verifySuccessSignIn(); + // await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); + // }) await test.step('Navigate to All Products and add view details of a random product', async () => { await allPages.homePage.clickAllProductsNav(); @@ -370,57 +361,57 @@ test('Verify new user views and cancels an order in my orders @webkit', async () await allPages.productDetailsPage.clickAddToCartButton(); }) - await test.step('Add product to cart, add new address and checkout', async () => { - await allPages.productDetailsPage.clickCartIcon(); - await allPages.cartPage.assertYourCartTitle(); - await expect(allPages.cartPage.getCartItemName()).toContainText(productName, { timeout: 10000 }); - await allPages.cartPage.clickOnCheckoutButton(); - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.fillShippingAddress( - firstName, email, 'New York', 'New York', '123 Main St', '10001', 'United States' - ); - await allPages.checkoutPage.clickSaveAddressButton(); - await allPages.checkoutPage.assertAddressAddedToast(); - }) - - await test.step('Complete order and verify in my orders', async () => { - await allPages.checkoutPage.selectCashOnDelivery(); - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.clickOnPlaceOrder(); - await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); - await allPages.inventoryPage.clickOnContinueShopping(); - - await allPages.loginPage.clickOnUserProfileIcon(); - await allPages.orderPage.clickOnMyOrdersTab(); - await allPages.orderPage.clickCancelOrderButton(); - await allPages.orderPage.confirmCancellation(); - }); + // await test.step('Add product to cart, add new address and checkout', async () => { + // await allPages.productDetailsPage.clickCartIcon(); + // await allPages.cartPage.assertYourCartTitle(); + // await expect(allPages.cartPage.getCartItemName()).toContainText(productName, { timeout: 10000 }); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.fillShippingAddress( + // firstName, email, 'New York', 'New York', '123 Main St', '10001', 'United States' + // ); + // await allPages.checkoutPage.clickSaveAddressButton(); + // await allPages.checkoutPage.assertAddressAddedToast(); + // }) + + // await test.step('Complete order and verify in my orders', async () => { + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await allPages.inventoryPage.clickOnContinueShopping(); + + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.orderPage.clickOnMyOrdersTab(); + // await allPages.orderPage.clickCancelOrderButton(); + // await allPages.orderPage.confirmCancellation(); + // }); }); -test('Verify That a New User Can Successfully Complete the Journey from Registration to a Multiple Order Placement @webkit', async () => { +test('Verify That a New User Can Successfully Complete the Journey from Registration to a Multiple Order Placement', { tag: '@webkit' }, async () => { const email = `test+${Date.now()}@test.com`; const firstName = 'Test'; const lastName = 'User'; let productName= `Rode NT1-A Condenser Mic`; - await test.step('Verify that user can register successfully', async () => { - // Signup - await allPages.loginPage.clickOnUserProfileIcon(); - await allPages.loginPage.validateSignInPage(); - await allPages.loginPage.clickOnSignupLink(); - await allPages.signupPage.assertSignupPage(); - await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); - await allPages.signupPage.verifySuccessSignUp(); - }) - - await test.step('Verify that user can login successfully', async () => { - // Login as new user - await allPages.loginPage.validateSignInPage(); - await allPages.loginPage.login(email, process.env.PASSWORD); - await allPages.loginPage.verifySuccessSignIn(); - await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); - }) + // await test.step('Verify that user can register successfully', async () => { + // // Signup + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.clickOnSignupLink(); + // await allPages.signupPage.assertSignupPage(); + // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); + // await allPages.signupPage.verifySuccessSignUp(); + // }) + + // await test.step('Verify that user can login successfully', async () => { + // // Login as new user + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.login(email, process.env.PASSWORD); + // await allPages.loginPage.verifySuccessSignIn(); + // await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); + // }) await test.step('Navigate to All Products and add view details of a random product', async () => { await allPages.homePage.clickOnShopNowButton(); @@ -433,69 +424,69 @@ test('Verify That a New User Can Successfully Complete the Journey from Registra }) await test.step('Add product to cart, change quantity, add new address and checkout', async () => { - await allPages.productDetailsPage.clickAddToCartButton(); - await allPages.productDetailsPage.clickCartIcon(); - await allPages.cartPage.clickIncreaseQuantityButton(); - await allPages.cartPage.clickOnCheckoutButton(); - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.selectCashOnDelivery(); - await allPages.checkoutPage.verifyCashOnDeliverySelected(); - await allPages.checkoutPage.fillShippingAddress(process.env.SFIRST_NAME, email, process.env.SCITY, process.env.SSTATE, process.env.SSTREET_ADD, process.env.SZIP_CODE, process.env.SCOUNTRY); - await allPages.checkoutPage.clickSaveAddressButton(); - await allPages.checkoutPage.clickOnPlaceOrder(); - await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); - await allPages.checkoutPage.verifyOrderConfirmedTitle(); - await allPages.checkoutPage.clickOnContinueShoppingButton(); + // await allPages.productDetailsPage.clickAddToCartButton(); + // await allPages.productDetailsPage.clickCartIcon(); + // await allPages.cartPage.clickIncreaseQuantityButton(); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCashOnDeliverySelected(); + // await allPages.checkoutPage.fillShippingAddress(process.env.SFIRST_NAME, email, process.env.SCITY, process.env.SSTATE, process.env.SSTREET_ADD, process.env.SZIP_CODE, process.env.SCOUNTRY); + // await allPages.checkoutPage.clickSaveAddressButton(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await allPages.checkoutPage.verifyOrderConfirmedTitle(); + // await allPages.checkoutPage.clickOnContinueShoppingButton(); }) await test.step('Add another product to cart, select existing address and checkout', async () => { - await allPages.homePage.clickOnShopNowButton(); - await allPages.allProductsPage.assertAllProductsTitle(); - await allPages.allProductsPage.clickNthProduct(1); - await allPages.productDetailsPage.clickAddToCartButton(); - await allPages.productDetailsPage.clickCartIcon(); - await allPages.cartPage.clickOnCheckoutButton(); - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.selectCashOnDelivery(); - await allPages.checkoutPage.verifyCashOnDeliverySelected(); - await allPages.checkoutPage.clickOnPlaceOrder(); - await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await allPages.homePage.clickOnShopNowButton(); + // await allPages.allProductsPage.assertAllProductsTitle(); + // await allPages.allProductsPage.clickNthProduct(1); + // await allPages.productDetailsPage.clickAddToCartButton(); + // await allPages.productDetailsPage.clickCartIcon(); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCashOnDeliverySelected(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); }) }); -test('Verify that the new user is able to Sign Up, Log In, and Navigate to the Home Page Successfully @webkit', async () => { +test('Verify that the new user is able to Sign Up, Log In, and Navigate to the Home Page Successfully', { tag: '@ios' }, async () => { const email = `test+${Date.now()}@test.com`; const firstName = 'Test'; const lastName = 'User'; - await test.step('Verify that user can register successfully', async () => { - await allPages.loginPage.clickOnUserProfileIcon(); - await allPages.loginPage.validateSignInPage(); - await allPages.loginPage.clickOnSignupLink(); - await allPages.signupPage.assertSignupPage(); - await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); - await allPages.signupPage.verifySuccessSignUp(); - }) - - await test.step('Verify that user can login successfully', async () => { - await allPages.loginPage.validateSignInPage(); - await allPages.loginPage.login(email, process.env.PASSWORD); - await allPages.loginPage.verifySuccessSignIn(); - await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); - }) +// await test.step('Verify that user can register successfully', async () => { +// await allPages.loginPage.clickOnUserProfileIcon(); +// await allPages.loginPage.validateSignInPage(); +// await allPages.loginPage.clickOnSignupLink(); +// await allPages.signupPage.assertSignupPage(); +// await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); +// await allPages.signupPage.verifySuccessSignUp(); +// }) + +// await test.step('Verify that user can login successfully', async () => { +// await allPages.loginPage.validateSignInPage(); +// await allPages.loginPage.login(email, process.env.PASSWORD); +// await allPages.loginPage.verifySuccessSignIn(); +// await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); +// }) }) -test('Verify that user is able to fill Contact Us page successfully @webkit', async () => { - await login(); +test('Verify that user is able to fill Contact Us page successfully', { tag: '@firefox' }, async () => { + // await login(); await allPages.homePage.clickOnContactUsLink(); await allPages.contactUsPage.assertContactUsTitle(); await allPages.contactUsPage.fillContactUsForm(); await allPages.contactUsPage.verifySuccessContactUsFormSubmission(); }); -test('Verify that user is able to submit a product review @android', async () => { +test('Verify that user is able to submit a product review', { tag: '@android' }, async () => { await test.step('Login as existing user and navigate to a product', async () => { - await login(); + // await login(); }) await test.step('Navigate to all product section and select a product', async () => { @@ -518,9 +509,9 @@ test('Verify that user is able to submit a product review @android', async () => }) }); -test('Verify that user can edit and delete a product review @andriod', async () => { +test('Verify that user can edit and delete a product review', { tag: '@chromium' }, async () => { await test.step('Login as existing user and navigate to a product', async () => { - await login(); + // await login(); }) await test.step('Navigate to all product section and select a product', async () => { @@ -556,7 +547,7 @@ test('Verify that user can edit and delete a product review @andriod', async () }) }); -test('Verify that user can purchase multiple quantities in a single order @ios', async () => { +test('Verify that user can purchase multiple quantities in a single order', { tag: '@ios' }, async () => { const productName = 'GoPro HERO10 Black'; await login(); await allPages.inventoryPage.clickOnShopNowButton(); @@ -578,7 +569,7 @@ test('Verify that user can purchase multiple quantities in a single order @ios', await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); }); -test('Verify that all the navbar are working properly @ios', async () => { +test('Verify that all the navbar are working properly', { tag: '@ios' }, async () => { await login(); await allPages.homePage.clickBackToHomeButton(); // await allPages.homePage.assertHomePage(); @@ -590,7 +581,7 @@ test('Verify that all the navbar are working properly @ios', async () => { await allPages.homePage.assertAboutUsTitle(); }); -test('Verify that user is able to delete selected product from cart @ios', async () => { +test('Verify that user is able to delete selected product from cart', { tag: '@android' }, async () => { const productName = 'GoPro HERO10 Black'; await login(); await allPages.inventoryPage.clickOnShopNowButton(); diff --git a/tests/get-users.spec.js b/tests/get-users.spec.js new file mode 100644 index 0000000..1ab0a3d --- /dev/null +++ b/tests/get-users.spec.js @@ -0,0 +1,164 @@ +// @ts-check +import { expect, test } from '@playwright/test'; + +// Base API URL - adjust this to match your actual API endpoint +const API_BASE_URL = process.env.API_BASE_URL || 'https://dummyjson.com'; +const USERS_ENDPOINT = '/users'; + +test.describe('GET Users API', () => { + + test('Fetch all users', { tag: '@api' }, async ({ request }) => { + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}`); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toHaveProperty('users'); + expect(Array.isArray(body.users)).toBe(true); + }); + + test('Fetch user by ID = 1', { tag: '@api' }, async ({ request }) => { + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}/1`); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toHaveProperty('id', 1); + expect(body).toHaveProperty('firstName'); + expect(body).toHaveProperty('lastName'); + }); + + test('Validate total users > 0', { tag: '@api' }, async ({ request }) => { + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}`); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toHaveProperty('total'); + expect(body.total).toBeGreaterThan(0); + }); + + test('Validate user image exists', { tag: '@api' }, async ({ request }) => { + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}/1`); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toHaveProperty('image'); + expect(body.image).toBeTruthy(); + expect(typeof body.image).toBe('string'); + }); + + test('Validate user 1 has firstName field', { tag: '@api' }, async ({ request }) => { + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}/1`); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toHaveProperty('firstName'); + expect(typeof body.firstName).toBe('string'); + expect(body.firstName.length).toBeGreaterThan(0); + }); + + test('Invalid user ID returns 404', { tag: '@api' }, async ({ request }) => { + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}/999999`); + + expect(response.status()).toBe(404); + }); + + test('default users (no query) returns data object/array', { tag: '@api' }, async ({ request }) => { + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}`); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toBeInstanceOf(Object); + // Should have either 'users' array or be an array itself + expect(body.users || Array.isArray(body)).toBeTruthy(); + }); + + test('limit param returns limited results', { tag: '@api' }, async ({ request }) => { + const limit = 5; + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}?limit=${limit}`); + + expect(response.status()).toBe(200); + const body = await response.json(); + const users = body.users || body; + const usersArray = Array.isArray(users) ? users : []; + expect(usersArray.length).toBeLessThanOrEqual(limit); + }); + + test('skip param shifts results', { tag: '@api' }, async ({ request }) => { + const skip = 5; + const limit = 10; + + // Get first page + const response1 = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}?limit=${limit}&skip=0`); + const body1 = await response1.json(); + const users1 = body1.users || body1; + const firstUser1 = Array.isArray(users1) ? users1[0] : null; + + // Get second page with skip + const response2 = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}?limit=${limit}&skip=${skip}`); + const body2 = await response2.json(); + const users2 = body2.users || body2; + const firstUser2 = Array.isArray(users2) ? users2[0] : null; + + expect(response1.status()).toBe(200); + expect(response2.status()).toBe(200); + + // If both have users, they should be different (unless skip doesn't work) + if (firstUser1 && firstUser2) { + expect(firstUser1.id).not.toBe(firstUser2.id); + } + }); + + test('sorting / search query (if supported) returns filtered results', { tag: '@api' }, async ({ request }) => { + // Try search query parameter (common patterns: q, search, query) + const searchTerm = 'john'; + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}/search?q=${searchTerm}`); + + expect(response.status()).toBe(200); + const body = await response.json(); + const users = body.users || body; + const usersArray = Array.isArray(users) ? users : []; + + if (usersArray.length > 0) { + // At least verify the response structure is valid + expect(Array.isArray(usersArray)).toBe(true); + } + }); + + test('delayed response (3s) should return 200', { tag: '@api' }, async ({ request }) => { + const isRetry = test.info().retry > 0; + if (!isRetry) { + expect(true).toBe(false); + } + + const delay = 3; + const startTime = Date.now(); + + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}?delay=${delay}`, { + timeout: 10000 // 10 second timeout + }); + + const endTime = Date.now(); + const duration = (endTime - startTime) / 1000; + + expect(response.status()).toBe(200); + expect(duration).toBeGreaterThanOrEqual(delay - 0.5); + + const body = await response.json(); + expect(body).toBeInstanceOf(Object); + }); + + test('enforce timeout (expect to fail if too slow) — set short timeout', { tag: '@api' }, async ({ request }) => { + const delay = 5; + const shortTimeout = 2000; + + try { + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}?delay=${delay}`, { + timeout: shortTimeout + }); + + + expect(response.status()).toBe(200); + } catch (error) { + expect(error.message).toMatch(/timeout|Timeout/i); + } + }); +}); diff --git a/tests/visual.spec.js b/tests/visual.spec.js new file mode 100644 index 0000000..a410be9 --- /dev/null +++ b/tests/visual.spec.js @@ -0,0 +1,23 @@ +import { expect, test } from '@playwright/test'; +import AllPages from '../pages/AllPages.js'; + +let allPages; + +test.beforeEach(async ({ page }) => { + allPages = new AllPages(page); + await page.goto('https://github.com/login'); +}); + +test.describe('Visual Comparison', () => { + + test.describe('GitHub Login Page', () => { + test('visual comparison demo test', { tag: ['@visual', '@chromium'] }, async ({ page }) => { + await page.goto('https://github.com/login'); + await expect(page).toHaveScreenshot('github-login.png'); + + await page.getByRole('textbox', { name: 'Username or email address' }).click(); + await page.getByRole('textbox', { name: 'Username or email address' }).fill('test'); + await expect(page).toHaveScreenshot('github-login-changed.png'); + }); + }); +}); From ffbe84c049347de13c3895a6ee5de97f6988ec8b Mon Sep 17 00:00:00 2001 From: TestDino Date: Tue, 10 Feb 2026 12:38:15 +0530 Subject: [PATCH 15/25] Updated playwright.config file as well as workflow file --- playwright.config.js | 6 ++ tests/delete-api.spec.js | 4 +- tests/post-api.spec.js | 98 ++++++++++++++++++++++++++++ tests/updateUser.spec.js | 134 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 tests/post-api.spec.js create mode 100644 tests/updateUser.spec.js diff --git a/playwright.config.js b/playwright.config.js index a8e812d..8af6021 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -55,5 +55,11 @@ export default defineConfig({ use: { ...devices['iPhone 12'] }, grep: /@ios/, // only run tests tagged @ios }, + + { + name: 'api', + use: { ...devices['API'] }, + grep: /@api/, // only run tests tagged @api + }, ], }); diff --git a/tests/delete-api.spec.js b/tests/delete-api.spec.js index 41a61c1..e85a3da 100644 --- a/tests/delete-api.spec.js +++ b/tests/delete-api.spec.js @@ -17,7 +17,7 @@ test.describe('DELETE User API', () => { expect(body).toHaveProperty('isDeleted', true); }); - test('Remove user twice', { tag: '@api' }, async ({ request }) => { + test.skip('Remove user twice', { tag: '@api' }, async ({ request }) => { const userId = 2; // First deletion @@ -32,7 +32,7 @@ test.describe('DELETE User API', () => { expect(body2).toHaveProperty('id', userId); }); - test('Validate body is returned', { tag: '@api' }, async ({ request }) => { + test.skip('Validate body is returned', { tag: '@api' }, async ({ request }) => { const userId = 3; const response = await request.delete(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}`); diff --git a/tests/post-api.spec.js b/tests/post-api.spec.js new file mode 100644 index 0000000..38059eb --- /dev/null +++ b/tests/post-api.spec.js @@ -0,0 +1,98 @@ +// @ts-check +import { expect, test } from '@playwright/test'; + +// Base API URL - adjust this to match your actual API endpoint +const API_BASE_URL = process.env.API_BASE_URL || 'https://dummyjson.com'; +const USERS_ENDPOINT = '/users'; +const ADD_ENDPOINT = '/users/add'; + +test.describe('POST Create User API', () => { + + test('Bad endpoint returns 404', { tag: '@api' }, async ({ request }) => { + const userData = { + firstName: 'Test', + lastName: 'User' + }; + + const response = await request.post(`${API_BASE_URL}${USERS_ENDPOINT}/invalid-endpoint`, { + data: userData + }); + + expect(response.status()).toBe(404); + }); + + test('Invalid JSON payload handling', { tag: '@api' }, async ({ request }) => { + const response = await request.post(`${API_BASE_URL}${ADD_ENDPOINT}`, { + data: 'invalid json string', + headers: { + 'Content-Type': 'application/json' + } + }); + + // Should return 400 Bad Request for invalid JSON + expect([400, 422]).toContain(response.status()); + }); + + test('Too large ID param should return 404', { tag: '@api' }, async ({ request }) => { + const tooLargeId = 999999999; + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}/${tooLargeId}`); + + expect(response.status()).toBe(404); + }); + + test('Deleting invalid id returns 200/response but not crash', { tag: '@api' }, async ({ request }) => { + const invalidId = 999999; + const response = await request.delete(`${API_BASE_URL}${USERS_ENDPOINT}/${invalidId}`); + + expect([200, 404]).toContain(response.status()); + const body = await response.json(); + expect(body).toBeInstanceOf(Object); + }); + + test('PUT: Invalid method usage returns appropriate response (no 500)', { tag: '@api' }, async ({ request }) => { + const userId = 1; + const updateData = { + firstName: 'Updated' + }; + + // Try PUT on an endpoint that might not support it properly + const response = await request.put(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}/invalid`, { + data: updateData + }); + + // Should return appropriate error (400, 404, 405) but not 500 + expect([400, 404, 405, 200]).toContain(response.status()); + expect(response.status()).not.toBe(500); + }); + + test('user schema contains expected keys', { tag: '@api' }, async ({ request }) => { + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}/1`); + + expect(response.status()).toBe(200); + const body = await response.json(); + + // Validate expected keys in user schema + const expectedKeys = ['id', 'firstName', 'lastName']; + expectedKeys.forEach(key => { + expect(body).toHaveProperty(key); + }); + }); + + test('users list contains objects with id and email', { tag: '@api' },async ({ request }) => { + const response = await request.get(`${API_BASE_URL}${USERS_ENDPOINT}`); + + expect(response.status()).toBe(200); + const body = await response.json(); + const users = body.users || body; + const usersArray = Array.isArray(users) ? users : []; + + if (usersArray.length > 0) { + // Check first user has id and email + const firstUser = usersArray[0]; + expect(firstUser).toHaveProperty('id'); + if (firstUser.email !== undefined) { + expect(typeof firstUser.email).toBe('string'); + } + } + }); +}); diff --git a/tests/updateUser.spec.js b/tests/updateUser.spec.js new file mode 100644 index 0000000..ae4e06a --- /dev/null +++ b/tests/updateUser.spec.js @@ -0,0 +1,134 @@ +// @ts-check +import { expect, test } from '@playwright/test'; + +// Base API URL - adjust this to match your actual API endpoint +const API_BASE_URL = process.env.API_BASE_URL || 'https://dummyjson.com'; +const USERS_ENDPOINT = '/users'; +const AUTH_ENDPOINT = '/auth/login'; + +test.describe('PUT / PATCH Update User API', () => { + + test('Update user details', { tag: '@api' }, async ({ request }) => { + const userId = 1; + const updateData = { + firstName: 'John', + lastName: 'Doe', + age: 30 + }; + + // Try PUT first, fallback to PATCH if needed + const response = await request.put(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}`, { + data: updateData + }); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toHaveProperty('id', userId); + expect(body).toHaveProperty('firstName', updateData.firstName); + expect(body).toHaveProperty('lastName', updateData.lastName); + }); + + test('Update user with empty payload', { tag: '@api' }, async ({ request }) => { + const userId = 2; + const response = await request.put(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}`, { + data: {} + }); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toBeInstanceOf(Object); + expect(body).toHaveProperty('id', userId); + }); + + test('Update only one field', { tag: '@api' }, async ({ request }) => { + const userId = 3; + const updateData = { + firstName: 'UpdatedFirstName' + }; + + // Use PATCH for partial update + const response = await request.patch(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}`, { + data: updateData + }); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toHaveProperty('id', userId); + expect(body).toHaveProperty('firstName', updateData.firstName); + }); + + test('Validate returned name field', { tag: '@api' }, async ({ request }) => { + const userId = 4; + const updateData = { + firstName: 'Jane', + lastName: 'Smith' + }; + + const response = await request.put(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}`, { + data: updateData + }); + + expect(response.status()).toBe(200); + const body = await response.json(); + expect(body).toHaveProperty('firstName'); + expect(body).toHaveProperty('lastName'); + expect(typeof body.firstName).toBe('string'); + expect(typeof body.lastName).toBe('string'); + expect(body.firstName).toBe(updateData.firstName); + expect(body.lastName).toBe(updateData.lastName); + }); + + test('Update and validate response contains updatedAt simulation', { tag: '@api' }, async ({ request }) => { + const userId = 5; + const updateData = { + firstName: 'Updated', + lastName: 'User' + }; + + const response = await request.put(`${API_BASE_URL}${USERS_ENDPOINT}/${userId}`, { + data: updateData + }); + + expect(response.status()).toBe(200); + const body = await response.json(); + + // Check for updatedAt or similar timestamp field + const hasTimestamp = body.hasOwnProperty('updatedAt') || + body.hasOwnProperty('updated') || + body.hasOwnProperty('modifiedAt'); + + // At minimum, validate the response structure + expect(body).toBeInstanceOf(Object); + expect(body).toHaveProperty('id', userId); + }); + + test('Login failure (invalid creds)', { tag: '@api' }, async ({ request }) => { + const loginData = { + username: 'invaliduser', + password: 'wrongpassword' + }; + + const response = await request.post(`${API_BASE_URL}${AUTH_ENDPOINT}`, { + data: loginData + }); + + // Should return error status (400 or 401) + expect([400, 401, 403]).toContain(response.status()); + const body = await response.json(); + expect(body).toBeInstanceOf(Object); + }); + + test('Login missing fields returns 400', { tag: '@api' }, async ({ request }) => { + const loginData = { + username: 'kminchelle' + }; + + const response = await request.post(`${API_BASE_URL}${AUTH_ENDPOINT}`, { + data: loginData + }); + + expect(response.status()).toBe(400); + const body = await response.json(); + expect(body).toBeInstanceOf(Object); + }); +}); From 2253a480651642eec2c7a33241ed12f48514bda9 Mon Sep 17 00:00:00 2001 From: TestDino Date: Tue, 10 Feb 2026 16:30:04 +0530 Subject: [PATCH 16/25] Updated the playwright config file --- tests/cart_checkout.spec.js | 177 ++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 tests/cart_checkout.spec.js diff --git a/tests/cart_checkout.spec.js b/tests/cart_checkout.spec.js new file mode 100644 index 0000000..123f880 --- /dev/null +++ b/tests/cart_checkout.spec.js @@ -0,0 +1,177 @@ +// @ts-check +import { expect, test } from '@playwright/test'; +import AllPages from '../pages/AllPages.js'; + +let allPages; + +test.beforeEach(async ({ page }) => { + allPages = new AllPages(page); + await page.goto('/'); +}); + +test.describe('Cart Module', () => { + test.describe('Product Removal', () => { + test('Verify that user is able to delete selected product from cart ',{tag: '@ios'}, async () => { + const productName = 'GoPro HERO10 Black'; + await allPages.inventoryPage.clickOnAllProductsLink(); + await allPages.inventoryPage.searchProduct(productName); + await allPages.inventoryPage.verifyProductTitleVisible(productName); + await allPages.inventoryPage.clickOnAddToCartIcon(); + + await allPages.cartPage.clickOnCartIcon(); + await allPages.cartPage.verifyCartItemVisible(productName); + await allPages.cartPage.clickOnDeleteProductIcon(); + await allPages.cartPage.verifyCartItemDeleted(productName); + + }); + }); +}); + +test.describe('Orders Module', () => { + test.describe('Order Cancellation', () => { + test('Verify new user views and cancels an order in my orders ',{tag: '@chromium'}, async () => { + const email = `test+${Date.now()}@test.com`; + const firstName = 'Test'; + const lastName = 'User'; + let productName = `Rode NT1-A Condenser Mic`; + + await test.step('Verify that user can register successfully', async () => { + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.clickOnSignupLink(); + // await allPages.signupPage.assertSignupPage(); + // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); + // await allPages.signupPage.verifySuccessSignUp(); + }); + + await test.step('Navigate to All Products and add view details of a random product', async () => { + await allPages.homePage.clickAllProductsNav(); + productName = await allPages.allProductsPage.getNthProductName(1); + await allPages.allProductsPage.clickNthProduct(1); + await allPages.productDetailsPage.clickAddToCartButton(); + }); + + await test.step('Add product to cart, add new address and checkout', async () => { + await allPages.productDetailsPage.clickCartIcon(); + // await allPages.cartPage.assertYourCartTitle(); + // await expect(allPages.cartPage.getCartItemName()).toContainText(productName, { timeout: 10000 }); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.fillShippingAddress( + // firstName, email, 'New York', 'New York', '123 Main St', '10001', 'United States' + // ); + // await allPages.checkoutPage.clickSaveAddressButton(); + // await allPages.checkoutPage.assertAddressAddedToast(); + // }); + + // await test.step('Complete order and verify in my orders', async () => { + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await allPages.inventoryPage.clickOnContinueShopping(); + + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.orderPage.clickOnMyOrdersTab(); + // await allPages.orderPage.clickCancelOrderButton(); + // await allPages.orderPage.confirmCancellation(); + }); + }); + }); +}); + +test.describe('User Journey', () => { + test.describe('Multiple Order Placement', () => { + test('Verify That a New User Can Successfully Complete the Journey from Registration to a Multiple Order Placement ',{tag: '@chromium'}, async () => { + const email = `test+${Date.now()}@test.com`; + const firstName = 'Test'; + const lastName = 'User'; + + await test.step('Verify that user can register successfully', async () => { + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.clickOnSignupLink(); + // await allPages.signupPage.assertSignupPage(); + // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); + // await allPages.signupPage.verifySuccessSignUp(); + }); + + await test.step('Navigate product details and validate tabs', async () => { + await allPages.homePage.clickOnShopNowButton(); + // await allPages.allProductsPage.assertAllProductsTitle(); + // await allPages.allProductsPage.clickNthProduct(1); + // await allPages.productDetailsPage.clickOnReviewsTab(); + // await allPages.productDetailsPage.assertReviewsTab(); + // await allPages.productDetailsPage.clickOnAdditionalInfoTab(); + // await allPages.productDetailsPage.assertAdditionalInfoTab(); + }); + + await test.step('Place first order', async () => { + // await allPages.productDetailsPage.clickAddToCartButton(); + // await allPages.productDetailsPage.clickCartIcon(); + // await allPages.cartPage.clickIncreaseQuantityButton(); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.fillShippingAddress( + // process.env.SFIRST_NAME, + // email, + // process.env.SCITY, + // process.env.SSTATE, + // process.env.SSTREET_ADD, + // process.env.SZIP_CODE, + // process.env.SCOUNTRY + // ); + // await allPages.checkoutPage.clickSaveAddressButton(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await allPages.checkoutPage.clickOnContinueShoppingButton(); + }); + + await test.step('Place second order using existing address', async () => { + // await allPages.homePage.clickOnShopNowButton(); + // await allPages.allProductsPage.assertAllProductsTitle(); + // await allPages.allProductsPage.clickNthProduct(1); + // await allPages.productDetailsPage.clickAddToCartButton(); + // await allPages.productDetailsPage.clickCartIcon(); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + }); + }); + }); +}); + +test.describe('Authentication', () => { + test.describe('Signup & Login', () => { + test('Verify that the new user is able to Sign Up, Log In, and Navigate to the Home Page Successfully ',{tag: '@chromium'}, async () => { + const email = `test+${Date.now()}@test.com`; + const firstName = 'Test'; + const lastName = 'User'; + + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.clickOnSignupLink(); + // await allPages.signupPage.assertSignupPage(); + // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); + // await allPages.signupPage.verifySuccessSignUp(); + + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.login(email, process.env.PASSWORD); + // await allPages.loginPage.verifySuccessSignIn(); + // await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); + }); + }); +}); + +test.describe('User Profile', () => { + test.describe('Personal Information', () => { + test('Verify that user can update personal information ',{tag: '@firefox'}, async () => { + await allPages.userPage.clickOnUserProfileIcon(); + // await allPages.userPage.updatePersonalInfo(); + // await allPages.userPage.verifyPersonalInfoUpdated(); + }); + }); +}); From 2fa0b71b2e2c3eb7afaae996f8a485e22022e8d0 Mon Sep 17 00:00:00 2001 From: Kriti Verma <155474803+kriti2710@users.noreply.github.com> Date: Thu, 5 Mar 2026 10:15:40 +0530 Subject: [PATCH 17/25] Updated test cases by adding tags/annotations feature --- tests/example.spec.js | 1242 ++++++++++++++++++++++------------------- 1 file changed, 671 insertions(+), 571 deletions(-) diff --git a/tests/example.spec.js b/tests/example.spec.js index c2a66c6..8962050 100644 --- a/tests/example.spec.js +++ b/tests/example.spec.js @@ -1,8 +1,6 @@ // @ts-check import { expect, test } from '@playwright/test'; import AllPages from '../pages/AllPages.js'; -import dotenv from 'dotenv'; -dotenv.config({ override: true }); let allPages; @@ -11,590 +9,692 @@ test.beforeEach(async ({ page }) => { await page.goto('/'); }); -async function login(username = process.env.USERNAME, password = process.env.PASSWORD) { - await allPages.loginPage.clickOnUserProfileIcon(); - await allPages.loginPage.validateSignInPage(); - await allPages.loginPage.login(username, password); -} +/* ---------- Helpers ---------- */ -async function login1(username = process.env.USERNAME1, password = process.env.PASSWORD) { +async function login( + username = process.env.USERNAME, + password = process.env.PASSWORD +) { await allPages.loginPage.clickOnUserProfileIcon(); await allPages.loginPage.validateSignInPage(); - await allPages.loginPage.login(username, password); + // await allPages.loginPage.login(username, password); } -async function logout() { - await allPages.loginPage.clickOnUserProfileIcon(); - await allPages.loginPage.clickOnLogoutButton(); -} - -test('Verify that user can login and logout successfully', { tag: '@android' }, async () => { - await login(); - await logout(); -}); - -test('Verify that user can update personal information', { tag: '@webkit' }, async () => { - // await login(); - await allPages.userPage.clickOnUserProfileIcon(); - // await allPages.userPage.updatePersonalInfo(); - // await allPages.userPage.verifyPersonalInfoUpdated(); -}); - -test('Verify that User Can Add, Edit, and Delete Addresses after Logging In', { tag: '@chromium' }, async () => { - // await login(); - - await test.step('Verify that user is able to add address successfully', async () => { - await allPages.userPage.clickOnUserProfileIcon(); - await allPages.userPage.clickOnAddressTab(); - await allPages.userPage.clickOnAddAddressButton(); - await allPages.userPage.fillAddressForm(); - await allPages.userPage.verifytheAddressIsAdded(); - }); - - await test.step('Verify that user is able to edit address successfully', async () => { - await allPages.userPage.clickOnEditAddressButton(); - await allPages.userPage.updateAddressForm(); - await allPages.userPage.verifytheUpdatedAddressIsAdded(); - }) - - await test.step('Verify that user is able to delete address successfully', async () => { - await allPages.userPage.clickOnDeleteAddressButton(); - }); -}); - -test('Verify that user can change password successfully', { tag: '@firefox' }, async () => { - await test.step('Login with existing password', async () => { - // await login1(); - }); - - await test.step('Change password and verify login with new password', async () => { - await allPages.userPage.clickOnUserProfileIcon(); - await allPages.userPage.clickOnSecurityButton(); - await allPages.userPage.enterNewPassword(); - await allPages.userPage.enterConfirmNewPassword(); - await allPages.userPage.clickOnUpdatePasswordButton(); - await allPages.userPage.getUpdatePasswordNotification(); - }); - await test.step('Verify login with new password and revert back to original password', async () => { - // Re-login with new password - await logout(); - await allPages.loginPage.login(process.env.USERNAME1, process.env.NEW_PASSWORD); - - // Revert back - await allPages.userPage.clickOnUserProfileIcon(); - await allPages.userPage.clickOnSecurityButton(); - await allPages.userPage.revertPasswordBackToOriginal(); - await allPages.userPage.getUpdatePasswordNotification(); - }) +/* ---------- FLAKY TESTS (fail on 1st run + 1st retry, pass on 2nd retry) ---------- */ + +test.describe('Flaky tests (pass on 2nd retry)', () => { + test.describe.configure({ retries: 2 }); + + test( + 'Verify that user can login and logout successfully', + { + tag: '@chromium', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Login' }, + { type: 'testdino:link', description: 'https://jira.example.com/LOGIN-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Flaky test: login and logout on Chromium' } + ] + }, + async ({}, testInfo) => { + const start = Date.now(); + await login(); + if (testInfo.retry < 2) { + throw new Error(`Flaky: failing on attempt ${testInfo.retry + 1}, will pass on 2nd retry`); + } + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } + ); + + test( + 'User searches products and views result (Searchbox)', + { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Search' }, + { type: 'testdino:link', description: 'https://jira.example.com/SEARCH-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Flaky test: search products on Firefox' } + ] + }, + async ({}, testInfo) => { + const start = Date.now(); + await login(); + if (testInfo.retry < 2) { + throw new Error(`Flaky: failing on attempt ${testInfo.retry + 1}, will pass on 2nd retry`); + } + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } + ); + + test( + 'User navigates through product categories (Product page)', + { + tag: '@webkit', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Products' }, + { type: 'testdino:link', description: 'https://jira.example.com/PRODUCTS-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Flaky test: product categories on WebKit' } + ] + }, + async ({}, testInfo) => { + const start = Date.now(); + await login(); + if (testInfo.retry < 2) { + throw new Error(`Flaky: failing on attempt ${testInfo.retry + 1}, will pass on 2nd retry`); + } + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } + ); }); -test('Verify that User Can Complete the Journey from Login to Order Placement', { tag: '@webkit' }, async () => { - const productName = 'GoPro HERO10 Black'; - // await login(); - await allPages.inventoryPage.clickOnShopNowButton(); - await allPages.inventoryPage.clickOnAllProductsLink(); - await allPages.inventoryPage.searchProduct(productName); - await allPages.inventoryPage.verifyProductTitleVisible(productName); - await allPages.inventoryPage.clickOnAddToCartIcon(); - - // await allPages.cartPage.clickOnCartIcon(); - // await allPages.cartPage.verifyCartItemVisible(productName); - // await allPages.cartPage.clickOnCheckoutButton(); - // await allPages.checkoutPage.verifyCheckoutTitle(); - // await allPages.checkoutPage.verifyProductInCheckout(productName); - // await allPages.checkoutPage.selectCashOnDelivery(); - // await allPages.checkoutPage.verifyCashOnDeliverySelected(); - // await allPages.checkoutPage.clickOnPlaceOrder(); - // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); -}); - -test('Verify user can place and cancel an order', { tag: '@webkit' }, async () => { - const productName = 'GoPro HERO10 Black'; - const productPriceAndQuantity = '₹49,999 × 1'; - const productQuantity = '1'; - const orderStatusProcessing = 'Processing'; - const orderStatusCanceled = 'Canceled'; - - await test.step('Verify that user can login successfully', async () => { - // await login(); - await allPages.inventoryPage.clickOnAllProductsLink(); - await allPages.inventoryPage.searchProduct(productName); - await allPages.inventoryPage.verifyProductTitleVisible(productName); - await allPages.inventoryPage.clickOnAddToCartIcon(); - }) - - // await test.step('Add product to cart and checkout', async () => { - // await allPages.cartPage.clickOnCartIcon(); - // await allPages.cartPage.verifyCartItemVisible(productName); - // await allPages.cartPage.clickOnCheckoutButton(); - // }) - - // await test.step('Place order and click on continue shopping', async () => { - // await allPages.checkoutPage.verifyCheckoutTitle(); - // await allPages.checkoutPage.verifyProductInCheckout(productName); - // await allPages.checkoutPage.selectCashOnDelivery(); - // await allPages.checkoutPage.verifyCashOnDeliverySelected(); - // await allPages.checkoutPage.clickOnPlaceOrder(); - // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); - // await allPages.checkoutPage.verifyOrderItemName(productName); - // await allPages.inventoryPage.clickOnContinueShopping(); - // }) - - // await test.step('Verify order in My Orders', async () => { - // await allPages.loginPage.clickOnUserProfileIcon(); - // await allPages.orderPage.clickOnMyOrdersTab(); - // await allPages.orderPage.verifyMyOrdersTitle(); - // await allPages.orderPage.clickOnPaginationButton(2); - // await allPages.orderPage.verifyProductInOrderList(productName); - // await allPages.orderPage.verifyPriceAndQuantityInOrderList(productPriceAndQuantity); - // await allPages.orderPage.verifyOrderStatusInList(orderStatusProcessing, productName); - // await allPages.orderPage.clickOnPaginationButton(1); - // await allPages.orderPage.clickViewDetailsButton(1); - // await allPages.orderPage.verifyOrderDetailsTitle(); - // await allPages.orderPage.verifyOrderSummary(productName, productQuantity, '₹49,999', orderStatusProcessing); - // }) - - // await test.step('Cancel order and verify status is updated to Canceled', async () => { - // await allPages.orderPage.clickCancelOrderButton(2); - // await allPages.orderPage.confirmCancellation(); - // await allPages.orderPage.verifyCancellationConfirmationMessage(); - // await allPages.orderPage.verifyMyOrdersCount(); - // await allPages.orderPage.clickOnMyOrdersTab(); - // await allPages.orderPage.verifyMyOrdersTitle(); - // await allPages.orderPage.clickOnPaginationButton(2); - // await allPages.orderPage.verifyOrderStatusInList(orderStatusCanceled, productName); - // }) -}); - -test('Verify that a New User Can Successfully Complete the Journey from Registration to a Single Order Placement', { tag: '@firefox' }, async () => { - // fresh test data - const email = `test+${Date.now()}@test.com`; - const firstName = 'Test'; - const lastName = 'User'; - - let productName; - let productPrice; - let productReviewCount; - - // await test.step('Verify that user can register successfully', async () => { - // await allPages.loginPage.clickOnUserProfileIcon(); - // await allPages.loginPage.validateSignInPage(); - // await allPages.loginPage.clickOnSignupLink(); - // await allPages.signupPage.assertSignupPage(); - // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); - // await allPages.signupPage.verifySuccessSignUp(); - // }) - - // await test.step('Verify that user can login successfully', async () => { - // await allPages.loginPage.validateSignInPage(); - // await allPages.loginPage.login(email, process.env.PASSWORD); - // await allPages.loginPage.verifySuccessSignIn(); - // await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); - // }) - - await test.step('Navigate to all product and add to wishlist section', async () => { - await allPages.homePage.clickAllProductsNav(); - await allPages.allProductsPage.assertAllProductsTitle(); - - productName = await allPages.allProductsPage.getNthProductName(1); - productPrice = await allPages.allProductsPage.getNthProductPrice(1); - productReviewCount = await allPages.allProductsPage.getNthProductReviewCount(1); - - await allPages.allProductsPage.clickNthProductWishlistIcon(1); - await expect(allPages.allProductsPage.getNthProductWishlistIconCount(1)).toContainText('1'); - await allPages.allProductsPage.clickNthProduct(1); - - await allPages.productDetailsPage.assertProductNameTitle(productName); - await allPages.productDetailsPage.assertProductPrice(productName, productPrice); - await allPages.productDetailsPage.assertProductReviewCount(productName, productReviewCount); - await expect(allPages.allProductsPage.getNthProductWishlistIconCount(1)).toContainText('1'); - }) - await test.step('Add product to cart, add new address and checkout', async () => { +/* ---------- STABLE TESTS (NO RANDOM FAILURES) ---------- */ + +test( + 'Verify that all the navbar are working properly', + { + tag: '@webkit', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Navbar' }, + { type: 'testdino:link', description: 'https://jira.example.com/NAVBAR-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Navbar functionality on WebKit' } + ] + }, + async () => { + const start = Date.now(); + await login(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test( + 'Verify that user can edit and delete a product review', + { + tag: '@chromium', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Review' }, + { type: 'testdino:link', description: 'https://jira.example.com/REVIEW-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Edit and delete product review on Chromium' } + ] + }, + async () => { + const start = Date.now(); + await login(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test( + 'Verify that User Can Complete the Journey from Login to Order Placement', + { + tag: '@chromium', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Order' }, + { type: 'testdino:link', description: 'https://jira.example.com/ORDER-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Login to order placement journey on Chromium' } + ] + }, + async () => { + const start = Date.now(); + await login(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test( + 'Verify that user can filter products by price range', + { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Filter' }, + { type: 'testdino:link', description: 'https://jira.example.com/FILTER-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Filter products by price on Firefox' } + ] + }, + async () => { + const start = Date.now(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test( + 'Verify if user can add product to wishlist, move to cart and checkout', + { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Wishlist' }, + { type: 'testdino:link', description: 'https://jira.example.com/WISHLIST-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Wishlist to cart and checkout on Firefox' } + ] + }, + async () => { + const start = Date.now(); + await login(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test( + 'Verify that user is able to submit a product review', + { + tag: '@webkit', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Review' }, + { type: 'testdino:link', description: 'https://jira.example.com/REVIEW-002' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Submit product review on WebKit' } + ] + }, + async () => { + const start = Date.now(); + await login(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test( + 'Verify that all the navbar are working properly (Navbar)', + { + tag: '@webkit', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Navbar' }, + { type: 'testdino:link', description: 'https://jira.example.com/NAVBAR-002' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Navbar (Navbar) on WebKit' } + ] + }, + async () => { + const start = Date.now(); + await login(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test( + 'Verify that user can edit and delete a product review (Single review)', + { + tag: '@chromium', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Review' }, + { type: 'testdino:link', description: 'https://jira.example.com/REVIEW-003' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Edit and delete review (Single review) on Chromium' } + ] + }, + async () => { + const start = Date.now(); + await login(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test( + 'Verify that User Can Complete the Journey from Login to Order Placement (Single order)', + { + tag: '@chromium', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Order' }, + { type: 'testdino:link', description: 'https://jira.example.com/ORDER-002' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Login to order (Single order) on Chromium' } + ] + }, + async () => { + const start = Date.now(); + await login(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test.only( + 'Verify that user can filter products by price range (Price page', + { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Filter' }, + { type: 'testdino:link', description: 'https://jira.example.com/FILTER-002' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Filter by price (Price page) on Firefox' } + ] + }, + async () => { + const start = Date.now(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test.only( + 'Verify if user can add product to wishlist, move to cart(Checkout page)', + { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Wishlist' }, + { type: 'testdino:link', description: 'https://jira.example.com/WISHLIST-002' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Wishlist to cart (Checkout page) on Firefox' } + ] + }, + async () => { + const start = Date.now(); + await login(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test.only( + 'Verify that user is able to submit a product review (Review)', + { + tag: '@webkit', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Review' }, + { type: 'testdino:link', description: 'https://jira.example.com/REVIEW-004' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Submit product review (Review) on WebKit' } + ] + }, + async () => { + const start = Date.now(); + await login(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test.only( + 'Verify that user can update cart quantity and verify total price', + { + tag: '@chromium', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Cart' }, + { type: 'testdino:link', description: 'https://jira.example.com/CART-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Update cart quantity and total price on Chromium' } + ] + }, + async () => { + const start = Date.now(); + await login(); + // await allPages.homePage.clickOnShopNowButton(); + // await allPages.allProductsPage.clickNthProduct(1); // await allPages.productDetailsPage.clickAddToCartButton(); - - // await allPages.productDetailsPage.clickCartIcon(); - // await allPages.cartPage.assertYourCartTitle(); - // await expect(allPages.cartPage.getCartItemName()).toContainText(productName, { timeout: 10000 }); - // await expect(allPages.cartPage.getCartItemPrice()).toContainText(productPrice); - // await expect(allPages.cartPage.getCartItemQuantity()).toContainText('1'); - // await allPages.cartPage.clickIncreaseQuantityButton(); - // await expect(allPages.cartPage.getCartItemQuantity()).toContainText('2'); - - // const cleanPrice = productPrice.replace(/[₹,]/g, ''); - // const priceValue = parseFloat(cleanPrice) * 2; - // await expect(allPages.cartPage.getTotalValue()).toContainText( - // priceValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') - // ); - // await allPages.cartPage.clickOnCheckoutButton(); - - // // Fill shipping address and save - // await allPages.checkoutPage.verifyCheckoutTitle(); - // await allPages.checkoutPage.fillShippingAddress( - // firstName, email, 'New York', 'New York', '123 Main St', '10001', 'United States' - // ); - // await allPages.checkoutPage.clickSaveAddressButton(); - // await allPages.checkoutPage.assertAddressAddedToast(); - - // // COD, verify summary, place order - // await allPages.checkoutPage.selectCashOnDelivery(); - // await allPages.checkoutPage.verifyCheckoutTitle(); - // await allPages.checkoutPage.assertOrderSummaryTitle(); - // await expect(allPages.checkoutPage.getOrderSummaryImage()).toBeVisible(); - // await expect(allPages.checkoutPage.getOrderSummaryProductName()).toContainText(productName); - // await allPages.checkoutPage.verifyProductInCheckout(productName); - // await expect(allPages.checkoutPage.getOrderSummaryProductQuantity()).toContainText('2'); - // await expect(allPages.checkoutPage.getOrderSummaryProductPrice()).toContainText(productPrice); - - // const subtotalValue = parseFloat(cleanPrice) * 2; - // const formattedSubtotal = subtotalValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); - // await expect(await allPages.checkoutPage.getOrderSummarySubtotalValue()).toContain(formattedSubtotal); - // await expect(allPages.checkoutPage.getOrderSummaryShippingValue()).toContainText('Free'); - // await allPages.checkoutPage.clickOnPlaceOrder(); - - // // Order details and return to home - // await allPages.orderDetailsPage.assertOrderDetailsTitle(); - // await allPages.orderDetailsPage.assertOrderPlacedName(); - // await allPages.orderDetailsPage.assertOrderPlacedMessage(); - // await allPages.orderDetailsPage.assertOrderPlacedDate(); - // await allPages.orderDetailsPage.assertOrderInformationTitle(); - // await allPages.orderDetailsPage.assertOrderConfirmedTitle(); - // await allPages.orderDetailsPage.assertOrderConfirmedMessage(); - // await allPages.orderDetailsPage.assertShippingDetailsTitle(); - // await allPages.orderDetailsPage.assertShippingEmailValue(email); - // await allPages.orderDetailsPage.assertPaymentMethodAmount(formattedSubtotal); - // await allPages.orderDetailsPage.assertDeliveryAddressLabel(); - // await allPages.orderDetailsPage.assertDeliveryAddressValue(); - // await allPages.orderDetailsPage.assertContinueShoppingButton(); - - // await allPages.orderDetailsPage.assertOrderSummaryTitle(); - // await allPages.orderDetailsPage.assertOrderSummaryProductName(productName); - // await allPages.orderDetailsPage.assertOrderSummaryProductQuantity('2'); - // await allPages.orderDetailsPage.assertOrderSummaryProductPrice(productPrice); - // await allPages.orderDetailsPage.assertOrderSummarySubtotalValue(formattedSubtotal); - // await allPages.orderDetailsPage.assertOrderSummaryShippingValue('Free'); - // await allPages.orderDetailsPage.assertOrderSummaryTotalValue(formattedSubtotal); - // await allPages.orderDetailsPage.clickBackToHomeButton(); - }); -}); - -test('Verify that user add product to cart before logging in and then complete order after logging in', { tag: '@chromium' }, async () => { - await test.step('Navigate and add product to cart before logging in', async () => { - await allPages.homePage.clickOnShopNowButton(); - await allPages.homePage.clickProductImage(); - await allPages.homePage.clickAddToCartButton(); - await allPages.homePage.validateAddCartNotification(); - // await allPages.loginPage.clickOnUserProfileIcon(); - }) - await test.step('Login and complete order', async () => { - // await login(); // await allPages.cartPage.clickOnCartIcon(); - // await allPages.cartPage.clickOnCheckoutButton(); - // await allPages.checkoutPage.verifyCheckoutTitle(); - // await allPages.checkoutPage.selectCashOnDelivery(); - // await allPages.checkoutPage.verifyCashOnDeliverySelected(); - // await allPages.checkoutPage.clickOnPlaceOrder(); - // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); -}) -}); - -test('Verify that user can filter products by price range', { tag: '@chromium' }, async () => { - // await login(); - await allPages.homePage.clickOnShopNowButton(); - await allPages.homePage.clickOnFilterButton(); - await allPages.homePage.AdjustPriceRangeSlider('10000', '20000'); - await allPages.homePage.clickOnFilterButton(); -}); - -test('Verify if user can add product to wishlist, moves it to card and then checks out', { tag: '@webkit' }, async () => { - // await login(); - - await test.step('Add product to wishlistand then add to cart', async () => { - await allPages.homePage.clickOnShopNowButton(); - await allPages.inventoryPage.addToWishlist(); - await allPages.inventoryPage.assertWishlistIcon(); - await allPages.inventoryPage.clickOnWishlistIconHeader(); - await allPages.inventoryPage.assertWishlistPage(); - await allPages.inventoryPage.clickOnWishlistAddToCard(); - }) - - await test.step('Checkout product added to cart', async () => { - // await allPages.cartPage.clickOnCartIcon(); - // await allPages.cartPage.clickOnCheckoutButton(); - // await allPages.checkoutPage.verifyCheckoutTitle(); - // await allPages.checkoutPage.selectCashOnDelivery(); - // await allPages.checkoutPage.verifyCashOnDeliverySelected(); - // await allPages.checkoutPage.clickOnPlaceOrder(); - // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); - }) - -}); - -test('Verify new user views and cancels an order in my orders', { tag: '@webkit' }, async () => { - const email = `test+${Date.now()}@test.com`; - const firstName = 'Test'; - const lastName = 'User'; - - let productName= `Rode NT1-A Condenser Mic`; - - // await test.step('Verify that user can register successfully', async () => { - // await allPages.loginPage.clickOnUserProfileIcon(); - // await allPages.loginPage.validateSignInPage(); - // await allPages.loginPage.clickOnSignupLink(); - // await allPages.signupPage.assertSignupPage(); - // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); - // await allPages.signupPage.verifySuccessSignUp(); - // }) - - // await test.step('Verify that user can login successfully', async () => { - // await allPages.loginPage.validateSignInPage(); - // await allPages.loginPage.login(email, process.env.PASSWORD); - // await allPages.loginPage.verifySuccessSignIn(); - // await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); - // }) - - await test.step('Navigate to All Products and add view details of a random product', async () => { - await allPages.homePage.clickAllProductsNav(); - await allPages.allProductsPage.assertAllProductsTitle(); - productName = await allPages.allProductsPage.getNthProductName(1); - await allPages.allProductsPage.clickNthProduct(1); - await allPages.productDetailsPage.clickAddToCartButton(); - }) - - // await test.step('Add product to cart, add new address and checkout', async () => { - // await allPages.productDetailsPage.clickCartIcon(); - // await allPages.cartPage.assertYourCartTitle(); - // await expect(allPages.cartPage.getCartItemName()).toContainText(productName, { timeout: 10000 }); - // await allPages.cartPage.clickOnCheckoutButton(); - // await allPages.checkoutPage.verifyCheckoutTitle(); - // await allPages.checkoutPage.fillShippingAddress( - // firstName, email, 'New York', 'New York', '123 Main St', '10001', 'United States' - // ); - // await allPages.checkoutPage.clickSaveAddressButton(); - // await allPages.checkoutPage.assertAddressAddedToast(); - // }) - - // await test.step('Complete order and verify in my orders', async () => { - // await allPages.checkoutPage.selectCashOnDelivery(); - // await allPages.checkoutPage.verifyCheckoutTitle(); - // await allPages.checkoutPage.clickOnPlaceOrder(); - // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); - // await allPages.inventoryPage.clickOnContinueShopping(); - - // await allPages.loginPage.clickOnUserProfileIcon(); - // await allPages.orderPage.clickOnMyOrdersTab(); - // await allPages.orderPage.clickCancelOrderButton(); - // await allPages.orderPage.confirmCancellation(); - // }); -}); - -test('Verify That a New User Can Successfully Complete the Journey from Registration to a Multiple Order Placement', { tag: '@webkit' }, async () => { - const email = `test+${Date.now()}@test.com`; - const firstName = 'Test'; - const lastName = 'User'; - - let productName= `Rode NT1-A Condenser Mic`; - - // await test.step('Verify that user can register successfully', async () => { - // // Signup - // await allPages.loginPage.clickOnUserProfileIcon(); - // await allPages.loginPage.validateSignInPage(); - // await allPages.loginPage.clickOnSignupLink(); - // await allPages.signupPage.assertSignupPage(); - // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); - // await allPages.signupPage.verifySuccessSignUp(); - // }) - - // await test.step('Verify that user can login successfully', async () => { - // // Login as new user - // await allPages.loginPage.validateSignInPage(); - // await allPages.loginPage.login(email, process.env.PASSWORD); - // await allPages.loginPage.verifySuccessSignIn(); - // await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); - // }) - - await test.step('Navigate to All Products and add view details of a random product', async () => { - await allPages.homePage.clickOnShopNowButton(); - await allPages.allProductsPage.assertAllProductsTitle(); - await allPages.allProductsPage.clickNthProduct(1); - await allPages.productDetailsPage.clickOnReviewsTab(); - await allPages.productDetailsPage.assertReviewsTab(); - await allPages.productDetailsPage.clickOnAdditionalInfoTab(); - await allPages.productDetailsPage.assertAdditionalInfoTab(); - }) - - await test.step('Add product to cart, change quantity, add new address and checkout', async () => { - // await allPages.productDetailsPage.clickAddToCartButton(); - // await allPages.productDetailsPage.clickCartIcon(); // await allPages.cartPage.clickIncreaseQuantityButton(); - // await allPages.cartPage.clickOnCheckoutButton(); - // await allPages.checkoutPage.verifyCheckoutTitle(); - // await allPages.checkoutPage.selectCashOnDelivery(); - // await allPages.checkoutPage.verifyCashOnDeliverySelected(); - // await allPages.checkoutPage.fillShippingAddress(process.env.SFIRST_NAME, email, process.env.SCITY, process.env.SSTATE, process.env.SSTREET_ADD, process.env.SZIP_CODE, process.env.SCOUNTRY); - // await allPages.checkoutPage.clickSaveAddressButton(); - // await allPages.checkoutPage.clickOnPlaceOrder(); - // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); - // await allPages.checkoutPage.verifyOrderConfirmedTitle(); - // await allPages.checkoutPage.clickOnContinueShoppingButton(); - }) - - await test.step('Add another product to cart, select existing address and checkout', async () => { + // await allPages.cartPage.verifyTotalPriceUpdated(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test.only( + 'Verify that user can view order history and order detail (Order page)', + { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Order' }, + { type: 'testdino:link', description: 'https://jira.example.com/ORDER-003' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Order history and order detail (Order page) on Firefox' } + ] + }, + async () => { + const start = Date.now(); + await login(); + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.orderPage.clickOnMyOrdersTab(); + // await allPages.orderPage.verifyOrdersListVisible(); + // await allPages.orderPage.clickOnFirstOrder(); + // await allPages.orderDetailsPage.verifyOrderDetailsDisplayed(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test.only( + 'Verify that user can update cart quantity and verify total price (Pricing)', + { + tag: '@chromium', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Cart' }, + { type: 'testdino:link', description: 'https://jira.example.com/CART-002' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Cart quantity and total price (Pricing) on Chromium' } + ] + }, + async () => { + const start = Date.now(); + await login(); // await allPages.homePage.clickOnShopNowButton(); - // await allPages.allProductsPage.assertAllProductsTitle(); // await allPages.allProductsPage.clickNthProduct(1); // await allPages.productDetailsPage.clickAddToCartButton(); - // await allPages.productDetailsPage.clickCartIcon(); - // await allPages.cartPage.clickOnCheckoutButton(); - // await allPages.checkoutPage.verifyCheckoutTitle(); - // await allPages.checkoutPage.selectCashOnDelivery(); - // await allPages.checkoutPage.verifyCashOnDeliverySelected(); - // await allPages.checkoutPage.clickOnPlaceOrder(); - // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); - }) -}); - -test('Verify that the new user is able to Sign Up, Log In, and Navigate to the Home Page Successfully', { tag: '@ios' }, async () => { - const email = `test+${Date.now()}@test.com`; - const firstName = 'Test'; - const lastName = 'User'; - -// await test.step('Verify that user can register successfully', async () => { -// await allPages.loginPage.clickOnUserProfileIcon(); -// await allPages.loginPage.validateSignInPage(); -// await allPages.loginPage.clickOnSignupLink(); -// await allPages.signupPage.assertSignupPage(); -// await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); -// await allPages.signupPage.verifySuccessSignUp(); -// }) - -// await test.step('Verify that user can login successfully', async () => { -// await allPages.loginPage.validateSignInPage(); -// await allPages.loginPage.login(email, process.env.PASSWORD); -// await allPages.loginPage.verifySuccessSignIn(); -// await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); -// }) -}) - -test('Verify that user is able to fill Contact Us page successfully', { tag: '@firefox' }, async () => { - // await login(); - await allPages.homePage.clickOnContactUsLink(); - await allPages.contactUsPage.assertContactUsTitle(); - await allPages.contactUsPage.fillContactUsForm(); - await allPages.contactUsPage.verifySuccessContactUsFormSubmission(); -}); - -test('Verify that user is able to submit a product review', { tag: '@android' }, async () => { - await test.step('Login as existing user and navigate to a product', async () => { - // await login(); - }) - - await test.step('Navigate to all product section and select a product', async () => { - await allPages.homePage.clickOnShopNowButton(); - await allPages.allProductsPage.assertAllProductsTitle(); - await allPages.allProductsPage.clickNthProduct(1); - }) - - await test.step('Submit a product review and verify submission', async () => { - await allPages.productDetailsPage.clickOnReviewsTab(); - await allPages.productDetailsPage.assertReviewsTab(); - - await allPages.productDetailsPage.clickOnWriteAReviewBtn(); - await allPages.productDetailsPage.fillReviewForm(); - await allPages.productDetailsPage.assertSubmittedReview({ - name: 'John Doe', - title: 'Great Product', - opinion: 'This product exceeded my expectations. Highly recommend!' - }); - }) -}); - -test('Verify that user can edit and delete a product review', { tag: '@chromium' }, async () => { - await test.step('Login as existing user and navigate to a product', async () => { - // await login(); - }) - - await test.step('Navigate to all product section and select a product', async () => { - await allPages.homePage.clickOnShopNowButton(); - await allPages.allProductsPage.assertAllProductsTitle(); - await allPages.allProductsPage.clickNthProduct(1); - }) - - await test.step('Submit a product review and verify submission', async () => { - await allPages.productDetailsPage.clickOnReviewsTab(); - await allPages.productDetailsPage.assertReviewsTab(); - - await allPages.productDetailsPage.clickOnWriteAReviewBtn(); - await allPages.productDetailsPage.fillReviewForm(); - await allPages.productDetailsPage.assertSubmittedReview({ - name: 'John Doe', - title: 'Great Product', - opinion: 'This product exceeded my expectations. Highly recommend!' - }); - }) - - await test.step('Edit the submitted review and verify changes', async () => { - await allPages.productDetailsPage.clickOnEditReviewBtn(); - await allPages.productDetailsPage.updateReviewForm(); - await allPages.productDetailsPage.assertUpdatedReview({ - title: 'Updated Review Title', - opinion: 'This is an updated review opinion.' - }) + // await allPages.cartPage.clickOnCartIcon(); + // await allPages.cartPage.clickIncreaseQuantityButton(); + // await allPages.cartPage.verifyTotalPriceUpdated(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), }); - - await test.step('Delete the submitted review and verify deletion', async () => { - await allPages.productDetailsPage.clickOnDeleteReviewBtn(); - }) -}); - -test('Verify that user can purchase multiple quantities in a single order', { tag: '@ios' }, async () => { - const productName = 'GoPro HERO10 Black'; + } +); + +test.only( + 'Verify that user can view order history and order details properly (Order details)', + { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Order' }, + { type: 'testdino:link', description: 'https://jira.example.com/ORDER-004' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Order history and details (Order details) on Firefox' } + ] + }, + async () => { + const start = Date.now(); await login(); - await allPages.inventoryPage.clickOnShopNowButton(); - await allPages.inventoryPage.clickOnAllProductsLink(); - await allPages.inventoryPage.searchProduct(productName); - await allPages.inventoryPage.verifyProductTitleVisible(productName); - await allPages.inventoryPage.clickOnAddToCartIcon(); - - await allPages.cartPage.clickOnCartIcon(); - await allPages.cartPage.verifyCartItemVisible(productName); - await allPages.cartPage.clickIncreaseQuantityButton(); - await allPages.cartPage.verifyIncreasedQuantity('3'); - await allPages.cartPage.clickOnCheckoutButton(); - await allPages.checkoutPage.verifyCheckoutTitle(); - await allPages.checkoutPage.verifyProductInCheckout(productName); - await allPages.checkoutPage.selectCashOnDelivery(); - await allPages.checkoutPage.verifyCashOnDeliverySelected(); - await allPages.checkoutPage.clickOnPlaceOrder(); - await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); -}); - -test('Verify that all the navbar are working properly', { tag: '@ios' }, async () => { + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.orderPage.clickOnMyOrdersTab(); + // await allPages.orderPage.verifyOrdersListVisible(); + // await allPages.orderPage.clickOnFirstOrder(); + // await allPages.orderDetailsPage.verifyOrderDetailsDisplayed(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test( + 'Verify that users can update cart quantity and verify total price (Single order)', + { + tag: '@chromium', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Cart' }, + { type: 'testdino:link', description: 'https://jira.example.com/CART-003' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Cart quantity (Single order) on Chromium' } + ] + }, + async () => { + const start = Date.now(); await login(); - await allPages.homePage.clickBackToHomeButton(); - // await allPages.homePage.assertHomePage(); - await allPages.homePage.clickAllProductsNav(); - await allPages.allProductsPage.assertAllProductsTitle(); - await allPages.homePage.clickOnContactUsLink(); - await allPages.contactUsPage.assertContactUsTitle(); - await allPages.homePage.clickAboutUsNav(); - await allPages.homePage.assertAboutUsTitle(); -}); - -test('Verify that user is able to delete selected product from cart', { tag: '@android' }, async () => { - const productName = 'GoPro HERO10 Black'; + // await allPages.homePage.clickOnShopNowButton(); + // await allPages.allProductsPage.clickNthProduct(1); + // await allPages.productDetailsPage.clickAddToCartButton(); + // await allPages.cartPage.clickOnCartIcon(); + // await allPages.cartPage.clickIncreaseQuantityButton(); + // await allPages.cartPage.verifyTotalPriceUpdated(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); + +test( + 'Verify that users can view order history and order details properly (Order history)', + { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Order' }, + { type: 'testdino:link', description: 'https://jira.example.com/ORDER-005' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Order history on Firefox' } + ] + }, + async () => { + const start = Date.now(); await login(); - await allPages.inventoryPage.clickOnShopNowButton(); - await allPages.inventoryPage.clickOnAllProductsLink(); - await allPages.inventoryPage.searchProduct(productName); - await allPages.inventoryPage.verifyProductTitleVisible(productName); - await allPages.inventoryPage.clickOnAddToCartIcon(); - - await allPages.cartPage.clickOnCartIcon(); - await allPages.cartPage.verifyCartItemVisible(productName); - await allPages.cartPage.clickOnDeleteProductIcon(); - await allPages.cartPage.verifyCartItemDeleted(productName); - await allPages.cartPage.verifyEmptyCartMessage(); - await allPages.cartPage.clickOnStartShoppingButton(); - await allPages.allProductsPage.assertAllProductsTitle(); -}); \ No newline at end of file + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.orderPage.clickOnMyOrdersTab(); + // await allPages.orderPage.verifyOrdersListVisible(); + // await allPages.orderPage.clickOnFirstOrder(); + // await allPages.orderDetailsPage.verifyOrderDetailsDisplayed(); + await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + } +); From 6b38fd2ab22bc690cd1f251eb4afa2d3eb361c7c Mon Sep 17 00:00:00 2001 From: Kriti Verma <155474803+kriti2710@users.noreply.github.com> Date: Thu, 5 Mar 2026 10:20:35 +0530 Subject: [PATCH 18/25] Updated test cases by adding tags/annotations feature --- tests/example.spec.js | 1301 ++++++++++++++++++++++------------------- 1 file changed, 689 insertions(+), 612 deletions(-) diff --git a/tests/example.spec.js b/tests/example.spec.js index 8962050..96da862 100644 --- a/tests/example.spec.js +++ b/tests/example.spec.js @@ -1,6 +1,8 @@ // @ts-check import { expect, test } from '@playwright/test'; import AllPages from '../pages/AllPages.js'; +import dotenv from 'dotenv'; +dotenv.config({ override: true }); let allPages; @@ -9,172 +11,70 @@ test.beforeEach(async ({ page }) => { await page.goto('/'); }); -/* ---------- Helpers ---------- */ - -async function login( - username = process.env.USERNAME, - password = process.env.PASSWORD -) { +async function login(username = process.env.USERNAME, password = process.env.PASSWORD) { await allPages.loginPage.clickOnUserProfileIcon(); await allPages.loginPage.validateSignInPage(); - // await allPages.loginPage.login(username, password); + await allPages.loginPage.login(username, password); } -/* ---------- FLAKY TESTS (fail on 1st run + 1st retry, pass on 2nd retry) ---------- */ +async function login1(username = process.env.USERNAME1, password = process.env.PASSWORD) { + await allPages.loginPage.clickOnUserProfileIcon(); + await allPages.loginPage.validateSignInPage(); + await allPages.loginPage.login(username, password); +} -test.describe('Flaky tests (pass on 2nd retry)', () => { - test.describe.configure({ retries: 2 }); +async function logout() { + await allPages.loginPage.clickOnUserProfileIcon(); + await allPages.loginPage.clickOnLogoutButton(); +} - test( - 'Verify that user can login and logout successfully', - { - tag: '@chromium', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Login' }, - { type: 'testdino:link', description: 'https://jira.example.com/LOGIN-001' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Flaky test: login and logout on Chromium' } - ] - }, - async ({}, testInfo) => { - const start = Date.now(); - await login(); - if (testInfo.retry < 2) { - throw new Error(`Flaky: failing on attempt ${testInfo.retry + 1}, will pass on 2nd retry`); - } - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } - ); - - test( - 'User searches products and views result (Searchbox)', - { - tag: '@firefox', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Search' }, - { type: 'testdino:link', description: 'https://jira.example.com/SEARCH-001' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Flaky test: search products on Firefox' } - ] - }, - async ({}, testInfo) => { - const start = Date.now(); - await login(); - if (testInfo.retry < 2) { - throw new Error(`Flaky: failing on attempt ${testInfo.retry + 1}, will pass on 2nd retry`); - } - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } - ); - - test( - 'User navigates through product categories (Product page)', - { - tag: '@webkit', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Products' }, - { type: 'testdino:link', description: 'https://jira.example.com/PRODUCTS-001' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Flaky test: product categories on WebKit' } - ] - }, - async ({}, testInfo) => { - const start = Date.now(); - await login(); - if (testInfo.retry < 2) { - throw new Error(`Flaky: failing on attempt ${testInfo.retry + 1}, will pass on 2nd retry`); - } - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } - ); +test('Verify that user can log in and log out successfully', { + tag: '@android', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Login' }, + { type: 'testdino:link', description: 'https://jira.example.com/LOGIN-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Login and logout on Android' } + ] +}, async () => { + const start = Date.now(); + await login(); + await logout(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); }); - -/* ---------- STABLE TESTS (NO RANDOM FAILURES) ---------- */ - -test( - 'Verify that all the navbar are working properly', - { - tag: '@webkit', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Navbar' }, - { type: 'testdino:link', description: 'https://jira.example.com/NAVBAR-001' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Navbar functionality on WebKit' } - ] - }, - async () => { - const start = Date.now(); - await login(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } -); - -test( - 'Verify that user can edit and delete a product review', - { - tag: '@chromium', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Review' }, - { type: 'testdino:link', description: 'https://jira.example.com/REVIEW-001' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Edit and delete product review on Chromium' } - ] - }, - async () => { +test('Verify that all navbar links work properly', { + tag: '@webkit', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Navbar' }, + { type: 'testdino:link', description: 'https://jira.example.com/NAVBAR-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Navbar functionality on WebKit' } + ] +}, async () => { const start = Date.now(); - await login(); - await expect(true).toBeTruthy(); + // await login(); + await allPages.homePage.clickBackToHomeButton(); + // await allPages.homePage.assertHomePage(); + await allPages.homePage.clickAllProductsNav(); + await allPages.allProductsPage.assertAllProductsTitle(); + await allPages.homePage.clickOnContactUsLink(); + await allPages.contactUsPage.assertContactUsTitle(); + await allPages.homePage.clickAboutUsNav(); + await allPages.homePage.assertAboutUsTitle(); const flowTime = Date.now() - start; test.info().annotations.push({ type: 'testdino:metric', @@ -185,205 +85,301 @@ test( threshold: 5000, }), }); - } -); - -test( - 'Verify that User Can Complete the Journey from Login to Order Placement', - { - tag: '@chromium', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Order' }, - { type: 'testdino:link', description: 'https://jira.example.com/ORDER-001' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Login to order placement journey on Chromium' } - ] - }, - async () => { - const start = Date.now(); - await login(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } -); - -test( - 'Verify that user can filter products by price range', - { - tag: '@firefox', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Filter' }, - { type: 'testdino:link', description: 'https://jira.example.com/FILTER-001' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Filter products by price on Firefox' } - ] - }, - async () => { - const start = Date.now(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } -); - -test( - 'Verify if user can add product to wishlist, move to cart and checkout', - { - tag: '@firefox', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Wishlist' }, - { type: 'testdino:link', description: 'https://jira.example.com/WISHLIST-001' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Wishlist to cart and checkout on Firefox' } - ] - }, - async () => { - const start = Date.now(); - await login(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } -); - -test( - 'Verify that user is able to submit a product review', - { - tag: '@webkit', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Review' }, - { type: 'testdino:link', description: 'https://jira.example.com/REVIEW-002' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Submit product review on WebKit' } - ] - }, - async () => { - const start = Date.now(); - await login(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } -); - -test( - 'Verify that all the navbar are working properly (Navbar)', - { - tag: '@webkit', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Navbar' }, - { type: 'testdino:link', description: 'https://jira.example.com/NAVBAR-002' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Navbar (Navbar) on WebKit' } - ] - }, - async () => { - const start = Date.now(); - await login(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } -); - -test( - 'Verify that user can edit and delete a product review (Single review)', - { - tag: '@chromium', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Review' }, - { type: 'testdino:link', description: 'https://jira.example.com/REVIEW-003' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Edit and delete review (Single review) on Chromium' } - ] - }, - async () => { - const start = Date.now(); - await login(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), +}); + +test('Verify that user can edit and delete a product review', { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Review' }, + { type: 'testdino:link', description: 'https://jira.example.com/REVIEW-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Edit and delete product review on Firefox' } + ] +}, async () => { + const start = Date.now(); + await test.step('Login as existing user and navigate to a product', async () => { + // await login(); + }) + + await test.step('Navigate to all product section and select a product', async () => { + await allPages.homePage.clickOnShopNowButton(); + await allPages.allProductsPage.assertAllProductsTitle(); + await allPages.allProductsPage.clickNthProduct(1); + }) + + await test.step('Submit a product review and verify submission', async () => { + await allPages.productDetailsPage.clickOnReviewsTab(); + await allPages.productDetailsPage.assertReviewsTab(); + + await allPages.productDetailsPage.clickOnWriteAReviewBtn(); + await allPages.productDetailsPage.fillReviewForm(); + await allPages.productDetailsPage.assertSubmittedReview({ + name: 'John Doe', + title: 'Great Product', + opinion: 'This product exceeded my expectations. Highly recommend!' + }); + }) + + await test.step('Edit the submitted review and verify changes', async () => { + await allPages.productDetailsPage.clickOnEditReviewBtn(); + await allPages.productDetailsPage.updateReviewForm(); + await allPages.productDetailsPage.assertUpdatedReview({ + title: 'Updated Review Title', + opinion: 'This is an updated review opinion.' + }) }); - } -); - -test( - 'Verify that User Can Complete the Journey from Login to Order Placement (Single order)', - { - tag: '@chromium', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Order' }, - { type: 'testdino:link', description: 'https://jira.example.com/ORDER-002' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Login to order (Single order) on Chromium' } - ] - }, - async () => { + + await test.step('Delete the submitted review and verify deletion', async () => { + await allPages.productDetailsPage.clickOnDeleteReviewBtn(); + }); + + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); +}); + +test('Verify that user can complete the journey from login to order placement', { + tag: '@ios', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Order' }, + { type: 'testdino:link', description: 'https://jira.example.com/ORDER-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Login to order placement journey on iOS' } + ] +}, async () => { + const start = Date.now(); + const productName = 'GoPro HERO10 Black'; + // await login(); + await allPages.inventoryPage.clickOnShopNowButton(); + await allPages.inventoryPage.clickOnAllProductsLink(); + await allPages.inventoryPage.searchProduct(productName); + await allPages.inventoryPage.verifyProductTitleVisible(productName); + await allPages.inventoryPage.clickOnAddToCartIcon(); + + // await allPages.cartPage.clickOnCartIcon(); + // await allPages.cartPage.verifyCartItemVisible(productName); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.verifyProductInCheckout(productName); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCashOnDeliverySelected(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); +}); + +test('Verify that a new user can complete the journey from registration to a single order placement', { + tag: '@android', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Registration' }, + { type: 'testdino:link', description: 'https://jira.example.com/REG-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Registration to single order on Android' } + ] +}, async () => { + const start = Date.now(); + // fresh test data + const email = `test+${Date.now()}@test.com`; + const firstName = 'Test'; + const lastName = 'User'; + + let productName; + let productPrice; + let productReviewCount; + + await test.step('Verify that user can register successfully', async () => { + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.clickOnSignupLink(); + // await allPages.signupPage.assertSignupPage(); + // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); + // await allPages.signupPage.verifySuccessSignUp(); + }) + + await test.step('Verify that user can login successfully', async () => { + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.login(email, process.env.PASSWORD); + // await allPages.loginPage.verifySuccessSignIn(); + // await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); + }) + + await test.step('Navigate to all product and add to wishlist section', async () => { + await allPages.homePage.clickAllProductsNav(); + await allPages.allProductsPage.assertAllProductsTitle(); + + productName = await allPages.allProductsPage.getNthProductName(1); + productPrice = await allPages.allProductsPage.getNthProductPrice(1); + productReviewCount = await allPages.allProductsPage.getNthProductReviewCount(1); + + await allPages.allProductsPage.clickNthProductWishlistIcon(1); + await expect(allPages.allProductsPage.getNthProductWishlistIconCount(1)).toContainText('1'); + await allPages.allProductsPage.clickNthProduct(1); + + await allPages.productDetailsPage.assertProductNameTitle(productName); + await allPages.productDetailsPage.assertProductPrice(productName, productPrice); + await allPages.productDetailsPage.assertProductReviewCount(productName, productReviewCount); + await expect(allPages.allProductsPage.getNthProductWishlistIconCount(1)).toContainText('1'); + }) + + await test.step('Add product to cart, add new address and checkout', async () => { + await allPages.productDetailsPage.clickAddToCartButton(); + + // await allPages.productDetailsPage.clickCartIcon(); + // await allPages.cartPage.assertYourCartTitle(); + // await expect(allPages.cartPage.getCartItemName()).toContainText(productName, { timeout: 10000 }); + // await expect(allPages.cartPage.getCartItemPrice()).toContainText(productPrice); + // await expect(allPages.cartPage.getCartItemQuantity()).toContainText('1'); + // await allPages.cartPage.clickIncreaseQuantityButton(); + // await expect(allPages.cartPage.getCartItemQuantity()).toContainText('2'); + + // const cleanPrice = productPrice.replace(/[₹,]/g, ''); + // const priceValue = parseFloat(cleanPrice) * 2; + // await expect(allPages.cartPage.getTotalValue()).toContainText( + // priceValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') + // ); + // await allPages.cartPage.clickOnCheckoutButton(); + + // // Fill shipping address and save + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.fillShippingAddress( + // firstName, email, 'New York', 'New York', '123 Main St', '10001', 'United States' + // ); + // await allPages.checkoutPage.clickSaveAddressButton(); + // await allPages.checkoutPage.assertAddressAddedToast(); + + // // COD, verify summary, place order + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.assertOrderSummaryTitle(); + // await expect(allPages.checkoutPage.getOrderSummaryImage()).toBeVisible(); + // await expect(allPages.checkoutPage.getOrderSummaryProductName()).toContainText(productName); + // await allPages.checkoutPage.verifyProductInCheckout(productName); + // await expect(allPages.checkoutPage.getOrderSummaryProductQuantity()).toContainText('2'); + // await expect(allPages.checkoutPage.getOrderSummaryProductPrice()).toContainText(productPrice); + + // const subtotalValue = parseFloat(cleanPrice) * 2; + // const formattedSubtotal = subtotalValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); + // await expect(await allPages.checkoutPage.getOrderSummarySubtotalValue()).toContain(formattedSubtotal); + // await expect(allPages.checkoutPage.getOrderSummaryShippingValue()).toContainText('Free'); + // await allPages.checkoutPage.clickOnPlaceOrder(); + + // // Order details and return to home + // await allPages.orderDetailsPage.assertOrderDetailsTitle(); + // await allPages.orderDetailsPage.assertOrderPlacedName(); + // await allPages.orderDetailsPage.assertOrderPlacedMessage(); + // await allPages.orderDetailsPage.assertOrderPlacedDate(); + // await allPages.orderDetailsPage.assertOrderInformationTitle(); + // await allPages.orderDetailsPage.assertOrderConfirmedTitle(); + // await allPages.orderDetailsPage.assertOrderConfirmedMessage(); + // await allPages.orderDetailsPage.assertShippingDetailsTitle(); + // await allPages.orderDetailsPage.assertShippingEmailValue(email); + // await allPages.orderDetailsPage.assertPaymentMethodAmount(formattedSubtotal); + // await allPages.orderDetailsPage.assertDeliveryAddressLabel(); + // await allPages.orderDetailsPage.assertDeliveryAddressValue(); + // await allPages.orderDetailsPage.assertContinueShoppingButton(); + + // await allPages.orderDetailsPage.assertOrderSummaryTitle(); + // await allPages.orderDetailsPage.assertOrderSummaryProductName(productName); + // await allPages.orderDetailsPage.assertOrderSummaryProductQuantity('2'); + // await allPages.orderDetailsPage.assertOrderSummaryProductPrice(productPrice); + // await allPages.orderDetailsPage.assertOrderSummarySubtotalValue(formattedSubtotal); + // await allPages.orderDetailsPage.assertOrderSummaryShippingValue('Free'); + // await allPages.orderDetailsPage.assertOrderSummaryTotalValue(formattedSubtotal); + // await allPages.orderDetailsPage.clickBackToHomeButton(); + }); + + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); +}); + +test('Verify that user can add product to cart before logging in and complete order after logging in', { + tag: '@webkit', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Cart' }, + { type: 'testdino:link', description: 'https://jira.example.com/CART-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Add to cart before login, order after login on WebKit' } + ] +}, async () => { + const start = Date.now(); + await test.step('Navigate and add product to cart before logging in', async () => { + await allPages.homePage.clickOnShopNowButton(); + await allPages.homePage.clickProductImage(); + await allPages.homePage.clickAddToCartButton(); + await allPages.homePage.validateAddCartNotification(); + // await allPages.loginPage.clickOnUserProfileIcon(); + }) + // await test.step('Login and complete order', async () => { +// await login(); +// await allPages.cartPage.clickOnCartIcon(); +// await allPages.cartPage.clickOnCheckoutButton(); +// await allPages.checkoutPage.verifyCheckoutTitle(); +// await allPages.checkoutPage.selectCashOnDelivery(); +// await allPages.checkoutPage.verifyCashOnDeliverySelected(); +// await allPages.checkoutPage.clickOnPlaceOrder(); +// await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); +// }) + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); +}); + +test('Verify that user can filter products by price range', { + tag: '@filter', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Filter' }, + { type: 'testdino:link', description: 'https://jira.example.com/FILTER-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Filter products by price range' } + ] +}, async () => { const start = Date.now(); await login(); - await expect(true).toBeTruthy(); + await allPages.homePage.clickOnShopNowButton(); + await allPages.homePage.clickOnFilterButton(); + await allPages.homePage.AdjustPriceRangeSlider('10000', '20000'); + await allPages.homePage.clickOnFilterButton(); const flowTime = Date.now() - start; test.info().annotations.push({ type: 'testdino:metric', @@ -394,55 +390,41 @@ test( threshold: 5000, }), }); - } -); - -test.only( - 'Verify that user can filter products by price range (Price page', - { - tag: '@firefox', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Filter' }, - { type: 'testdino:link', description: 'https://jira.example.com/FILTER-002' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Filter by price (Price page) on Firefox' } - ] - }, - async () => { +}); + +test('Verify that user can add product to wishlist, move it to cart, and checkout', { + tag: '@wishlist', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Wishlist' }, + { type: 'testdino:link', description: 'https://jira.example.com/WISHLIST-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Wishlist to cart and checkout' } + ] +}, async () => { const start = Date.now(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), + // await login(); + + await test.step('Add product to wishlistand then add to cart', async () => { + await allPages.homePage.clickOnShopNowButton(); + await allPages.inventoryPage.addToWishlist(); + await allPages.inventoryPage.assertWishlistIcon(); + await allPages.inventoryPage.clickOnWishlistIconHeader(); + await allPages.inventoryPage.assertWishlistPage(); + await allPages.inventoryPage.clickOnWishlistAddToCard(); + }) + + await test.step('Checkout product added to cart', async () => { + await allPages.cartPage.clickOnCartIcon(); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCashOnDeliverySelected(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); }); - } -); - -test.only( - 'Verify if user can add product to wishlist, move to cart(Checkout page)', - { - tag: '@firefox', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Wishlist' }, - { type: 'testdino:link', description: 'https://jira.example.com/WISHLIST-002' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Wishlist to cart (Checkout page) on Firefox' } - ] - }, - async () => { - const start = Date.now(); - await login(); - await expect(true).toBeTruthy(); + const flowTime = Date.now() - start; test.info().annotations.push({ type: 'testdino:metric', @@ -453,204 +435,222 @@ test.only( threshold: 5000, }), }); - } -); - -test.only( - 'Verify that user is able to submit a product review (Review)', - { - tag: '@webkit', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Review' }, - { type: 'testdino:link', description: 'https://jira.example.com/REVIEW-004' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Submit product review (Review) on WebKit' } - ] - }, - async () => { +}); + +test.describe('Orders Module', () => { + test.describe('Order Cancellation', () => { + test('Verify that new user can view and cancel an order in My Orders', { + tag: '@chromium', + annotation: [ + { type: 'testdino:priority', description: 'p0' }, + { type: 'testdino:feature', description: 'Orders' }, + { type: 'testdino:link', description: 'https://jira.example.com/ORDER-002' }, + { type: 'testdino:owner', description: '@Kriti Verma' }, + { type: 'testdino:notify-slack', description: '@Kriti Verma' }, + { type: 'testdino:context', description: 'Critical order cancellation flow for new users' } + ] + }, async () => { const start = Date.now(); - await login(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), + const email = `test+${Date.now()}@test.com`; + const firstName = 'Test'; + const lastName = 'User'; + + let productName= `Rode NT1-A Condenser Mic`; + + // await test.step('Verify that user can register successfully', async () => { + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.clickOnSignupLink(); + // await allPages.signupPage.assertSignupPage(); + // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); + // await allPages.signupPage.verifySuccessSignUp(); + // }) + + // await test.step('Verify that user can login successfully', async () => { + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.login(email, process.env.PASSWORD); + // await allPages.loginPage.verifySuccessSignIn(); + // await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); + // }) + + await test.step('Navigate to All Products and add view details of a random product', async () => { + await allPages.homePage.clickAllProductsNav(); + await allPages.allProductsPage.assertAllProductsTitle(); + productName = await allPages.allProductsPage.getNthProductName(1); + await allPages.allProductsPage.clickNthProduct(1); + await allPages.productDetailsPage.clickAddToCartButton(); + }); + + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'order-flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); + + // await test.step('Add product to cart, add new address and checkout', async () => { + // await allPages.productDetailsPage.clickCartIcon(); + // await allPages.cartPage.assertYourCartTitle(); + // await expect(allPages.cartPage.getCartItemName()).toContainText(productName, { timeout: 10000 }); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.fillShippingAddress( + // firstName, email, 'New York', 'New York', '123 Main St', '10001', 'United States' + // ); + // await allPages.checkoutPage.clickSaveAddressButton(); + // await allPages.checkoutPage.assertAddressAddedToast(); + // }) + + // await test.step('Complete order and verify in my orders', async () => { + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await allPages.inventoryPage.clickOnContinueShopping(); + + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.orderPage.clickOnMyOrdersTab(); + // await allPages.orderPage.clickCancelOrderButton(); + // await allPages.orderPage.confirmCancellation(); + // }); }); - } -); - -test.only( - 'Verify that user can update cart quantity and verify total price', - { - tag: '@chromium', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Cart' }, - { type: 'testdino:link', description: 'https://jira.example.com/CART-001' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Update cart quantity and total price on Chromium' } - ] - }, - async () => { + }); +}); + +test('Verify that a new user can complete the journey from registration to multiple order placements', { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Order' }, + { type: 'testdino:link', description: 'https://jira.example.com/ORDER-003' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Registration to multiple order placement on Firefox' } + ] +}, async () => { const start = Date.now(); - await login(); - // await allPages.homePage.clickOnShopNowButton(); - // await allPages.allProductsPage.clickNthProduct(1); + const email = `test+${Date.now()}@test.com`; + const firstName = 'Test'; + const lastName = 'User'; + + let productName= `Rode NT1-A Condenser Mic`; + + await test.step('Navigate to All Products and add view details of a random product', async () => { + await allPages.homePage.clickOnShopNowButton(); + await allPages.allProductsPage.assertAllProductsTitle(); + await allPages.allProductsPage.clickNthProduct(1); + await allPages.productDetailsPage.clickOnReviewsTab(); + await allPages.productDetailsPage.assertReviewsTab(); + await allPages.productDetailsPage.clickOnAdditionalInfoTab(); + await allPages.productDetailsPage.assertAdditionalInfoTab(); + }) + + await test.step('Add product to cart, change quantity, add new address and checkout', async () => { // await allPages.productDetailsPage.clickAddToCartButton(); - // await allPages.cartPage.clickOnCartIcon(); + // await allPages.productDetailsPage.clickCartIcon(); // await allPages.cartPage.clickIncreaseQuantityButton(); - // await allPages.cartPage.verifyTotalPriceUpdated(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } -); - -test.only( - 'Verify that user can view order history and order detail (Order page)', - { - tag: '@firefox', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Order' }, - { type: 'testdino:link', description: 'https://jira.example.com/ORDER-003' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Order history and order detail (Order page) on Firefox' } - ] - }, - async () => { - const start = Date.now(); - await login(); - // await allPages.loginPage.clickOnUserProfileIcon(); - // await allPages.orderPage.clickOnMyOrdersTab(); - // await allPages.orderPage.verifyOrdersListVisible(); - // await allPages.orderPage.clickOnFirstOrder(); - // await allPages.orderDetailsPage.verifyOrderDetailsDisplayed(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } -); - -test.only( - 'Verify that user can update cart quantity and verify total price (Pricing)', - { - tag: '@chromium', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Cart' }, - { type: 'testdino:link', description: 'https://jira.example.com/CART-002' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Cart quantity and total price (Pricing) on Chromium' } - ] - }, - async () => { - const start = Date.now(); - await login(); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCashOnDeliverySelected(); + // await allPages.checkoutPage.fillShippingAddress(process.env.SFIRST_NAME, email, process.env.SCITY, process.env.SSTATE, process.env.SSTREET_ADD, process.env.SZIP_CODE, process.env.SCOUNTRY); + // await allPages.checkoutPage.clickSaveAddressButton(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + // await allPages.checkoutPage.verifyOrderConfirmedTitle(); + // await allPages.checkoutPage.clickOnContinueShoppingButton(); + }) + + await test.step('Add another product to cart, select existing address and checkout', async () => { // await allPages.homePage.clickOnShopNowButton(); + // await allPages.allProductsPage.assertAllProductsTitle(); // await allPages.allProductsPage.clickNthProduct(1); // await allPages.productDetailsPage.clickAddToCartButton(); - // await allPages.cartPage.clickOnCartIcon(); - // await allPages.cartPage.clickIncreaseQuantityButton(); - // await allPages.cartPage.verifyTotalPriceUpdated(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } -); - -test.only( - 'Verify that user can view order history and order details properly (Order details)', - { - tag: '@firefox', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Order' }, - { type: 'testdino:link', description: 'https://jira.example.com/ORDER-004' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Order history and details (Order details) on Firefox' } - ] - }, - async () => { + // await allPages.productDetailsPage.clickCartIcon(); + // await allPages.cartPage.clickOnCheckoutButton(); + // await allPages.checkoutPage.verifyCheckoutTitle(); + // await allPages.checkoutPage.selectCashOnDelivery(); + // await allPages.checkoutPage.verifyCashOnDeliverySelected(); + // await allPages.checkoutPage.clickOnPlaceOrder(); + // await allPages.checkoutPage.verifyOrderPlacedSuccessfully(); + }); + + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); +}); + +test('Verify that a new user can sign up, log in, and navigate to the home page successfully', { + tag: '@ios', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Registration' }, + { type: 'testdino:link', description: 'https://jira.example.com/REG-002' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Sign up, login and navigate home on iOS' } + ] +}, async () => { const start = Date.now(); - await login(); - // await allPages.loginPage.clickOnUserProfileIcon(); - // await allPages.orderPage.clickOnMyOrdersTab(); - // await allPages.orderPage.verifyOrdersListVisible(); - // await allPages.orderPage.clickOnFirstOrder(); - // await allPages.orderDetailsPage.verifyOrderDetailsDisplayed(); - await expect(true).toBeTruthy(); - const flowTime = Date.now() - start; - test.info().annotations.push({ - type: 'testdino:metric', - description: JSON.stringify({ - name: 'flow-time', - value: flowTime, - unit: 'ms', - threshold: 5000, - }), - }); - } -); - -test( - 'Verify that users can update cart quantity and verify total price (Single order)', - { - tag: '@chromium', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Cart' }, - { type: 'testdino:link', description: 'https://jira.example.com/CART-003' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Cart quantity (Single order) on Chromium' } - ] - }, - async () => { + const email = `test+${Date.now()}@test.com`; + const firstName = 'Test'; + const lastName = 'User'; + + await test.step('Verify that user can register successfully', async () => { + // await allPages.loginPage.clickOnUserProfileIcon(); + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.clickOnSignupLink(); + // await allPages.signupPage.assertSignupPage(); + // await allPages.signupPage.signup(firstName, lastName, email, process.env.PASSWORD); + // await allPages.signupPage.verifySuccessSignUp(); + }) + + // await test.step('Verify that user can login successfully', async () => { + // await allPages.loginPage.validateSignInPage(); + // await allPages.loginPage.login(email, process.env.PASSWORD); + // await allPages.loginPage.verifySuccessSignIn(); + // await expect(allPages.homePage.getHomeNav()).toBeVisible({ timeout: 30000 }); + // }) + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); +}) + +test('Verify that user can fill and submit the Contact Us form successfully', { + tag: '@chromium', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Contact' }, + { type: 'testdino:link', description: 'https://jira.example.com/CONTACT-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Contact Us form submission on Chromium' } + ] +}, async () => { const start = Date.now(); await login(); - // await allPages.homePage.clickOnShopNowButton(); - // await allPages.allProductsPage.clickNthProduct(1); - // await allPages.productDetailsPage.clickAddToCartButton(); - // await allPages.cartPage.clickOnCartIcon(); - // await allPages.cartPage.clickIncreaseQuantityButton(); - // await allPages.cartPage.verifyTotalPriceUpdated(); - await expect(true).toBeTruthy(); + await allPages.homePage.clickOnContactUsLink(); + await allPages.contactUsPage.assertContactUsTitle(); + await allPages.contactUsPage.fillContactUsForm(); + await allPages.contactUsPage.verifySuccessContactUsFormSubmission(); const flowTime = Date.now() - start; test.info().annotations.push({ type: 'testdino:metric', @@ -661,31 +661,109 @@ test( threshold: 5000, }), }); - } -); - -test( - 'Verify that users can view order history and order details properly (Order history)', - { - tag: '@firefox', - annotation: [ - { type: 'testdino:priority', description: 'p1' }, - { type: 'testdino:feature', description: 'Order' }, - { type: 'testdino:link', description: 'https://jira.example.com/ORDER-005' }, - { type: 'testdino:owner', description: 'qa-team' }, - { type: 'testdino:notify-slack', description: '#e2e-alerts' }, - { type: 'testdino:context', description: 'Order history on Firefox' } - ] - }, - async () => { +}); + +test('Verify that user can submit a product review', { + tag: '@firefox', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Review' }, + { type: 'testdino:link', description: 'https://jira.example.com/REVIEW-002' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Submit product review on Firefox' } + ] +}, async () => { + const start = Date.now(); + await test.step('Login as existing user and navigate to a product', async () => { + // await login(); + }) + + await test.step('Navigate to all product section and select a product', async () => { + await allPages.homePage.clickOnShopNowButton(); + await allPages.allProductsPage.assertAllProductsTitle(); + await allPages.allProductsPage.clickNthProduct(1); + }) + + await test.step('Submit a product review and verify submission', async () => { + await allPages.productDetailsPage.clickOnReviewsTab(); + await allPages.productDetailsPage.assertReviewsTab(); + + await allPages.productDetailsPage.clickOnWriteAReviewBtn(); + await allPages.productDetailsPage.fillReviewForm(); + await allPages.productDetailsPage.assertSubmittedReview({ + name: 'John Doe', + title: 'Great Product', + opinion: 'This product exceeded my expectations. Highly recommend!' + }); + }); + + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); +}); + +test('Verify that user can update personal information in profile', { + tag: '@webkit', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Profile' }, + { type: 'testdino:link', description: 'https://jira.example.com/PROFILE-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Update personal information on WebKit' } + ] +}, async () => { + const start = Date.now(); + await allPages.userPage.clickOnUserProfileIcon(); +// await allPages.userPage.updatePersonalInfo(); +// await allPages.userPage.verifyPersonalInfoUpdated(); + const flowTime = Date.now() - start; + test.info().annotations.push({ + type: 'testdino:metric', + description: JSON.stringify({ + name: 'flow-time', + value: flowTime, + unit: 'ms', + threshold: 5000, + }), + }); +}); + +test('Verify that user can delete a selected product from cart', { + tag: '@android', + annotation: [ + { type: 'testdino:priority', description: 'p1' }, + { type: 'testdino:feature', description: 'Cart' }, + { type: 'testdino:link', description: 'https://jira.example.com/CART-001' }, + { type: 'testdino:owner', description: 'qa-team' }, + { type: 'testdino:notify-slack', description: '#e2e-alerts' }, + { type: 'testdino:context', description: 'Delete selected product from cart on Android' } + ] +}, async () => { const start = Date.now(); + const productName = 'GoPro HERO10 Black'; await login(); - // await allPages.loginPage.clickOnUserProfileIcon(); - // await allPages.orderPage.clickOnMyOrdersTab(); - // await allPages.orderPage.verifyOrdersListVisible(); - // await allPages.orderPage.clickOnFirstOrder(); - // await allPages.orderDetailsPage.verifyOrderDetailsDisplayed(); - await expect(true).toBeTruthy(); + await allPages.inventoryPage.clickOnShopNowButton(); + await allPages.inventoryPage.clickOnAllProductsLink(); + await allPages.inventoryPage.searchProduct(productName); + await allPages.inventoryPage.verifyProductTitleVisible(productName); + await allPages.inventoryPage.clickOnAddToCartIcon(); + + await allPages.cartPage.clickOnCartIcon(); + await allPages.cartPage.verifyCartItemVisible(productName); + await allPages.cartPage.clickOnDeleteProductIcon(); + await allPages.cartPage.verifyCartItemDeleted(productName); + await allPages.cartPage.verifyEmptyCartMessage(); + await allPages.cartPage.clickOnStartShoppingButton(); + await allPages.allProductsPage.assertAllProductsTitle(); const flowTime = Date.now() - start; test.info().annotations.push({ type: 'testdino:metric', @@ -696,5 +774,4 @@ test( threshold: 5000, }), }); - } -); +}); From 4e574acd2ee59075531b01e6e2a1003694d3c729 Mon Sep 17 00:00:00 2001 From: Kriti Verma <155474803+kriti2710@users.noreply.github.com> Date: Sat, 7 Mar 2026 20:59:00 +0530 Subject: [PATCH 19/25] Refactor Playwright test workflow configuration Updated Playwright test workflow to use Node.js 20.x and adjusted shard settings. Added merging of reports and improved environment variable handling. --- .github/workflows/test.yml | 206 +++++++++++-------------------------- 1 file changed, 60 insertions(+), 146 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 70ea782..506ac2f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,155 +1,31 @@ -# # .github/workflows/playwright-daily.yml -# # Runs Playwright test shards every day at **11 : 42 AM IST** (06 : 12 UTC) -# # plus anytime you trigger it manually from the Actions tab. - -# name: Run Playwright tests - -# on: -# push: # runs on every push -# pull_request: # runs on new PRs or PR updates -# schedule: -# - cron: '30 3 * * 1-5' -# workflow_dispatch: - -# jobs: -# run-tests: -# name: Run shard ${{ matrix.shardIndex }}/5 -# runs-on: ubuntu-latest - -# strategy: -# fail-fast: false -# matrix: -# shardIndex: [1,2,3,4,5] -# shardTotal: [5] - -# steps: -# - uses: actions/checkout@v4 - -# - name: Setup Node.js 18.x -# uses: actions/setup-node@v3 -# with: -# node-version: '18' - -# - name: Create .env file -# run: | -# echo "USERNAME=${{ secrets.USERNAME }}" >> .env -# echo "PASSWORD=${{ secrets.PASSWORD }}" >> .env -# echo "NEW_PASSWORD=${{ secrets.NEW_PASSWORD }}" >> .env -# echo "FIRST_NAME=${{ secrets.FIRST_NAME }}" >> .env -# echo "STREET_NAME=${{ secrets.STREET_NAME }}" >> .env -# echo "CITY=${{ secrets.CITY }}" >> .env -# echo "STATE=${{ secrets.STATE }}" >> .env -# echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env -# echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env - -# - name: Cache npm dependencies -# uses: actions/cache@v3 -# with: -# path: ~/.npm -# key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} -# restore-keys: | -# ${{ runner.os }}-node- - -# - name: Install deps + browsers -# run: | -# npm ci -# npx playwright install --with-deps chromium firefox webkit - -# - name: List Playwright projects (debug) -# run: npx playwright list --projects | cat - -# - name: Run shard ${{ matrix.shardIndex }} -# run: npx playwright test --grep="@chromium|@firefox|@webkit|@android|@ios" --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - -# - name: Upload blob report -# if: ${{ !cancelled() }} -# uses: actions/upload-artifact@v4 -# with: -# name: blob-report-${{ matrix.shardIndex }} -# path: ./blob-report -# retention-days: 1 - -# merge-reports: -# name: Merge Reports -# needs: run-tests -# if: always() # run even if some shards fail -# runs-on: ubuntu-latest - -# steps: -# - uses: actions/checkout@v4 - -# - name: Setup Node.js 18.x -# uses: actions/setup-node@v3 -# with: -# node-version: '18' - -# - name: Cache npm dependencies -# uses: actions/cache@v3 -# with: -# path: ~/.npm -# key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} -# restore-keys: | -# ${{ runner.os }}-node- - -# - name: Install deps + browsers -# run: | -# npm ci -# npx playwright install --with-deps - -# - name: Download all blob reports -# uses: actions/download-artifact@v4 -# with: -# path: ./all-blob-reports -# pattern: blob-report-* -# merge-multiple: true - -# - name: Merge HTML & JSON reports -# run: npx playwright merge-reports --config=playwright.config.js ./all-blob-reports - -# - name: Upload combined report -# uses: actions/upload-artifact@v4 -# with: -# name: Playwright Test Report -# path: ./playwright-report -# retention-days: 14 - -# - name: Send TestDino report -# run: | -# npx --yes tdpw ./playwright-report \ -# --token="${{ secrets.TESTDINO_TOKEN }}" \ -# --upload-html \ -# --verbose - - name: Run Playwright tests on: push: pull_request: + schedule: + - cron: '30 3 * * *' # 9:00 AM IST everyday # 11:00 AM IST workflow_dispatch: jobs: run-tests: - name: Run shard ${{ matrix.shardIndex }}/5 + name: Run Playwright tests ${{ matrix.shardIndex }}/3 runs-on: ubuntu-latest strategy: fail-fast: false matrix: - shardIndex: [1, 2, 3, 4, 5] - shardTotal: [5] + shardIndex: [1, 2, 3] + shardTotal: [3] steps: - - name: Checkout repo - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - # ✅ Required Node version - name: Setup Node.js 20.x - uses: actions/setup-node@v4 + uses: actions/setup-node@v3 with: - node-version: '20' + node-version: "20" - # ✅ Required env variables for tests - name: Create .env file run: | echo "USERNAME=${{ secrets.USERNAME }}" >> .env @@ -162,7 +38,6 @@ jobs: echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env - # ✅ Cache npm dependencies - name: Cache npm dependencies uses: actions/cache@v3 with: @@ -171,27 +46,66 @@ jobs: restore-keys: | ${{ runner.os }}-node- - # ✅ Install dependencies + TestDino (.tgz) + Playwright browsers - - name: Install dependencies & browsers + - name: Install dependencies run: | - npm install - npm install --save-dev @testdino/playwright@latest - npx playwright install --with-deps chromium firefox webkit + npm ci + npx playwright install --with-deps - # ✅ Run Playwright shard with TestDino - - name: Run Playwright shard with TestDino - env: - TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }} + - name: Run Playwright Tests run: | npx playwright test \ - --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} \ - --grep "@chromium|@firefox|@webkit|@android|@ios|@api" \ + --grep="@chromium|@firefox|@webkit" \ + --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - # ✅ Upload blob report (needed for merge) - name: Upload blob report if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: name: blob-report-${{ matrix.shardIndex }} path: ./blob-report - retention-days: 1 \ No newline at end of file + retention-days: 1 + + merge-reports: + name: Merge Reports + needs: run-tests + if: always() + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js 20.x + uses: actions/setup-node@v3 + with: + node-version: "20" + + - name: Install dependencies + run: | + npm ci + npx playwright install --with-deps + + - name: Download all blob reports + uses: actions/download-artifact@v4 + with: + path: ./all-blob-reports + pattern: blob-report-* + merge-multiple: true + + - name: Merge HTML & JSON reports + run: | + npx playwright merge-reports \ + --config=playwright.config.js \ + ./all-blob-reports + + - name: Upload combined Playwright report + uses: actions/upload-artifact@v4 + with: + name: Playwright Test Report + path: ./playwright-report + retention-days: 14 + + - name: Upload report to TestDino + env: + TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }} + run: | + npx tdpw upload ./playwright-report --token="$TESTDINO_TOKEN" From f763542fe63273822abcdd53cd3d4ad9b638abb4 Mon Sep 17 00:00:00 2001 From: Kriti Verma <155474803+kriti2710@users.noreply.github.com> Date: Sat, 7 Mar 2026 21:07:15 +0530 Subject: [PATCH 20/25] Refactor Playwright configuration settings Updated configuration settings for Playwright tests, including retries, workers, timeout, and reporter options. --- playwright.config.js | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/playwright.config.js b/playwright.config.js index 8af6021..88ef773 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -1,30 +1,33 @@ // @ts-check import { defineConfig, devices } from '@playwright/test'; +import * as dotenv from 'dotenv'; + +dotenv.config({ quiet: true }); const isCI = !!process.env.CI; export default defineConfig({ testDir: './tests', + fullyParallel: true, forbidOnly: isCI, - retries: isCI ? 1 : 1, - workers: isCI ? 5 : 5, - timeout: 60 * 1000, - reporter: [ - ['html', { - outputFolder: 'playwright-report', - open: 'never' - }], - ['blob', { outputDir: 'blob-report' }], - ['json', { outputFile: './playwright-report/report.json' }], - ['@testdino/playwright', { token: process.env.TESTDINO_TOKEN }], - ], + retries: isCI ? 0 : 0, + workers: isCI ? 1 : 1, + + timeout: 30 * 1000, + +reporter: [ + ['html', { outputFolder: 'playwright-report', open: 'never' }], + ['blob', { outputDir: 'blob-report' }], // Blob reporter for merging + ['json', { outputFile: './playwright-report/report.json' }], +], use: { - baseURL: 'https://storedemo.testdino.com/', + baseURL: 'https://storedemo.testdino.com', headless: true, - trace: 'on', + + trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'retain-on-failure', }, From d8c9add567663e58041e5dabaa1d68f608af9e91 Mon Sep 17 00:00:00 2001 From: Kriti Verma <155474803+kriti2710@users.noreply.github.com> Date: Sat, 7 Mar 2026 21:08:14 +0530 Subject: [PATCH 21/25] Expand Playwright test grep filters to include API and mobile --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 506ac2f..40832b9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,7 +54,7 @@ jobs: - name: Run Playwright Tests run: | npx playwright test \ - --grep="@chromium|@firefox|@webkit" \ + --grep="@chromium|@firefox|@webkit|@api|@andriod|@ios" \ --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - name: Upload blob report From cca433437e2c0a243729ec9ed793d5f4813879e8 Mon Sep 17 00:00:00 2001 From: Kriti Verma <155474803+kriti2710@users.noreply.github.com> Date: Sat, 7 Mar 2026 21:09:11 +0530 Subject: [PATCH 22/25] Increase shard count to 5 in test workflow --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 40832b9..b7d40fa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,8 +15,8 @@ jobs: strategy: fail-fast: false matrix: - shardIndex: [1, 2, 3] - shardTotal: [3] + shardIndex: [1, 2, 3, 4, 5] + shardTotal: [5] steps: - uses: actions/checkout@v4 From 28f10402e21dbfe96cbd62e5cacbb5dc0733957f Mon Sep 17 00:00:00 2001 From: Kriti Verma <155474803+kriti2710@users.noreply.github.com> Date: Sat, 7 Mar 2026 21:18:54 +0530 Subject: [PATCH 23/25] Update Playwright config for retries and debugging --- playwright.config.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/playwright.config.js b/playwright.config.js index 88ef773..deac8db 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -12,57 +12,58 @@ export default defineConfig({ fullyParallel: true, forbidOnly: isCI, - retries: isCI ? 0 : 0, + // ✅ Retries set to 2 + retries: 2, + workers: isCI ? 1 : 1, timeout: 30 * 1000, -reporter: [ - ['html', { outputFolder: 'playwright-report', open: 'never' }], - ['blob', { outputDir: 'blob-report' }], // Blob reporter for merging - ['json', { outputFile: './playwright-report/report.json' }], -], + reporter: [ + ['html', { outputFolder: 'playwright-report', open: 'never' }], + ['blob', { outputDir: 'blob-report' }], // Blob reporter for merging + ['json', { outputFile: './playwright-report/report.json' }], + ], use: { baseURL: 'https://storedemo.testdino.com', headless: true, - trace: 'on-first-retry', - screenshot: 'only-on-failure', - video: 'retain-on-failure', + // ✅ Always capture debugging artifacts + trace: 'on', + screenshot: 'on', + video: 'on', }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, - grep: /@chromium/, // only run tests tagged @chromium + grep: /@chromium/, }, { name: 'firefox', use: { ...devices['Desktop Firefox'] }, - grep: /@firefox/, // only run tests tagged @firefox + grep: /@firefox/, }, { name: 'webkit', use: { ...devices['Desktop Safari'] }, - grep: /@webkit/, // only run tests tagged @webkit + grep: /@webkit/, }, { name: 'android', use: { ...devices['Pixel 5'] }, - grep: /@android/, // only run tests tagged @android + grep: /@android/, }, { name: 'ios', use: { ...devices['iPhone 12'] }, - grep: /@ios/, // only run tests tagged @ios + grep: /@ios/, }, - { name: 'api', - use: { ...devices['API'] }, - grep: /@api/, // only run tests tagged @api + grep: /@api/, }, ], }); From 16086cb11e553ef21b6e52b242e7ab044fe7f0a8 Mon Sep 17 00:00:00 2001 From: Kriti Verma <155474803+kriti2710@users.noreply.github.com> Date: Sat, 7 Mar 2026 21:25:56 +0530 Subject: [PATCH 24/25] Update Playwright test shard count to 5 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b7d40fa..50e228c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,7 +9,7 @@ on: jobs: run-tests: - name: Run Playwright tests ${{ matrix.shardIndex }}/3 + name: Run Playwright tests ${{ matrix.shardIndex }}/5 runs-on: ubuntu-latest strategy: From 33a1042bd9cb0fb3721ed6fbaf17acc26b88ff95 Mon Sep 17 00:00:00 2001 From: Kriti Verma <155474803+kriti2710@users.noreply.github.com> Date: Sat, 7 Mar 2026 21:31:01 +0530 Subject: [PATCH 25/25] Enhance TestDino upload command with additional options --- .github/workflows/test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 50e228c..cb2edc9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -108,4 +108,7 @@ jobs: env: TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }} run: | - npx tdpw upload ./playwright-report --token="$TESTDINO_TOKEN" + npx tdpw upload ./playwright-report \ + --upload-traces \ + --upload-html \ + --token="$TESTDINO_TOKEN"