PracticeQAAutomation logoPracticeQAAutomation
Pw

TypeScript · @playwright/test

Pharmacy with Playwright

Search medicines by name or salt, see cheaper generic substitutes, respect per-item quantity limits, and get blocked at checkout until you upload a prescription (or book a consult) for Rx items.

App under test

💊 MediKart

URL
/apps/pharmacy
Mobile
9876543210
OTP
445566
Rx upload
PDF/JPG/PNG ≤ 5 MB
Free delivery
₹300+
Consult
₹199

Scenarios to automate

Work top to bottom — each one adds a new technique.

  1. 1

    Mobile + OTP login

    Beginner

    Passwordless sign-in: mk-login-id (mobile) → mk-login → mk-code (OTP) → mk-verify. A wrong OTP shows mk-code-error; an unknown mobile counts toward the 3-attempt lock.

  2. 2

    Min-length autocomplete

    Beginner

    med-suggestions only appears after 2 characters; match by brand or salt.

  3. 3

    Substitutes & savings

    Intermediate

    On Mox 500, saving-m3g shows “Save ₹50 (42%)”; add-substitute-* adds the generic.

  4. 4

    Quantity limits

    Intermediate

    inc-<id> disables at the medicine's max (antibiotics: 2–3); add-med-* disables when maxed.

  5. 5

    Rx gate

    Advanced

    With an Rx item, placing the order shows error-rx until rx-upload + prescription-file or rx-consult.

  6. 6

    Upload validation

    Intermediate

    A .txt or >5 MB file shows an error under prescription-file; valid files show prescription-file-name.

  7. 7

    Totals

    Intermediate

    med-delivery is ₹40 under ₹300 and FREE above; rx-consult adds ₹199 to med-total.

  8. 8

    Filters

    Beginner

    med-category-* chips and filter-all/otc/rx narrow the med-grid.

  9. 9

    Reorder

    Beginner

    reorder-<id> on the orders page refills the cart with the same lines.

Sample Playwright suite

A working starting point that finds elements every way Playwright can — by role, label, text, id, name, CSS, XPath and data-testid — so you practice them all. Pick your language, switch to data-testid only to compare, or try your own in the Locator Playground.

Language
medikart.spec.ts
import { test, expect } from '@playwright/test';

// playwright.config.ts → use: { baseURL: 'https://www.practiceqaautomation.com' }
// Locators in this suite: getByRole ×5 · getByLabel ×3 · CSS ×3 · XPath ×2 · getByTestId ×16
test('orders medicines with a prescription', async ({ page }) => {
  await page.goto('/apps/pharmacy');

  // Sign in first
  await page.getByLabel('Mobile number').fill('9876543210');
  await page.getByRole('button', { name: 'Continue' }).click();
  await page.locator('#mk-code').fill('445566');
  await page.locator('xpath=//button[normalize-space()="Verify & continue"]').click();
  await page.getByTestId('med-search').fill('amox');
  await page.getByTestId('med-option-m3').click();
  await expect(page.getByTestId('med-title')).toContainText('Mox 500');
  await expect(page.getByTestId('saving-m3g')).toContainText('Save ₹50');
  await page.getByRole('button', { name: 'Add instead' }).click();
  await expect(page.getByTestId('cart-count')).toContainText('1');
  await page.locator('xpath=//a[normalize-space()="Shop"]').click();
  await page.getByTestId('add-med-m1').click();
  await page.getByTestId('add-med-m1').click();
  await page.getByTestId('nav-cart').click();
  await expect(page.getByTestId('rx-required')).toBeVisible();
  await page.getByRole('button', { name: 'Place order' }).click();
  await expect(page.getByTestId('error-rx')).toBeVisible();
  await page.getByTestId('rx-upload').click();
  await page.getByLabel('Prescription').setInputFiles('fixtures/prescription.pdf');
  await expect(page.getByTestId('prescription-file-name')).toContainText('prescription.pdf');
  await page.locator('#delivery-slot').selectOption('Tomorrow 8–11 am');
  await page.getByLabel('Phone').fill('9876543210');
  await page.locator('#med-address').fill('12B Palm Residency, Baner, Pune');
  await expect(page.getByTestId('med-total')).toContainText('₹178');
  await page.getByRole('switch', { name: 'Refill reminder' }).click();
  await page.getByRole('button', { name: 'Place order' }).click();
  await expect(page.getByTestId('med-order-placed')).toBeVisible();
  await expect(page.getByTestId('med-order-id')).toContainText('MK-');
  await expect(page.getByTestId('refill-on')).toBeVisible();
});

Practicing another tool?