top of page

Playwright Tutorial for Beginners: Installation and Hands-On Overview

Updated: Feb 23

Playwright is a modern end-to-end test automation framework designed for reliable, cross-browser testing using a single unified API. It supports Chromium, Firefox, and WebKit, and comes with a powerful built-in test runner, automatic waiting mechanisms, parallel execution, and rich HTML reporting. In this Playwright tutorial for beginners, we will go beyond basic installation and understand how Playwright fits into a modern TypeScript-based automation workflow.

This guide walks through installing Playwright using Node.js, setting up a TypeScript project structure, and understanding how the Playwright Test Runner discovers and executes test files. You will write and run your first test, explore how fixtures like page are injected automatically, and see how assertions using expect() validate browser behavior. We will also briefly examine how Playwright manages browser contexts, test isolation, and execution artifacts such as reports and test results.

By the end of this hands-on overview, you will have a functional Playwright environment and a clear understanding of its test architecture. This technical foundation prepares you for deeper topics such as locator strategy, DOM interaction, fixtures and hooks, debugging with traces, and building scalable automation frameworks using TypeScript.


Prerequisites


Check Node + npm Installation

Open Command Prompt / Terminal and run:

node -v
npm -v

In case you do not have the setup installed, follow these steps till vscode install



  • Create your project folder and open VS Code



mkdir playwright_learn
cd playwright_learn
code .

Install Playwright


Run this inside your project folder:

npm init playwright@latest


You will see prompts like these:

Prompt A: TypeScript or JavaScript?

Choose:

  • TypeScript (best for jobs + Playwright projects)

  • or JavaScript

Prompt B: Where to put tests?

Common choice:

  • tests 

Prompt C: Add GitHub Actions workflow?

Choose:

  • Y if you want CI later (good practice)

  • n if you don’t need it now

Prompt D: Install browsers?

Choose:

  • Y (recommended)

After this, Playwright creates files + installs packages and browsers.


  • Understand Playwright Folder Structure


After installing Playwright, several folders and files are created automatically. Each one has a specific role in how Playwright works . Let's understand each one by one:




📁 node_modules/

  • Contains all libraries (dependencies) installed for your project

  • Example:

    • @playwright/test (Playwright test runner)

    • browser-related packages

  • Do not edit this folder

  • Never push it to GitHub


📁 tests/

  • This folder holds all Playwright test files

  • Playwright creates a sample test file by default, for example:

    example.spec.ts


About .spec.ts


  • spec has no special technical meaning

  • It is a naming convention

  • It indicates:“This file contains test specifications”

  • Common naming examples:

    • login.spec.ts

    • checkout.spec.ts

    • order-flow.spec.ts

    • login.test.ts also indicates test specification


📄 .gitignore

  • Tells Git which files should not be committed

  • Typical ignored items:


Keeps the repository clean and professional.


📄 package.json


This file describes your project metadata and scripts.

It includes:

  • Project name & version

  • Dependencies (@playwright/test)

  • Scripts to run tests


Example:

"scripts": {
  "test": "playwright test",
  "test:ui": "playwright test --ui"
}

📄 package-lock.json

  • Locks exact dependency versions

  • Ensures consistent installs across machines

  • Auto-generated — don’t edit manually


📄 playwright.config.ts (Main Configuration File)



When working with Playwright, one of the most important files in your project is:

playwright.config.ts

This file is the brain of your Playwright automation framework. It controls how Playwright discovers tests, launches browsers, applies timeouts, and generates reports.

Instead of repeating settings in every test file, we define them once here and Playwright applies them automatically across the project.

Starting with the Simplest Configuration

We intentionally removed the pre-populated options and built our configuration step by step to clearly understand each setting.

Our current configuration looks like this:

import { defineConfig } from '@playwright/test';export default defineConfig({  testDir: './tests',  timeout: 40 * 1000,  expect: {    timeout: 40 * 1000,  },  reporter: 'html',  use: {    browserName: 'chromium',    headless: false,  },});

Let’s understand each part.

testDir – How Playwright finds your tests

testDir: './tests',

This tells Playwright that all test files are located inside the tests folder.

Example project structure:

project root ├── tests │    ├── login.spec.ts │    ├── cart.spec.ts

When you run:

npx playwright test

Playwright automatically:

• goes to the tests folder• finds files matching .spec.ts or .test.ts• executes all test() blocks

You can also run a specific test:

npx playwright test tests/login.spec.ts

This automatic discovery is why folder structure and naming conventions are important.

timeout – Maximum time allowed for a test

timeout: 40 * 1000,

This sets the maximum test execution time to 40 seconds.

Playwright waits for:

• page loads• elements to appear• actions to complete

This is especially useful for:

• legacy applications• heavy dashboards• slow-loading components

We write 40 * 1000 because Playwright expects time in milliseconds.

expect timeout – Maximum wait time for assertions

expect: {  timeout: 40 * 1000,},

This controls how long Playwright waits for assertions.

Example:

await expect(page.locator('#orders')).toBeVisible();

Playwright will wait until the element appears or timeout occurs.

This automatic waiting makes Playwright tests reliable and less flaky.

reporter – Generating HTML reports

reporter: 'html',

This generates a detailed HTML report after test execution.

You can open it using:

npx playwright show-report

The report shows:

• passed tests• failed tests• execution time• debugging details

Reports are very useful for analyzing automation results.

browserName – Choosing the browser

browserName: 'chromium',

This tells Playwright to run tests using the Chromium browser.

Playwright supports:

• chromium• firefox• webkit

Chromium is the most commonly used browser in automation.

headless – Running browser in visible or background mode

headless: false,

This runs the browser in headed mode, meaning you can see the browser window.

This is useful for:

• learning• debugging• understanding test flow

For CI/CD or faster execution, you can set:

headless: true,

This runs the browser in background.

Why playwright.config is TypeScript and not JSON

Playwright uses TypeScript instead of JSON because TypeScript allows logic and flexibility.

JSON is limited:

• cannot use conditions• cannot use environment variables easily• cannot reuse variables• cannot write logic

With TypeScript, we can do things like:

const isCI = !!process.env.CI;export default defineConfig({  timeout: isCI ? 60000 : 40000,  use: {    headless: isCI ? true : false,  },});

This allows environment-specific configuration.

TypeScript also provides:

• autocomplete• type safety• reusable logic

This makes Playwright suitable for real-world frameworks.

What happens when you run a test

When you execute:

npx playwright test

Playwright performs these steps:

  1. Reads playwright.config.ts

  2. Finds test files in testDir

  3. Launches the configured browser

  4. Applies timeout and execution settings

  5. Runs tests

  6. Generates HTML report

If multiple test files exist, Playwright runs them in parallel for faster execution.

Tests inside a single file run sequentially.

Summary

The playwright.config.ts file is the central control point of your automation framework.

It defines:

• where tests are located• which browser to use• timeout settings• report generation• headless or headed execution

We started with a minimal configuration and gradually enhanced it to understand each option clearly.

As we continue building our framework, we will add more powerful settings like:

• baseURL• storage state• retries• custom fixtures

This step-by-step approach ensures a strong foundation for building scalable and reliable Playwright automation frameworks.

The playwright.config.ts file is the central control point of your Playwright automation framework.

Think of it as the brain of your Playwright project.

It controls how tests are located, executed, and reported.

Using this file, you can configure:

  • Test directory location

  • Browser behavior

  • Timeout settings

  • Retry logic

  • Base URL

  • Reporting format

  • Headed or headless execution

Instead of repeating these settings in every test, we define them once in this configuration file.

Minimal Playwright Config (Starting Simple)

To understand each option clearly, we start with a minimal configuration:


This configuration defines the basic execution behaviour for the entire project.


we will gradually enhance it to



testDir – Where Playwright finds tests

testDir: './tests'

This tells Playwright that all test files are located inside the tests folder.

Whenever you run:

npx playwright test

Playwright automatically discovers and executes all test files inside this folder.


timeout – Maximum time allowed for each test

timeout: 40 * 1000

This sets the test timeout to 40 seconds.

We write 40 * 1000 because Playwright expects timeout in milliseconds.

This means Playwright will wait up to 40 seconds for the test to complete before failing it.

This is useful for:

  • slow-loading pages

  • heavy applications

  • large components like web tables


expect timeout – Maximum wait time for assertions

expect: {  timeout: 40 * 1000,}

This controls how long Playwright will wait for assertions to pass.

Example:

await expect(page.locator('#orders')).toBeVisible();

Playwright will wait up to 40 seconds for the element to appear.

This automatic waiting makes tests more reliable.


reporter – Generate HTML execution report

reporter: 'html'

This tells Playwright to generate an HTML report after test execution.

You can open it using:

npx playwright show-report

The report provides:

  • pass/fail status

  • execution time

  • debugging information

This is extremely useful for analyzing test results.

browserName – Selecting the browser

browserName: 'chromium'

This tells Playwright to run tests using the Chromium browser.

Playwright supports multiple browsers:

  • chromium

  • firefox

  • webkit

Chromium is the most commonly used browser for automation.

headless – Controlling browser visibility

headless: false

This runs the browser in headed mode, meaning the browser window will open and you can see the test execution.

This is useful during learning and debugging.

For CI/CD or faster execution, you can set:

headless: true

to run the browser in the background.


How Playwright uses this configuration

When you run:

npx playwright test

Playwright:

  1. Reads playwright.config.ts

  2. Finds test files inside testDir

  3. Launches Chromium browser

  4. Applies timeout and expect settings

  5. Runs tests

  6. Generates HTML report


Why Playwright config is TypeScript and not JSON

Playwright uses TypeScript instead of JSON for configuration because TypeScript allows logic and flexibility.


Limitations of JSON

JSON is static and limited:

  • Cannot contain logic

  • Cannot use conditions

  • Cannot use environment variables easily

  • Cannot reuse variables


Advantages of TypeScript configuration


Because Playwright config is TypeScript, you can write dynamic logic.

Example: Different timeout for CI vs local execution

timeout: process.env.CI ? 60000 : 30000

Example: Running headless only in CI

use: {  headless: process.env.CI ? true : false,}

Example: Reusing variables

const isCI = !!process.env.CI;

Benefits include:

  • flexibility

  • environment-specific configuration

  • code reuse

  • autocomplete and type safety

This makes Playwright config powerful and production-ready.




▶ Run Playwright Tests

Now that Playwright is installed and the folder structure is ready, let’s understand how to execute tests.


🖥 Run Tests Using Command Line (CLI)


The basic command to run Playwright tests is:

npx playwright test

What happens by default?

  • Playwright reads configuration from playwright.config.ts

  • By default, it runs tests in 3 browsers:

    • Chromium

    • Firefox

    • WebKit

  • The sample example.spec.ts file contains 2 test cases, so you’ll see multiple executions (2 tests × 3 browsers).



📊 View HTML Report

After execution, you can open the test report using:

npx playwright show-report

This opens a beautiful HTML report in the browser showing:

  • Passed / Failed tests

  • Execution time

  • Screenshots (if configured)

  • Detailed logs


🌐 Run Tests in a Specific Browser

To run tests only in a specific browser, use the --project option:

npx playwright test --project=chromium

By default, tests run headlessly (browser runs in the background without UI).



👀 Run Tests in Headed Mode (See Browser)


To actually see the browser execution:

npx playwright test --project=chromium --headed

Although the browser opens, execution is usually very fast.



📂 Run a Specific Test File


By default, all files inside the tests/ folder are executed.

To run a particular file:

npx playwright test example.spec.ts --project=chromium --headed

🔎 Run a Specific Test by Name

If you want to run only one specific test case:

npx playwright test -g "has title" --project=chromium --headed

The -g option matches the test name.


⏭ Skip a Test

To skip a test:

test.skip('test name', async ({ page }) => {
  // skipped test
});

🎯 Run Only One Test (Debugging Mode)

To execute only a particular test while debugging:

test.only('test name', async ({ page }) => {
  // only this test runs
});

Note:

After running your Playwright tests using:

npx playwright test

Playwright automatically generates two folders:

  • test-results/ → stores raw test execution data such as screenshots, videos,

  • and trace files.

  • playwright-report/ → contains the HTML report (index.html) that shows test results in a browser.

You do not need to create these folders manually. They are automatically created every time tests are executed.

If deleted, they will be recreated during the next test run.

📌 These folders are generated artifacts and are usually added to .gitignore in real projects.


🧪 Running Tests Using VS Code UI

Command line is powerful — but Playwright also integrates beautifully with VS Code.


✅ Install Playwright VS Code Extension

  1. Open VS Code

  2. Go to Extensions

  3. Search for: Playwright Test for VS Code

  4. Install it


🧭 Use Test Explorer

After installation, you’ll see a Testing icon in the left sidebar.

Clicking it opens the Test Explorer view, where you can:


  • See all available tests

  • Run all tests

  • Run selected tests

  • Debug tests



⚙ Browser & Execution Settings in Explorer

At the bottom panel in Test Explorer, you’ll find options for:

  • Browser selection

  • Headless / Headed mode

  • Debug mode


🔄 Difference Between CLI and VS Code Execution


When running from CLI:

  • The browser closes immediately after execution

When running from VS Code UI:

  • The browser remains open after execution

  • Allows manual exploration of the application

This is very useful during debugging.

Even in headless mode, the Explorer shows:

  • Live execution status

  • Test runtime updates


🧠 Run Tests in Playwright UI Mode

Another powerful option is running:

npx playwright test --ui

This opens the Playwright Test Runner window.


It provides:

  • Visual test timeline

  • Before & After action states

  • Step-by-step execution

  • DOM snapshots

  • Debug-friendly interface

This mode is extremely helpful for:

  • Beginners

  • Debugging failures

  • Understanding test flow


You now know how to:

  • Run all tests

  • Run specific files

  • Run specific tests

  • Run in specific browsers

  • Run in headed mode

  • Skip or isolate tests

  • Use VS Code Test Explorer

  • Use Playwright UI mode


Trace View and Debug


We already saw how UI Mode (--ui) provides a rich, step-by-step view of test execution, including action states (before/after each step). Now let’s learn how to get the same level of debugging detail even when running tests from the command line — especially useful for CI/CD pipelines.


  • Enable Trace in CLI Mode


You can enable tracing while running tests using:

npx playwright test --project=chromium --trace on

What happens after you run this?

  • Playwright captures a detailed trace for the test run.

  • When you open the HTML report, you’ll notice a new section called Traces.

To open the report:

npx playwright show-report

✅ In the report:

  • You’ll see a Traces tab/section

  • Clicking a trace opens a viewer that looks very similar to what we saw earlier in Playwright UI Test Runner

You’ll be able to inspect:

  • Each step executed

  • Before/after state

  • DOM snapshots

  • Network activity

  • Console logs (if enabled)


Why Trace is Powerful in CI/CD

In local execution, you can easily rerun tests. But in CI pipelines, when a test fails, you usually don’t have:

  • the browser screen

  • Your local machine access

  • the ability to “watch it again” easily


✅ With trace enabled, you can:

  • Download the report artifact from CI

  • open it locally

  • Replay exactly what happened step-by-step


This makes debugging CI failures much faster.


  • Trace Settings in playwright.config.ts


Instead of passing-- trace every time, you can control trace behaviour from configuration.

Example:

use: {
  trace: 'on-first-retry',
}

What does on-first-retry mean?

It means:

  • Trace is not collected on the first run

  • If the test fails, and Playwright retries it,

  • Trace is collected only on the first retry


✅ Why is this a good default?Because traces can be heavy in size. This setting saves storage and still captures useful debugging info when failures happen.


🔁 Change Trace to “Always On”

If you want tracing for every run:

use: {
  trace: 'on',
}

What does trace: 'on' mean?


  • Playwright collects traces for every test run

  • Useful during:

    • learning

    • debugging locally

    • short projects



Debug Using Playwright Inspector


Another powerful debugging option is running tests in debug mode, which opens the Playwright Inspector.

Run:

npx playwright test --project=chromium --debug

What opens?

  • The browser (usually in headed mode)

  • Playwright Inspector window

This is extremely helpful when you want to pause execution and inspect step-by-step.


Inspector Controls


Inside Playwright Inspector, you get debugging controls like:

  • Resume (continue execution)

  • Pause

  • Step over (execute one action at a time)

  • Detailed action logs for each step

This gives you a very clear understanding of:

  • What Playwright is doing

  • What locator is being used

  • What action is happening

  • where exactly it fails


Create your First Playwright Test


Let's write and run a very simple Playwright test on a real-world style demo e-commerce website.


Test App (Demo Store):http://qa-cart.com


We will keep the test intentionally simple and focus only on:

  • opening the site

  • validating the page title

  • validating the header text


We will cover Playwright core concepts (fixtures, async/await, assertions, locators, etc.) in a separate section.


Prerequisite: Install SelectorHub (For Finding Locators)


To identify CSS selectors easily, install SelectorHub in your browser.

How to install

  1. Open Chrome (or Edge)

  2. Go to Chrome Web Store

  3. Search: SelectorHub

  4. Click Add to Chrome

SelectorHub helps you quickly inspect elements and copy selectors like:

  • CSS selectors

  • XPath (we will use CSS in this demo)


  • Create a New Test File

Inside the tests folder, create a new file:

tests/first-test.spec.ts
  • Add the Test Code

Copy and paste the code below:

/*
Writing first test
Test App
*************
http://qa-cart.com
**********************
Test Steps
**********************
1. Go to the home page
2. Assert if the title is correct
3. Assert header text
**********************
*/

import { test, expect } from '@playwright/test';

test("Load Home Page", async ({ page }) => {

  // 1. Go to the home page
  await page.goto("http://qa-cart.com");

  // 2. Assert if the title is correct
  await expect(page).toHaveTitle("QA TEST AUTOMATION DEMO STORE BY ANURADHA AGARWAL");

  // 3. Assert header text
  await expect(page.locator(".site-title:visible"))
    .toHaveText("QA Demo Store - Anuradha Agarwal");

});
  • Why We Used: visible in the Locator

On this demo store, some elements exist twice:

  • one version for desktop

  • one version for mobile

Sometimes one is visible and the other is hidden, but both match the same selector.This can cause Playwright to fail with errors like “strict mode violation” or “multiple elements found”.

To avoid that, we deliberately used:

.page.locator(".site-title:visible")

This tells Playwright:

“Only pick the element that is currently visible on the page.”
  • Run the Test

Open the terminal in your project root and run:

npx playwright test project=chromium --headed
  • View the HTML Report

After the run completes, open the report:

npx playwright show-report

This will open Playwright’s HTML report in your default browser so you can view:

  • pass/fail status

  • test steps

  • error details (if any)


Important Notes for Your First Playwright Test

Before moving ahead, there are a few important things every beginner must understand. These small details can save hours of confusion.

1️⃣ Test File Name and Folder Structure Matter

Playwright automatically discovers test files based on:

  • The tests/ folder

  • File naming pattern like:

    • *.spec.ts

    • *.test.ts

✅ Correct Example

tests/
  first-test.spec.ts

If you create the file outside the tests folder or do not use .spec.ts or .test.ts, Playwright may not detect it.

❌ Common Mistake

src/first-test.ts   ← Playwright will not run this automatically

📌 Always keep test files inside the tests folder unless configured differently in playwright.config.ts.

2️⃣ Test Case Name Is Important

test("Load Home Page", async ({ page }) => {

The string "Load Home Page":

  • Appears in reports

  • Helps identify failures

  • Should clearly describe what the test verifie



3️⃣ The await Keyword Is Critical

Most Playwright operations are asynchronous.

Without await, the test may:

  • Move to the next step too early

  • Fail unexpectedly

  • Become unstable

Example (Correct)

await page.goto("http://qa-cart.com");
await expect(page).toHaveTitle("QA TEST AUTOMATION DEMO STORE BY ANURADHA AGARWAL");

❌ Without await

page.goto("http://qa-cart.com");   // ❌ Missing await

This may cause:

  • Assertion running before page loads

  • Random test failures

📌 Beginner Rule:

If Playwright is doing something (clicking, navigating, asserting), it usually needs await.

Troubleshooting Your First Test

Here are common issues beginners face and how to fix them.

❗ Test Not Running

Possible Reasons:

  • File is not inside tests/

  • File name is not .spec.ts or .test.ts

  • Syntax error in file

Run:

npx playwright test

If no tests are found, check folder and file naming.

❗ "Multiple elements found" Error

This happens when:

  • The page has duplicate elements (desktop + mobile versions)

  • The locator matches more than one element

Fix:

Use :visible

await expect(page.locator(".site-title:visible"))
  .toHaveText("QA Demo Store - Anuradha Agarwal");

❗ Title Assertion Fails

Check:

  • Exact spelling

  • Capitalization

  • Extra spaces

Title assertions are case-sensitive.

❗ Forgot await

If your test:

  • Fails randomly

  • Skips steps

  • Executes too fast

Check if await is missing.

❗ Website Not Loading

  • Open the URL manually in browser

  • Confirm internet connection

  • Confirm URL is correct

Beginner Checklist Before Running a Test

✔ File inside tests/

✔ File ends with .spec.ts

✔ Proper test name

✔ All Playwright actions use await

✔ Correct locators

✔ Correct URL


What’s Next?

Now that you have successfully written and executed your first Playwright test, we are ready to go deeper.

In the next section, we will explain Playwright core concepts in a beginner-friendly way, including:

  • Playwright Test Runner

  • The test() function

  • locator object

  • Fixtures (like page,browsercontext)

  • The expect() assertion library

  • The async / await model



Understanding Core Playwright Concepts

Let’s revisit our first test:

import { test, expect } from '@playwright/test';

test("Load Home Page", async ({ page }) => {

  await page.goto("http://qa-cart.com");

  await expect(page).toHaveTitle(
    "QA TEST AUTOMATION DEMO STORE BY ANURADHA AGARWAL"
  );

  await expect(page.locator(".site-title:visible"))
    .toHaveText("QA Demo Store - Anuradha Agarwal");

});

This small test already uses all the important Playwright core concepts. Let’s break them down clearly.


1️⃣ Playwright Test Runner

When you run:

npx playwright test

You are starting the Playwright Test Runner.

The Test Runner is responsible for:

  • Finding test files inside the tests/ folder

  • Running each test() function

  • Managing browser instances

  • Handling parallel execution

  • Generating reports

  • Managing retries

You don’t need Mocha, Jest, or any external framework. Playwright has its own built-in test runner.

📌 In our example, when we ran the command, the runner found first-test.spec.ts and executed the "Load Home Page" test automatically.


2️⃣ The test() Function

test("Load Home Page", async ({ page }) => {

The test() function defines a single test case.


It has two main parts:

  1. The test name"Load Home Page" → appears in reports

  2. The test function. This contains all the steps

Think of test() as:

A container that holds one automation scenario.

3️⃣ Fixtures (page, browser, browserContext)

Inside our test:

async ({ page }) => {

The page object is a fixture.

What is a fixture?

A fixture is a resource that Playwright automatically prepares and gives to your test.

In this case:

  • page represents a fresh browser tab

  • It is created before the test

  • It is closed after the test

You do NOT manually launch the browser.

Other built-in fixtures include:

  • browser

  • browserContext

  • request

Example with browserContext

test("Example", async ({ browser }) => {
  const context = await browser.newContext();
  const page = await context.newPage();
});

But in most beginner tests, you will use the page fixture directly.


4️⃣ The Locator Object

In our test:

page.locator(".site-title:visible")

This creates a Locator object.


What is a Locator?

A Locator represents a way to find an element on the page.

It does not immediately act. It defines how to locate the element.

For example:

const header = page.locator(".site-title:visible");

This does not click or validate anything yet. It just defines where the element is.

Playwright locators:

  • Automatically wait for elements

  • Handle visibility checks

  • Retry until timeout


📌 In our demo store, there are duplicate elements (desktop + mobile).That’s why we used:

:visible

to select only the visible one.


5️⃣ The expect() Assertion Library

Assertions verify that something is correct.

In our test:

await expect(page).toHaveTitle("...");

and

await expect(page.locator(...)).toHaveText("...");

expect() checks whether:

  • The page title matches

  • The element text matches

  • The element is visible

  • The element contains text


Without assertions, a test only performs actions. It does not validate behavior.

Assertions determine whether the test:

  • Passes

  • Fails


6️⃣ The async / await Model

Notice every Playwright action uses await.

await page.goto("http://qa-cart.com");
await expect(...);

Why?

Browser operations take time:

  • Page loading

  • Rendering elements

  • Network responses

JavaScript runs asynchronously.

If you remove await:

page.goto("http://qa-cart.com"); // ❌

The next line may execute before the page finishes loading.

This causes:

  • Random failures

  • Flaky tests

  • Hard-to-debug issues


How All Core Concepts Work Together


Here’s what happens when you run the test:

  1. Playwright Test Runner starts

  2. It finds the test file

  3. It creates a browser

  4. It creates a page fixture

  5. It runs the test() function

  6. It executes steps using async/await

  7. It validates results using expect()

  8. It closes the browser

  9. It generates a report




Comments


Never Miss a Post. Subscribe Now!

Thanks for submitting!

©anuradha agarwal

    bottom of page