Playwright Custom Fixtures with Examples

In Playwright, fixtures are reusable setup and teardown utilities that help you share test data, page objects, authentication, API clients, and configurations across tests.

Custom fixtures make your framework:

  • Reusable
  • Maintainable
  • Scalable
  • Cleaner and easier to read

1. What is a Fixture in Playwright?

A fixture is a setup environment provided to your test before execution.

Playwright already provides built-in fixtures such as:

  • page
  • browser
  • context
  • request

Example:

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

test('example test', async ({ page }) => {
await page.goto('https://example.com');
});

Here, page is a built-in fixture.


2. Why Use Custom Fixtures?

Custom fixtures help when you want to:

  • Reuse login steps
  • Share page objects
  • Create API clients
  • Initialize test data
  • Setup database connections
  • Handle authentication
  • Avoid duplicate code

3. Basic Structure of Custom Fixture

import { test as base } from '@playwright/test';

export const test = base.extend({

myFixture: async ({}, use) => {

// Setup
const data = "Hello Fixture";

// Provide fixture
await use(data);

// Teardown
console.log("Fixture cleanup");
}
});

4. Example 1 โ€” Simple Custom Fixture

Folder Structure

project
โ”œโ”€โ”€ tests
โ”‚ โ””โ”€โ”€ example.spec.ts
โ”‚
โ”œโ”€โ”€ fixtures
โ”‚ โ””โ”€โ”€ testFixture.ts

Step 1: Create Fixture File

fixtures/testFixture.ts

import { test as base } from '@playwright/test';

type MyFixtures = {
userName: string;
};

export const test = base.extend<MyFixtures>({

userName: async ({}, use) => {

const name = 'Deepesh';

await use(name);

console.log('Test completed');
}
});

export { expect } from '@playwright/test';

Step 2: Use Fixture in Test

tests/example.spec.ts

import { test, expect } from '../fixtures/testFixture';

test('Custom Fixture Example', async ({ userName }) => {

console.log(userName);

expect(userName).toBe('Deepesh');
});

5. Example 2 โ€” Page Object Fixture

This is the most common real-world usage.


Folder Structure

project
โ”œโ”€โ”€ pages
โ”‚ โ””โ”€โ”€ LoginPage.ts
โ”‚
โ”œโ”€โ”€ fixtures
โ”‚ โ””โ”€โ”€ pageFixture.ts
โ”‚
โ”œโ”€โ”€ tests
โ”‚ โ””โ”€โ”€ login.spec.ts

Step 1: Create Page Object

pages/LoginPage.ts

import { Page } from '@playwright/test';

export class LoginPage {

constructor(private page: Page) {}

async navigate() {
await this.page.goto('https://example.com/login');
}

async login(username: string, password: string) {

await this.page.fill('#username', username);
await this.page.fill('#password', password);

await this.page.click('#loginBtn');
}
}

Step 2: Create Fixture

fixtures/pageFixture.ts

import { test as base } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';

type PageFixtures = {
loginPage: LoginPage;
};

export const test = base.extend<PageFixtures>({

loginPage: async ({ page }, use) => {

const loginPage = new LoginPage(page);

await use(loginPage);
}
});

export { expect } from '@playwright/test';

Step 3: Use Fixture in Test

tests/login.spec.ts

import { test, expect } from '../fixtures/pageFixture';

test('Login Test', async ({ loginPage }) => {

await loginPage.navigate();

await loginPage.login(
'admin',
'password123'
);
});

6. Example 3 โ€” Authentication Fixture

This is extremely useful in enterprise frameworks.


Authentication Fixture

import { test as base } from '@playwright/test';

type AuthFixtures = {
authenticatedPage: any;
};

export const test = base.extend<AuthFixtures>({

authenticatedPage: async ({ page }, use) => {

await page.goto('https://example.com/login');

await page.fill('#username', 'admin');
await page.fill('#password', 'admin123');

await page.click('#login');

// Reuse logged-in page
await use(page);

// Optional cleanup
await page.close();
}
});

export { expect } from '@playwright/test';

Test File

import { test, expect } from '../fixtures/authFixture';

test('Dashboard Test', async ({ authenticatedPage }) => {

await authenticatedPage.goto(
'https://example.com/dashboard'
);

await expect(
authenticatedPage.locator('h1')
).toContainText('Dashboard');
});

7. Example 4 โ€” API Fixture

Useful for API automation frameworks.


fixtures/apiFixture.ts

import { test as base, request } from '@playwright/test';

type ApiFixture = {
apiContext: any;
};

export const test = base.extend<ApiFixture>({

apiContext: async ({}, use) => {

const apiContext = await request.newContext({

baseURL: 'https://reqres.in/api',

extraHTTPHeaders: {
'Accept': 'application/json'
}
});

await use(apiContext);

await apiContext.dispose();
}
});

export { expect } from '@playwright/test';

API Test

import { test, expect } from '../fixtures/apiFixture';

test('Get Users API', async ({ apiContext }) => {

const response = await apiContext.get('/users?page=2');

expect(response.status()).toBe(200);

const body = await response.json();

console.log(body);
});

8. Worker Fixture vs Test Fixture

Playwright supports two fixture scopes.

Fixture TypeScopeRuns
Test FixturePer TestEvery test
Worker FixturePer WorkerOnce per worker

Example of Worker Fixture

import { test as base } from '@playwright/test';

type WorkerFixture = {
token: string;
};

export const test = base.extend<{}, WorkerFixture>({

token: [async ({}, use) => {

console.log('Generate Token');

const token = 'ABC123TOKEN';

await use(token);

}, { scope: 'worker' }]
});

9. Auto Fixtures

Auto fixtures execute automatically before every test.


Example

import { test as base } from '@playwright/test';

export const test = base.extend({

autoLogger: [async ({}, use) => {

console.log('Before Test');

await use();

console.log('After Test');

}, { auto: true }]
});

10. Best Practices

Use Fixtures For

  • Login handling
  • API clients
  • Database setup
  • Page objects
  • Environment setup
  • Test data generation

Avoid

  • Very large fixtures
  • Too much business logic
  • Circular dependencies
  • Hardcoded credentials

11. Real Enterprise Framework Structure

project
โ”œโ”€โ”€ fixtures
โ”‚ โ”œโ”€โ”€ authFixture.ts
โ”‚ โ”œโ”€โ”€ apiFixture.ts
โ”‚ โ”œโ”€โ”€ pageFixture.ts
โ”‚
โ”œโ”€โ”€ pages
โ”‚ โ”œโ”€โ”€ LoginPage.ts
โ”‚ โ”œโ”€โ”€ DashboardPage.ts
โ”‚
โ”œโ”€โ”€ tests
โ”‚ โ”œโ”€โ”€ ui
โ”‚ โ”œโ”€โ”€ api
โ”‚
โ”œโ”€โ”€ utils
โ”œโ”€โ”€ test-data
โ”œโ”€โ”€ playwright.config.ts

12. Advantages of Custom Fixtures

BenefitDescription
ReusabilityAvoid duplicate code
ScalabilityEasier framework growth
MaintainabilityCentralized setup
Clean TestsBetter readability
Faster DevelopmentReuse common logic

13. Interview Questions

Q1. What is a fixture in Playwright?

A reusable setup/teardown utility used in tests.


Q2. Difference between built-in and custom fixtures?

  • Built-in fixtures are provided by Playwright.
  • Custom fixtures are user-defined.

Q3. What is worker scope?

Fixture executes once per worker process.


Q4. Why use fixtures with Page Object Model?

To inject reusable page object instances into tests.


14. Recommended Real-World Usage

Most companies use fixtures for:

  • Authentication
  • Page Object initialization
  • API clients
  • Environment configuration
  • Test reporting
  • Database utilities
  • Logging

15. Summary

Custom fixtures are one of the most important concepts in Playwright frameworks because they:

  • Reduce code duplication
  • Improve maintainability
  • Support scalable automation frameworks
  • Work perfectly with POM and API automation

Most enterprise Playwright frameworks heavily depend on custom fixtures.

JavaScript Exception Handling

Exception handling in JavaScript is used to manage runtime errors without stopping the entire program. It helps developers write stable and reliable applications.


What is an Exception?

An exception is an unexpected error that occurs while the program is running.

Examples:

  • Dividing by invalid values
  • Accessing undefined variables
  • Invalid JSON parsing
  • Network/API failures
  • Custom validation errors

Why Exception Handling is Important

Exception handling helps to:

  • Prevent application crashes
  • Show meaningful error messages
  • Debug applications easily
  • Handle API/database failures gracefully
  • Improve user experience

1. The Core Structure: try...catch

The try block contains code that might throw an error. If an error occurs, JavaScript immediately stops executing the try block and jumps to the catch block.

JavaScript

try {
  // Code that might fail
  let result = 10 / unknownVariable; 
  console.log("This line will not run");
} catch (error) {
  // Code to handle the error
  console.log("An error occurred:", error.message);
}

console.log("Execution continues normally.");

2. Standard Error Properties

Inside the catch block, the error object provides valuable diagnostic metadata:

  • error.name: The type of error (e.g., ReferenceError, TypeError).
  • error.message: A human-readable description of what went wrong.
  • error.stack: The stack trace showing where the error occurred in the source files.

JavaScript

try {
  null.toString(); // Throws a TypeError
} catch (err) {
  console.log("Name:", err.name);       // "TypeError"
  console.log("Message:", err.message); // "Cannot read properties of null..."
}

3. The finally Block

The optional finally block always executes, regardless of whether an error occurred or was caught. It is ideal for cleanup tasks (e.g., closing file streams, resetting UI states, or clearing timers).

JavaScript

let isLoading = true;

try {
  // Simulating an operation
  console.log("Fetching data...");
  throw new Error("Network timeout");
} catch (err) {
  console.log("Error caught:", err.message);
} finally {
  // Runs whether try succeeds or catch fires
  isLoading = false;
  console.log("Loading completed. Status:", isLoading);
}

4. Throwing Custom Errors (throw)

You can trigger explicit errors using the throw statement. While you can throw primitives (strings or numbers), it is best practice to throw standard Error objects so you retain stack trace information.

JavaScript

function withdrawMoney(amount, balance) {
  if (typeof amount !== 'number') {
    throw new TypeError("Amount must be a number");
  }
  if (amount > balance) {
    throw new Error("Insufficient funds for this withdrawal");
  }
  return balance - amount;
}

try {
  let newBalance = withdrawMoney(150, 100);
} catch (err) {
  console.log(`[${err.name}] ${err.message}`);
}

5. Built-in JavaScript Error Types

Understanding common built-in error classes helps you diagnose issues quickly:

Error TypeTrigger CauseExample
ReferenceErrorAccessing an undeclared variableconsole.log(x);
TypeErrorPerforming an invalid operation on a value"text".toUpperCase() works, but (123).toUpperCase() fails
SyntaxErrorInvalid JavaScript syntax (usually caught at parse time)JSON.parse("{ bad json }")
RangeErrorA numeric variable or parameter is outside its valid rangenew Array(-1)

6. Asynchronous Exception Handling

Traditional try...catch blocks cannot catch errors inside asynchronous callbacks or promises because the try block finishes executing before the async callback runs.

Promises

Use the .catch() method to handle rejected promises:

JavaScript

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error("API server offline")), 1000);
  });
}

fetchData()
  .then(data => console.log(data))
  .catch(err => console.log("Promise Error:", err.message));

async / await

With async / await, you can wrap asynchronous code in a standard try...catch block:

JavaScript

async function loadUserData() {
  try {
    let response = await fetchData(); // Waits for promise resolution/rejection
    console.log(response);
  } catch (err) {
    console.log("Async/Await Error:", err.message);
  }
}

loadUserData();

Nested try…catch

You can use multiple try-catch blocks.

try {
try {
console.log(userName);
} catch(error) {
console.log("Inner Catch");
}

console.log(data);
} catch(error) {
console.log("Outer Catch");
}

Exception Handling in Functions

function divide(a, b) {
try {
if(b === 0) {
throw new Error("Division by zero not allowed");
}

return a / b;

} catch(error) {
return error.message;
}
}

console.log(divide(10, 0));

Exception Handling with JSON

Very common in API automation and backend development.

let jsonData = '{"name":"Deepesh"}';

try {
let user = JSON.parse(jsonData);
console.log(user.name);

} catch(error) {
console.log("Invalid JSON");
}

Invalid JSON Example

let jsonData = '{"name":"Deepesh"';

try {
let user = JSON.parse(jsonData);

} catch(error) {
console.log("JSON Parsing Failed");
}

Async Exception Handling

Used with async/await.

Example

async function fetchData() {

try {
let response = await fetch("https://dummyjson.com/users/1");

let data = await response.json();

console.log(data);

} catch(error) {
console.log("API Error:", error.message);
}
}

fetchData();

Type of Errors with Examples:

JavaScript provides standard built-in error constructors that inherit from the base Error object. Each error type corresponds to a specific category of runtime exception.

1. Core Built-In Error Types

Error (Generic Base Error)

The generic base object used for general exceptions or as a parent class for custom user-defined errors.

JavaScript

try {
  throw new Error("Application failed to process the request.");
} catch (err) {
  console.log(err.name);    // "Error"
  console.log(err.message); // "Application failed to process the request."
}

TypeError

Occurs when an operation is performed on a value of an unexpected data type, such as attempting to invoke a non-function or reading properties of null/undefined.

JavaScript

try {
  const count = 42;
  count.toUpperCase(); // TypeError: count.toUpperCase is not a function
} catch (err) {
  console.log(err.name); // "TypeError"
}

ReferenceError

Occurs when trying to access or dereference a variable that does not exist or has not been initialized (such as accessing a let/const variable in its Temporal Dead Zone).

JavaScript

try {
  console.log(nonExistentVariable); // ReferenceError
} catch (err) {
  console.log(err.name); // "ReferenceError"
}

SyntaxError

Occurs when code violates JavaScript language syntax rules. Parsing utilities like JSON.parse() or eval() throw runtime SyntaxErrors when passed malformed input.

JavaScript

try {
  JSON.parse("{ badJson: true "); // SyntaxError: Unexpected token...
} catch (err) {
  console.log(err.name); // "SyntaxError"
}

RangeError

Occurs when a numeric value or function argument falls outside its allowed range or bounds (e.g., invalid array lengths, out-of-bounds numbers in .toFixed(), or max stack size recursion).

JavaScript

try {
  const invalidArray = new Array(-10); // RangeError: Invalid array length
} catch (err) {
  console.log(err.name); // "RangeError"
}

URIError

Occurs when URI encoding or decoding global functions (such as decodeURI(), decodeURIComponent(), or encodeURI()) encounter malformed characters.

JavaScript

try {
  decodeURI("%"); // URIError: URI malformed
} catch (err) {
  console.log(err.name); // "URIError"
}

AggregateError

Introduced in ES2021, AggregateError wraps multiple errors into a single error object. It is automatically thrown by Promise.any() when every promise passed to it rejects.

JavaScript

Promise.any([
  Promise.reject(new Error("Database offline")),
  Promise.reject(new Error("Cache unavailable"))
]).catch(err => {
  console.log(err instanceof AggregateError); // true
  console.log(err.errors[0].message);         // "Database offline"
  console.log(err.errors[1].message);         // "Cache unavailable"
});

SuppressedError

Introduced with Explicit Resource Management (using declarations). It occurs when an error is thrown during the cleanup/disposal of a resource while another error was already active.

JavaScript

try {
  // Represents a primary error and a secondary disposal error
  throw new SuppressedError(
    new Error("Cleanup failed"),  // The new error during disposal
    new Error("Main logic failed"), // The original suppressed error
    "Resource disposal failure"
  );
} catch (err) {
  console.log(err.error.message);      // "Cleanup failed"
  console.log(err.suppressed.message); // "Main logic failed"
}

EvalError

A legacy error object created for issues related to the global eval() function. While modern JS engines no longer throw native EvalErrors (favoring SyntaxError or TypeError instead), the constructor remains in the language specification for backwards compatibility.

JavaScript

try {
  throw new EvalError("Custom evaluation error");
} catch (err) {
  console.log(err.name); // "EvalError"
}

2. Environment & Host-Specific Errors

Beyond core ECMAScript, JavaScript runtime environments (browsers, Node.js) define additional specialized error objects:

Error TypeEnvironmentCause
DOMExceptionWeb APIs / Node.jsRaised by Web APIs for operations like aborted fetch requests (AbortError), quota limits (QuotaExceededError), or security policy violations.
InternalErrorSpiderMonkey (Firefox)Non-standard error thrown when the JS engine encounters internal limits (e.g., “too much recursion”).
WebAssembly.*ErrorBrowsers / Node.jsWebAssembly.CompileError, WebAssembly.LinkError, or WebAssembly.RuntimeError thrown during Wasm operations.

Quick Reference Summary

Error (Base Class)
โ”œโ”€โ”€ TypeError          (Wrong value type / invalid invocation)
โ”œโ”€โ”€ ReferenceError     (Variable does not exist / TDZ)
โ”œโ”€โ”€ SyntaxError        (Malformed code or invalid JSON)
โ”œโ”€โ”€ RangeError         (Numeric parameter out of bounds)
โ”œโ”€โ”€ URIError           (Malformed URI sequence)
โ”œโ”€โ”€ AggregateError     (Collection of multiple errors)
โ”œโ”€โ”€ SuppressedError    (Resource disposal error over an existing error)
โ”œโ”€โ”€ EvalError          (Legacy eval exception)
โ””โ”€โ”€ Environment Errors (DOMException, WebAssembly errors, etc.)

Best Practices

1. Use Specific Error Messages

throw new Error("Password cannot be empty");

2. Avoid Empty catch Blocks

โŒ Bad

catch(error) {

}

โœ… Good

catch(error) {
console.log(error.message);
}

3. Use finally for Cleanup

Useful for:

  • Closing database connections
  • Clearing resources
  • Stopping loaders

4. Do Not Overuse try…catch

Use it only around risky code.


Real-World Example

Form Validation

function login(username, password) {

try {

if(!username) {
throw new Error("Username is required");
}

if(!password) {
throw new Error("Password is required");
}

console.log("Login Successful");

} catch(error) {
console.log(error.message);
}
}

login("", "12345");

Playwright Framework Read Data from a JSON File

Using JSON files in a Playwright framework is a common way to manage:

  • Test data
  • Environment configuration
  • User credentials
  • API payloads
  • Multiple datasets for data-driven testing

1. Project Structure Example

playwright-framework/
โ”‚
โ”œโ”€โ”€ test-data/
โ”‚ โ”œโ”€โ”€ users.json
โ”‚ โ””โ”€โ”€ loginData.json
โ”‚
โ”œโ”€โ”€ tests/
โ”‚ โ””โ”€โ”€ login.spec.ts
โ”‚
โ”œโ”€โ”€ utils/
โ”‚ โ””โ”€โ”€ jsonReader.ts
โ”‚
โ”œโ”€โ”€ playwright.config.ts
โ”œโ”€โ”€ package.json
โ””โ”€โ”€ tsconfig.json

2. Create a JSON File

test-data/loginData.json

{
"validUser": {
"username": "admin",
"password": "admin123"
},
"invalidUser": {
"username": "wronguser",
"password": "wrongpass"
}
}

3. Read JSON Directly in Playwright Test

tests/login.spec.ts

import { test, expect } from '@playwright/test';
import loginData from '../test-data/loginData.json';

test('Login with valid user', async ({ page }) => {

await page.goto('https://example.com/login');

await page.fill('#username', loginData.validUser.username);

await page.fill('#password', loginData.validUser.password);

await page.click('#loginBtn');

await expect(page).toHaveURL(/dashboard/);
});

4. Enable JSON Imports in TypeScript

Update your tsconfig.json.

tsconfig.json

{
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true
}
}

5. Reading JSON Using fs Module (Dynamic Read)

This approach is useful when:

  • File changes frequently
  • Large datasets
  • Runtime data loading
  • External config management

utils/jsonReader.ts

import fs from 'fs';

export function readJsonFile(path: string) {

const data = fs.readFileSync(path, 'utf-8');

return JSON.parse(data);
}

Usage in Test

import { test, expect } from '@playwright/test';
import { readJsonFile } from '../utils/jsonReader';

test('Login using JSON data', async ({ page }) => {

const testData = readJsonFile('./test-data/loginData.json');

await page.goto('https://example.com/login');

await page.fill('#username', testData.validUser.username);

await page.fill('#password', testData.validUser.password);

await page.click('#loginBtn');

await expect(page).toHaveURL(/dashboard/);
});

6. Data-Driven Testing Using JSON

test-data/users.json

[
{
"username": "user1",
"password": "pass1"
},
{
"username": "user2",
"password": "pass2"
},
{
"username": "user3",
"password": "pass3"
}
]

Data-Driven Playwright Test

import { test } from '@playwright/test';
import users from '../test-data/users.json';

users.forEach((user) => {

test(`Login test for ${user.username}`, async ({ page }) => {

await page.goto('https://example.com/login');

await page.fill('#username', user.username);

await page.fill('#password', user.password);

await page.click('#loginBtn');
});
});

7. Best Practice in Enterprise Playwright Framework

Keep Separate JSON Files For

PurposeExample File
Login DataloginData.json
API Payloadspayloads.json
Environment Dataenv.json
Test Usersusers.json
Configurationsconfig.json

8. Recommended Folder Structure

test-data/
โ”‚
โ”œโ”€โ”€ ui/
โ”‚ โ”œโ”€โ”€ login.json
โ”‚ โ””โ”€โ”€ checkout.json
โ”‚
โ”œโ”€โ”€ api/
โ”‚ โ”œโ”€โ”€ createUser.json
โ”‚ โ””โ”€โ”€ updateUser.json
โ”‚
โ””โ”€โ”€ environments/
โ”œโ”€โ”€ qa.json
โ””โ”€โ”€ prod.json

9. Example: Environment Configuration

environments/qa.json

{
"baseURL": "https://qa.example.com",
"username": "qauser",
"password": "qapass"
}

Usage

import env from '../test-data/environments/qa.json';

test('Environment Test', async ({ page }) => {

await page.goto(env.baseURL);
});

10. Async JSON Read Example

import fs from 'fs/promises';

export async function readJson(path: string) {

const data = await fs.readFile(path, 'utf-8');

return JSON.parse(data);
}

11. Real-World Enterprise Utility Class

utils/dataManager.ts

import fs from 'fs';

export class DataManager {

static getTestData(filePath: string) {

const data = fs.readFileSync(filePath, 'utf-8');

return JSON.parse(data);
}
}

Usage

import { test } from '@playwright/test';
import { DataManager } from '../utils/dataManager';

test('Enterprise JSON Example', async ({ page }) => {

const data = DataManager.getTestData(
'./test-data/loginData.json'
);

await page.goto('https://example.com');

console.log(data.validUser.username);
});

12. Common Errors and Fixes

ErrorSolution
Cannot find JSON moduleAdd resolveJsonModule: true
Unexpected token JSONUse JSON.parse() properly
Path not foundUse correct relative path
Undefined valuesVerify JSON structure

13. Recommended Best Practices

Use JSON When

โœ… Static test data
โœ… Small-medium datasets
โœ… Config management
โœ… API request payloads

Playwright API Automation with POM

API Automation with Page Object Model (POM)

What is API Automation in Playwright?

Playwright is not only used for UI automation; it also supports powerful API testing using built-in HTTP request methods.

API automation helps to:

  • Validate backend services
  • Test REST APIs
  • Verify response data
  • Perform authentication testing
  • Integrate API + UI workflows

Why Use Page Object Model (POM) for API Testing?

Page Object Model is a design pattern used to:

  • Separate API logic from test logic
  • Improve code reusability
  • Make framework scalable
  • Reduce code duplication
  • Improve maintenance

Recommended Project Structure

playwright-api-framework/
โ”‚
โ”œโ”€โ”€ tests/
โ”‚ โ”œโ”€โ”€ user.spec.ts
โ”‚ โ””โ”€โ”€ booking.spec.ts
โ”‚
โ”œโ”€โ”€ api/
โ”‚ โ”œโ”€โ”€ UserAPI.ts
โ”‚ โ””โ”€โ”€ BookingAPI.ts
โ”‚
โ”œโ”€โ”€ utils/
โ”‚ โ”œโ”€โ”€ apiClient.ts
โ”‚ โ””โ”€โ”€ testData.ts
โ”‚
โ”œโ”€โ”€ fixtures/
โ”‚ โ””โ”€โ”€ auth.json
โ”‚
โ”œโ”€โ”€ playwright.config.ts
โ”œโ”€โ”€ package.json
โ””โ”€โ”€ tsconfig.json

Step 1: Install Playwright

Initialize Project

npm init -y

Install Playwright

npm init playwright@latest

Choose:

  • TypeScript
  • VS Code
  • GitHub Actions (optional)

Step 2: Configure Playwright

playwright.config.ts

import { defineConfig } from '@playwright/test';

export default defineConfig({
use: {
baseURL: 'https://reqres.in/api',
extraHTTPHeaders: {
'Content-Type': 'application/json'
}
}
});

Step 3: Create Base API Client

utils/apiClient.ts

This class handles common API operations.

import { APIRequestContext, request } from '@playwright/test';

export class APIClient {
private apiContext!: APIRequestContext;

async createContext() {
this.apiContext = await request.newContext({
baseURL: 'https://reqres.in/api',
extraHTTPHeaders: {
'Content-Type': 'application/json'
}
});
}

getContext() {
return this.apiContext;
}
}

Step 4: Create API Page Object

api/UserAPI.ts

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

export class UserAPI {
readonly request: APIRequestContext;

constructor(request: APIRequestContext) {
this.request = request;
}

async getUsers(pageNumber: number) {
const response = await this.request.get(`/users?page=${pageNumber}`);

expect(response.status()).toBe(200);

return await response.json();
}

async createUser(name: string, job: string) {
const response = await this.request.post('/users', {
data: {
name,
job
}
});

expect(response.status()).toBe(201);

return await response.json();
}

async updateUser(id: number, name: string, job: string) {
const response = await this.request.put(`/users/${id}`, {
data: {
name,
job
}
});

expect(response.status()).toBe(200);

return await response.json();
}

async deleteUser(id: number) {
const response = await this.request.delete(`/users/${id}`);

expect(response.status()).toBe(204);
}
}

Step 5: Write API Test Cases

tests/user.spec.ts

import { test, request, expect } from '@playwright/test';
import { UserAPI } from '../api/UserAPI';

test.describe('User API Tests', () => {

let userAPI: UserAPI;

test.beforeEach(async () => {
const apiContext = await request.newContext({
baseURL: 'https://reqres.in/api'
});

userAPI = new UserAPI(apiContext);
});

test('Get Users List', async () => {

const response = await userAPI.getUsers(2);

expect(response.page).toBe(2);
expect(response.data.length).toBeGreaterThan(0);
});

test('Create New User', async () => {

const response = await userAPI.createUser(
'Deepesh',
'QA Engineer'
);

expect(response.name).toBe('Deepesh');
expect(response.job).toBe('QA Engineer');
});

test('Update Existing User', async () => {

const response = await userAPI.updateUser(
2,
'Deepesh Updated',
'Senior QA'
);

expect(response.name).toBe('Deepesh Updated');
});

test('Delete User', async () => {

await userAPI.deleteUser(2);
});

});

Step 6: Execute Tests

Run All Tests

npx playwright test

Run Specific File

npx playwright test tests/user.spec.ts

Run in Headed Mode

npx playwright test --headed

Generate HTML Report

npx playwright show-report

API Assertions Examples

Validate Status Code

expect(response.status()).toBe(200);

Validate Response Body

expect(responseBody.name).toBe('Deepesh');

Validate Headers

expect(response.headers()['content-type'])
.toContain('application/json');

Authentication Example

Login API

async login(email: string, password: string) {

const response = await this.request.post('/login', {
data: {
email,
password
}
});

return await response.json();
}

Token Handling Example

const token = loginResponse.token;

const apiContext = await request.newContext({
extraHTTPHeaders: {
Authorization: `Bearer ${token}`
}
});

Reusable Test Data

utils/testData.ts

export const users = {
adminUser: {
name: 'Deepesh',
job: 'Automation Engineer'
}
};

Advanced Framework Enhancements

You can extend this framework with:

FeaturePurpose
Environment ConfigDEV/UAT/PROD support
LoggerAPI request-response logs
Allure ReportsAdvanced reporting
Retry MechanismHandle flaky APIs
CI/CDJenkins/GitHub Actions
Database ValidationBackend verification
Schema ValidationValidate JSON structure
Faker LibraryDynamic test data
Parallel ExecutionFaster execution

Real-World Enterprise Structure

framework/
โ”‚
โ”œโ”€โ”€ api/
โ”œโ”€โ”€ tests/
โ”œโ”€โ”€ fixtures/
โ”œโ”€โ”€ utils/
โ”œโ”€โ”€ helpers/
โ”œโ”€โ”€ data/
โ”œโ”€โ”€ reports/
โ”œโ”€โ”€ logs/
โ”œโ”€โ”€ schemas/
โ”œโ”€โ”€ config/
โ””โ”€โ”€ .github/workflows/

Best Practices

1. Keep API Logic Separate

Do not write API calls directly inside test files.

โœ… Correct:

userAPI.createUser()

โŒ Wrong:

request.post(...)

inside every test.


2. Use Environment Variables

BASE_URL=https://uat-api.company.com

3. Validate Response Time

expect(response.ok()).toBeTruthy();

4. Use Soft Assertions Carefully

expect.soft(response.status()).toBe(200);

5. Create Reusable Helpers

Example:

  • Token manager
  • Payload builder
  • Common assertions

Advantages of Playwright API Automation

AdvantageDescription
Fast ExecutionNo browser required
Built-in AssertionsEasy validations
API + UI ComboEnd-to-end workflow
Parallel SupportFaster pipelines
TypeScript SupportBetter maintainability
Auto WaitingStable execution

API + UI Hybrid Testing Example

test('Create user via API and validate in UI', async ({ page }) => {

// Create user via API
await userAPI.createUser('Deepesh', 'QA');

// Validate in UI
await page.goto('/users');

await expect(
page.locator('text=Deepesh')
).toBeVisible();
});

Maintain Different Config Files for API and UI Tests

To maintain 2 separate config files for API and UI test cases in frameworks like Playwright Docs, the best approach is to create the following:

  • One config for UI tests
  • One config for API tests

This helps you:

  • Run tests independently
  • Use different base URLs
  • Use different reporters/timeouts
  • Execute API tests faster without browser launch
  • Maintain clean project structure

Recommended Project Structure

project-root/
โ”‚
โ”œโ”€โ”€ tests/
โ”‚ โ”œโ”€โ”€ ui/
โ”‚ โ”‚ โ”œโ”€โ”€ login.spec.ts
โ”‚ โ”‚ โ””โ”€โ”€ dashboard.spec.ts
โ”‚ โ”‚
โ”‚ โ””โ”€โ”€ api/
โ”‚ โ”œโ”€โ”€ users.spec.ts
โ”‚ โ””โ”€โ”€ auth.spec.ts
โ”‚
โ”œโ”€โ”€ playwright-ui.config.ts
โ”œโ”€โ”€ playwright-api.config.ts
โ”‚
โ”œโ”€โ”€ utils/
โ”œโ”€โ”€ pages/
โ”œโ”€โ”€ package.json
โ””โ”€โ”€ tsconfig.json

1. UI Config File

Create:

playwright-ui.config.ts

import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './tests/ui',

timeout: 60000,

use: {
browserName: 'chromium',
headless: false,
baseURL: 'https://example-ui.com',

screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'on-first-retry'
},

reporter: [
['html'],
['list']
],

projects: [
{
name: 'chrome',
use: {
browserName: 'chromium'
}
}
]
});

2. API Config File

Create:

playwright-api.config.ts

import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './tests/api',

timeout: 30000,

use: {
baseURL: 'https://api.example.com',

extraHTTPHeaders: {
Accept: 'application/json'
}
},

reporter: [
['html'],
['dot']
],

workers: 4
});

3. Run UI Tests

npx playwright test --config=playwright-ui.config.ts

4. Run API Tests

npx playwright test --config=playwright-api.config.ts

5. Add Package.json Scripts

package.json

{
"scripts": {
"test:ui": "playwright test --config=playwright-ui.config.ts",

"test:api": "playwright test --config=playwright-api.config.ts",

"test:all": "npm run test:ui && npm run test:api"
}
}

6. Environment-Specific Config (Recommended)

You can also maintain:

.env.dev
.env.qa
.env.stage

Install dotenv:

npm install dotenv

Example:

import dotenv from 'dotenv';

dotenv.config({ path: '.env.qa' });

export default defineConfig({
use: {
baseURL: process.env.BASE_URL
}
});

7. Better Enterprise Approach (Best Practice)

Many companies use:

configs/
โ”‚
โ”œโ”€โ”€ ui/
โ”‚ โ”œโ”€โ”€ dev.config.ts
โ”‚ โ”œโ”€โ”€ qa.config.ts
โ”‚ โ””โ”€โ”€ stage.config.ts
โ”‚
โ””โ”€โ”€ api/
โ”œโ”€โ”€ dev.config.ts
โ”œโ”€โ”€ qa.config.ts
โ””โ”€โ”€ stage.config.ts

This supports:

  • Multiple environments
  • CI/CD pipelines
  • Parallel execution
  • Easy maintenance

8. Common Real-World Usage

TypeSeparate Config Needed?Why
UI TestsYesBrowser settings
API TestsYesNo browser needed
Mobile TestsYesDevice configs
Smoke TestsYesFaster execution
RegressionYesLarge suite handling

9. Advanced Approach Using Base Config

You can avoid duplication using a shared base config.

playwright.base.ts

import { defineConfig } from '@playwright/test';

export default defineConfig({
timeout: 30000,

reporter: 'html'
});

UI Config

import base from './playwright.base';

export default {
...base,

testDir: './tests/ui',

use: {
browserName: 'chromium',
baseURL: 'https://ui.example.com'
}
};

API Config

import base from './playwright.base';

export default {
...base,

testDir: './tests/api',

use: {
baseURL: 'https://api.example.com'
}
};

Best Practice Recommendation

Use:

โœ… Separate config files
โœ… Shared base config
โœ… Environment variables
โœ… Separate folders for API/UI
โœ… Separate reports
โœ… Package.json scripts

Step-by-Step Guide to Install Git on MacOS

Method 1: Install Git Using Homebrew (Recommended)

Step 1: Open Terminal

Press:

  • Command (โŒ˜) + Space
  • Type Terminal
  • Press Enter

Step 2: Check if Git is Already Installed

Run:

git --version

If Git is installed, youโ€™ll see output like:

git version 2.45.0

If not installed, continue below.


Step 3: Install Homebrew (If Not Installed)

Run this command in Terminal:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Wait for installation to complete.


Step 4: Verify Homebrew Installation

Run:

brew --version

Example output:

Homebrew 4.3.0

Step 5: Install Git Using Homebrew

Run:

brew install git

Homebrew downloads and installs the latest Git version.


Step 6: Verify Git Installation

Run:

git --version

Example:

git version 2.45.1

Step 7: Configure Git Username

Run:

git config --global user.name "Your Name"

Example:

git config --global user.name "Deepesh Yadav"

Step 8: Configure Git Email

Run:

git config --global user.email "your-email@example.com"

Example:

git config --global user.email "deepesh@gmail.com"

Step 9: Verify Git Configuration

Run:

git config --list

Example output:

user.name=Deepesh Yadav
user.email=deepesh@gmail.com

Playwright Page Object Model (POM) – Step by Step Guide

1. What is Page Object Model (POM)?

Page Object Model (POM) is a design pattern used in test automation where:

  • Each web page is represented as a class
  • Locators and methods are stored separately from test files
  • Tests become reusable, maintainable, and readable

2. Why Use POM?

Problems Without POM

Without POM:

  • Duplicate locators everywhere
  • Hard to maintain tests
  • UI changes break multiple tests
  • Large test files become messy

Benefits of POM

โœ… Reusable code
โœ… Easy maintenance
โœ… Better readability
โœ… Centralized locators
โœ… Scalable framework
โœ… Cleaner tests


3. Basic Folder Structure

project/
โ”‚
โ”œโ”€โ”€ tests/
โ”‚ โ””โ”€โ”€ login.spec.ts
โ”‚
โ”œโ”€โ”€ pages/
โ”‚ โ””โ”€โ”€ LoginPage.ts
โ”‚
โ”œโ”€โ”€ utils/
โ”‚
โ”œโ”€โ”€ fixtures/
โ”‚
โ”œโ”€โ”€ playwright.config.ts
โ”‚
โ”œโ”€โ”€ package.json
โ”‚
โ””โ”€โ”€ tsconfig.json

4. Install Playwright

Step 1: Create Project

mkdir playwright-pom
cd playwright-pom

Step 2: Initialize Node Project

npm init -y

Step 3: Install Playwright

npm init playwright@latest

Select:

  • TypeScript
  • Tests folder
  • GitHub Actions (optional)

5. Understanding POM Structure

In POM:

ComponentResponsibility
Page ClassStores locators + methods
Test FileContains test scenarios
FixturesShared setup
UtilsReusable helper methods

6. Create Your First Page Object


Example Website

We will automate:

  • Login page
  • Dashboard validation

7. Create Login Page Class

File

pages/LoginPage.ts

LoginPage.ts

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

export class LoginPage {

readonly page: Page;
readonly username: Locator;
readonly password: Locator;
readonly loginBtn: Locator;
readonly dashboardText: Locator;

constructor(page: Page) {
this.page = page;

this.username = page.locator('#username');
this.password = page.locator('#password');
this.loginBtn = page.locator('#loginBtn');
this.dashboardText = page.locator('text=Dashboard');
}

async gotoLoginPage() {
await this.page.goto('https://example.com/login');
}

async enterUsername(user: string) {
await this.username.fill(user);
}

async enterPassword(pass: string) {
await this.password.fill(pass);
}

async clickLogin() {
await this.loginBtn.click();
}

async login(user: string, pass: string) {
await this.enterUsername(user);
await this.enterPassword(pass);
await this.clickLogin();
}

async verifyDashboardVisible() {
await expect(this.dashboardText).toBeVisible();
}
}

8. Create Test File

File

tests/login.spec.ts

login.spec.ts

import { test } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';

test('User Login Test', async ({ page }) => {

const loginPage = new LoginPage(page);

await loginPage.gotoLoginPage();

await loginPage.login('admin', 'admin123');

await loginPage.verifyDashboardVisible();
});

9. Execute Tests

npx playwright test

10. Run Specific Test

npx playwright test tests/login.spec.ts

11. View HTML Report

npx playwright show-report

12. Improve POM Design

Basic POM is good, but enterprise frameworks need more structure.


Better Folder Structure

project/
โ”‚
โ”œโ”€โ”€ pages/
โ”‚ โ”œโ”€โ”€ LoginPage.ts
โ”‚ โ”œโ”€โ”€ DashboardPage.ts
โ”‚ โ””โ”€โ”€ BasePage.ts
โ”‚
โ”œโ”€โ”€ tests/
โ”‚
โ”œโ”€โ”€ fixtures/
โ”‚
โ”œโ”€โ”€ test-data/
โ”‚
โ”œโ”€โ”€ utils/
โ”‚
โ”œโ”€โ”€ hooks/
โ”‚
โ”œโ”€โ”€ api/
โ”‚
โ”œโ”€โ”€ constants/
โ”‚
โ””โ”€โ”€ playwright.config.ts

13. Create Base Page

Why Base Page?

To avoid duplicate common methods:

  • click
  • fill
  • wait
  • navigate
  • screenshot

BasePage.ts

import { Page, Locator } from '@playwright/test';

export class BasePage {

readonly page: Page;

constructor(page: Page) {
this.page = page;
}

async navigate(url: string) {
await this.page.goto(url);
}

async click(locator: Locator) {
await locator.click();
}

async fill(locator: Locator, value: string) {
await locator.fill(value);
}

async getTitle() {
return await this.page.title();
}

async wait(milliseconds: number) {
await this.page.waitForTimeout(milliseconds);
}
}

14. Extend Base Page

Updated LoginPage.ts

import { Page, Locator } from '@playwright/test';
import { BasePage } from './BasePage';

export class LoginPage extends BasePage {

readonly username: Locator;
readonly password: Locator;
readonly loginBtn: Locator;

constructor(page: Page) {
super(page);

this.username = page.locator('#username');
this.password = page.locator('#password');
this.loginBtn = page.locator('#loginBtn');
}

async login(user: string, pass: string) {

await this.navigate('https://example.com/login');

await this.fill(this.username, user);

await this.fill(this.password, pass);

await this.click(this.loginBtn);
}
}

15. Create Dashboard Page

DashboardPage.ts

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

export class DashboardPage {

readonly page: Page;
readonly dashboardHeader: Locator;

constructor(page: Page) {
this.page = page;

this.dashboardHeader = page.locator('h1');
}

async verifyDashboardLoaded() {
await expect(this.dashboardHeader).toHaveText('Dashboard');
}
}

16. Updated Test

import { test } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';
import { DashboardPage } from '../pages/DashboardPage';

test('Verify Login', async ({ page }) => {

const loginPage = new LoginPage(page);
const dashboardPage = new DashboardPage(page);

await loginPage.login('admin', 'admin123');

await dashboardPage.verifyDashboardLoaded();
});

17. Best Practices for POM

1. Keep Locators Private to Page

โŒ Bad

page.locator('#btn').click();

inside test files.


โœ… Good

await loginPage.clickLogin();

2. Avoid Assertions Inside Page Methods

Page objects should perform actions.

Assertions should mostly remain in test files.


3. Use Meaningful Method Names

โœ… Good

await loginPage.login();

โŒ Bad

await loginPage.doAction1();

4. One Page = One Class

Each application page should have its own class.


5. Reuse Common Functions

Use:

  • BasePage
  • Utility classes
  • Helper functions

18. Real Enterprise POM Structure

project/
โ”‚
โ”œโ”€โ”€ pages/
โ”‚ โ”œโ”€โ”€ auth/
โ”‚ โ”‚ โ”œโ”€โ”€ LoginPage.ts
โ”‚ โ”‚ โ””โ”€โ”€ ForgotPasswordPage.ts
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ dashboard/
โ”‚ โ”‚ โ””โ”€โ”€ DashboardPage.ts
โ”‚ โ”‚
โ”‚ โ””โ”€โ”€ common/
โ”‚ โ””โ”€โ”€ BasePage.ts
โ”‚
โ”œโ”€โ”€ tests/
โ”‚
โ”œโ”€โ”€ fixtures/
โ”‚
โ”œโ”€โ”€ api/
โ”‚
โ”œโ”€โ”€ utils/
โ”‚
โ”œโ”€โ”€ constants/
โ”‚
โ”œโ”€โ”€ test-data/
โ”‚
โ”œโ”€โ”€ reports/
โ”‚
โ””โ”€โ”€ screenshots/

19. Advanced POM Concepts

Component Object Model

Reusable UI components:

  • Navbar
  • Sidebar
  • Footer
  • Modal
  • Table

Example

export class HeaderComponent {

readonly profileIcon;
readonly logoutBtn;

constructor(page) {
this.profileIcon = page.locator('#profile');
this.logoutBtn = page.locator('#logout');
}

async logout() {
await this.profileIcon.click();
await this.logoutBtn.click();
}
}

20. POM with Fixtures

fixtures/baseTest.ts

import { test as base } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';

type MyFixtures = {
loginPage: LoginPage;
};

export const test = base.extend<MyFixtures>({
loginPage: async ({ page }, use) => {
await use(new LoginPage(page));
},
});

Usage

import { test } from '../fixtures/baseTest';

test('Login Test', async ({ loginPage }) => {

await loginPage.login('admin', 'admin123');
});

21. POM with Environment Variables

Install dotenv

npm install dotenv

.env

BASE_URL=https://example.com
USERNAME=admin
PASSWORD=admin123

playwright.config.ts

import dotenv from 'dotenv';

dotenv.config();

export default {
use: {
baseURL: process.env.BASE_URL
}
};

22. Common Mistakes in POM

โŒ Huge Page Classes

Avoid:

  • 2000-line page classes

Split by:

  • Components
  • Features

โŒ Hardcoded Waits

Avoid:

waitForTimeout(5000)

Use:

  • auto waiting
  • expect
  • waitForResponse

โŒ Duplicate Locators

Centralize locators.


23. Industry-Level Recommendations

Recommended Stack

AreaTool
UI AutomationPlaywright
LanguageTypeScript
FrameworkPOM + Fixtures
ReportingAllure
CI/CDGitHub Actions
API TestingPlaywright API
DataJSON / Faker
Parallel RunPlaywright Workers

24. Final Enterprise Flow

Test File
โ†“
Page Object
โ†“
Base Page
โ†“
Playwright Engine
โ†“
Browser

25. Summary

POM Helps You

โœ… Build scalable frameworks
โœ… Reduce maintenance
โœ… Improve readability
โœ… Reuse code
โœ… Create enterprise-level automation


26. Recommended Next Topics

After learning POM, learn:

  1. Playwright Fixtures
  2. API Testing
  3. Authentication Handling
  4. Parallel Execution
  5. Data-Driven Testing
  6. CI/CD Integration
  7. Retry Mechanism
  8. Playwright Hooks
  9. Allure Reporting
  10. Hybrid Framework Design

JavaScript Object Methods and Programs

In JavaScript, an Object is a non-primitive data type used to store data in key-value pairs.

Objects are one of the most important concepts in JavaScript because almost everything in JavaScript is based on objects.


1. Creating Objects

Using Object Literal (Most Common)

const person = {
name: "John",
age: 25,
city: "New York"
};

console.log(person);

Using new Object()

const person = new Object();

person.name = "John";
person.age = 25;

console.log(person);

2. Accessing Object Properties

Dot Notation

console.log(person.name);
console.log(person.age);

Bracket Notation

console.log(person["name"]);
console.log(person["age"]);

Useful when property names are dynamic.

let key = "name";

console.log(person[key]);

3. Adding Properties

person.country = "USA";

console.log(person);

4. Updating Properties

person.age = 30;

console.log(person.age);

5. Deleting Properties

delete person.city;

console.log(person);

6. Nested Objects

const student = {
name: "Sam",
marks: {
math: 90,
science: 85
}
};

console.log(student.marks.math);

7. Object Methods

Methods are functions inside objects.

const user = {
name: "Alex",

greet: function () {
console.log("Hello");
}
};

user.greet();

Important Object Methods


1. Object.keys()

Returns all object keys.

const person = {
name: "John",
age: 25
};

console.log(Object.keys(person));

Output:

["name", "age"]

2. Object.values()

Returns all values.

console.log(Object.values(person));

Output:

["John", 25]

3. Object.entries()

Returns key-value pairs as arrays.

console.log(Object.entries(person));

Output:

[
["name", "John"],
["age", 25]
]

4. Object.assign()

Copies properties from one object to another.

const obj1 = { a: 1 };
const obj2 = { b: 2 };

const result = Object.assign({}, obj1, obj2);

console.log(result);

Output:

{ a: 1, b: 2 }

5. Object.freeze()

Prevents modification.

const car = {
brand: "BMW"
};

Object.freeze(car);

car.brand = "Audi";

console.log(car.brand);

Output:

BMW

6. Object.seal()

Allows updating existing properties but prevents adding/removing.

const user = {
name: "John"
};

Object.seal(user);

user.name = "Sam"; // allowed
user.age = 30; // not allowed

console.log(user);

7. Object.hasOwn()

Checks if property exists.

const person = {
name: "John"
};

console.log(Object.hasOwn(person, "name"));

Output:

true

8. Object.create()

Creates a new object using another object as prototype.

const animal = {
sound: "Bark"
};

const dog = Object.create(animal);

console.log(dog.sound);

9. Object.fromEntries()

Converts array to object.

const arr = [
["name", "John"],
["age", 25]
];

console.log(Object.fromEntries(arr));

Output:

{
name: "John",
age: 25
}

10. Object.is()

Compares two values.

console.log(Object.is(10, 10));

Output:

true

Looping Through Objects

Using for...in

const person = {
name: "John",
age: 25
};

for (let key in person) {
console.log(key, person[key]);
}

Object Destructuring

const person = {
name: "John",
age: 25
};

const { name, age } = person;

console.log(name);
console.log(age);

Spread Operator with Objects

const obj1 = {
a: 1
};

const obj2 = {
...obj1,
b: 2
};

console.log(obj2);

Shallow Copy vs Reference

Reference Copy

const obj1 = {
name: "John"
};

const obj2 = obj1;

obj2.name = "Sam";

console.log(obj1.name);

Output:

Sam

Shallow Copy

const obj1 = {
name: "John"
};

const obj2 = { ...obj1 };

obj2.name = "Sam";

console.log(obj1.name);

Output:

John

Real-World Example

const employee = {
id: 101,
name: "David",
department: "QA",
skills: ["JavaScript", "Playwright"],

displayInfo() {
console.log(`${this.name} works in ${this.department}`);
}
};

employee.displayInfo();

Common Interview Questions

Difference Between Object and Array

ObjectArray
Stores key-value pairsStores ordered values
Uses keysUses indexes
{}[]

Difference Between == and Object.is()

console.log(NaN == NaN); // false
console.log(Object.is(NaN, NaN)); // true

Practice Programs

1. Count Object Properties

const user = {
name: "John",
age: 25,
city: "NY"
};

console.log(Object.keys(user).length);

2. Merge Two Objects

const a = { x: 1 };
const b = { y: 2 };

const c = { ...a, ...b };

console.log(c);

3. Convert Object to Array

const person = {
name: "John",
age: 25
};

console.log(Object.entries(person));

Summary

JavaScript objects are used to:

  • Store structured data
  • Create reusable methods
  • Represent real-world entities
  • Manage application state

Most commonly used object methods:

  • Object.keys()
  • Object.values()
  • Object.entries()
  • Object.assign()
  • Object.freeze()
  • Object.seal()
  • Object.hasOwn()

10 JavaScript Object Programs with Solutions


1. Count Number of Properties in an Object

Problem

Find total number of keys in an object.

Solution

const user = {
name: "John",
age: 25,
city: "New York"
};

const count = Object.keys(user).length;

console.log(count);

Output

3

2. Iterate Through Object Properties

Problem

Print all keys and values from an object.

Solution

const student = {
name: "Sam",
marks: 90,
grade: "A"
};

for (let key in student) {
console.log(key + " : " + student[key]);
}

Output

name : Sam
marks : 90
grade : A

3. Merge Two Objects

Problem

Combine two objects into one.

Solution

const obj1 = {
a: 1,
b: 2
};

const obj2 = {
c: 3,
d: 4
};

const merged = { ...obj1, ...obj2 };

console.log(merged);

Output

{
a: 1,
b: 2,
c: 3,
d: 4
}

4. Check if Property Exists

Problem

Check whether a key exists in object.

Solution

const employee = {
id: 101,
name: "David"
};

console.log("name" in employee);
console.log("salary" in employee);

Output

true
false

5. Remove Property from Object

Problem

Delete a property from object.

Solution

const car = {
brand: "BMW",
color: "Black"
};

delete car.color;

console.log(car);

Output

{
brand: "BMW"
}

6. Convert Object to Array

Problem

Convert object into array of key-value pairs.

Solution

const person = {
name: "John",
age: 30
};

const result = Object.entries(person);

console.log(result);

Output

[
["name", "John"],
["age", 30]
]

7. Find Sum of Object Values

Problem

Calculate sum of numeric values in object.

Solution

const marks = {
math: 90,
science: 80,
english: 85
};

let sum = 0;

for (let key in marks) {
sum += marks[key];
}

console.log(sum);

Output

255

8. Clone an Object

Problem

Create copy of object without affecting original.

Solution

const original = {
name: "Alex",
age: 28
};

const copy = { ...original };

copy.name = "Sam";

console.log(original);
console.log(copy);

Output

{ name: "Alex", age: 28 }

{ name: "Sam", age: 28 }

9. Freeze an Object

Problem

Prevent object modification.

Solution

const user = {
name: "John"
};

Object.freeze(user);

user.name = "Sam";

console.log(user.name);

Output

John

10. Nested Object Access

Problem

Access values inside nested objects.

Solution

const company = {
name: "TechSoft",
employee: {
id: 101,
details: {
name: "David",
role: "QA Engineer"
}
}
};

console.log(company.employee.details.name);
console.log(company.employee.details.role);

Output

David
QA Engineer

Bonus Program โ€” Object Destructuring

Problem

Extract object properties into variables.

Solution

const user = {
name: "John",
age: 25
};

const { name, age } = user;

console.log(name);
console.log(age);

Output

John
25

Concepts Covered

These programs cover:

  • Object creation
  • Object iteration
  • Object methods
  • Nested objects
  • Destructuring
  • Spread operator
  • Property checking
  • Cloning
  • Freezing objects
  • Data transformation

Beginner Interview Programs

1. Find the Employee with the Highest Salary

Scenario

A company stores employee details in an object. Find the employee who has the highest salary.

Input

const employees = {
    emp1: { name: "John", salary: 55000 },
    emp2: { name: "Alice", salary: 72000 },
    emp3: { name: "David", salary: 68000 }
};

Expected Output

Highest Salary Employee:
Alice
Salary: 72000

2. Count Product Categories

Scenario

An online shopping website stores products with categories. Count how many products belong to each category.

Input

const products = {
    p1: { category: "Electronics" },
    p2: { category: "Furniture" },
    p3: { category: "Electronics" },
    p4: { category: "Books" },
    p5: { category: "Books" }
};

Expected Output

Electronics : 2
Furniture : 1
Books : 2

3. Merge Student Information

Scenario

Merge two student objects into one object.

Input

const personal = {
    name: "Rahul",
    age: 21
};

const academic = {
    course: "B.Tech",
    marks: 88
};

Expected Output

{
    name: "Rahul",
    age: 21,
    course: "B.Tech",
    marks: 88
}

4. Find Missing Properties

Scenario

Check whether every employee object contains an email property.

Input

const employees = {
    emp1: {
        name: "John",
        email: "john@test.com"
    },
    emp2: {
        name: "Alice"
    },
    emp3: {
        name: "David",
        email: "david@test.com"
    }
};

Expected Output

Employee Missing Email:
Alice

5. Calculate Total Shopping Cart Value

Scenario

Calculate the total bill of all products in the shopping cart.

Input

const cart = {
    item1: {
        name: "Mouse",
        price: 700,
        quantity: 2
    },
    item2: {
        name: "Keyboard",
        price: 1200,
        quantity: 1
    },
    item3: {
        name: "Monitor",
        price: 9500,
        quantity: 1
    }
};

Expected Output

Total Cart Value:
12100

6. Remove Null Values from Object

Scenario

Remove all properties whose value is null.

Input

const user = {
    name: "Deepesh",
    phone: null,
    city: "Bhopal",
    email: null,
    age: 30
};

Expected Output

{
    name: "Deepesh",
    city: "Bhopal",
    age: 30
}

7. Find Duplicate Values

Scenario

Identify duplicate values present in an object.

Input

const students = {
    s1: "A",
    s2: "B",
    s3: "A",
    s4: "C",
    s5: "B"
};

Expected Output

Duplicate Values:
A
B

8. Convert Object into Sorted Array

Scenario

Convert the object values into an array and sort them in ascending order.

Input

const marks = {
    maths: 78,
    science: 91,
    english: 65,
    computer: 99
};

Expected Output

[65, 78, 91, 99]

9. Update Nested Object

Scenario

Update the city of the employee.

Input

const employee = {
    id: 101,
    name: "John",
    address: {
        city: "Delhi",
        state: "Delhi"
    }
};

Task

Update city to Mumbai.

Expected Output

{
    id:101,
    name:"John",
    address:{
        city:"Mumbai",
        state:"Delhi"
    }
}

10. Find Average Salary

Scenario

Calculate the average salary of all employees.

Input

const employees = {
    emp1: { salary: 45000 },
    emp2: { salary: 60000 },
    emp3: { salary: 75000 },
    emp4: { salary: 50000 }
};

Expected Output

Average Salary:
57500

11. Inventory Stock Checker

Scenario

Display all products whose quantity is less than 5.

Input

const inventory = {
    p1: { name: "Laptop", quantity: 3 },
    p2: { name: "Keyboard", quantity: 8 },
    p3: { name: "Mouse", quantity: 2 },
    p4: { name: "Monitor", quantity: 10 }
};

Expected Output

Low Stock Products:
Laptop
Mouse

12. Group Employees by Department

Scenario

Group employees based on department.

Input

const employees = {
    emp1: { name: "John", department: "IT" },
    emp2: { name: "Alice", department: "HR" },
    emp3: { name: "David", department: "IT" },
    emp4: { name: "Emma", department: "Finance" }
};

Expected Output

{
    IT: ["John", "David"],
    HR: ["Alice"],
    Finance: ["Emma"]
}

13. Find the Most Expensive Product

Scenario

Find the product with the highest price.

Input

const products = {
    p1: { name: "Phone", price: 25000 },
    p2: { name: "Laptop", price: 65000 },
    p3: { name: "Watch", price: 12000 }
};

Expected Output

Laptop
65000

14. Count Boolean Values

Scenario

Count how many properties have true and false values.

Input

const permissions = {
    read: true,
    write: false,
    delete: true,
    update: false,
    share: true
};

Expected Output

True : 3
False : 2

15. Reverse Key-Value Pairs

Scenario

Swap the keys and values of an object.

Input

const countryCodes = {
    India: "IN",
    America: "US",
    Japan: "JP"
};

Expected Output

{
    IN: "India",
    US: "America",
    JP: "Japan"
}

16. Find Employees Joined After 2022

Scenario

A company stores employee joining years. Display the employees who joined after 2022.

Input

const employees = {
    emp1: { name: "John", joiningYear: 2021 },
    emp2: { name: "Alice", joiningYear: 2023 },
    emp3: { name: "David", joiningYear: 2024 },
    emp4: { name: "Emma", joiningYear: 2022 }
};

Expected Output

Employees Joined After 2022
---------------------------
Alice
David

17. Update Product Prices by Percentage

Scenario

An e-commerce application increases all product prices by 10%.

Input

const products = {
    p1: { name: "Laptop", price: 50000 },
    p2: { name: "Mouse", price: 800 },
    p3: { name: "Keyboard", price: 1500 }
};

Expected Output

Updated Prices

Laptop : 55000
Mouse : 880
Keyboard : 1650

18. Find Customers with Premium Membership

Scenario

Display only customers whose membership type is Premium.

Input

const customers = {
    c1: { name: "Rahul", membership: "Premium" },
    c2: { name: "Amit", membership: "Regular" },
    c3: { name: "Neha", membership: "Premium" },
    c4: { name: "Priya", membership: "Regular" }
};

Expected Output

Premium Customers

Rahul
Neha

19. Count Active Users

Scenario

Count how many users are active and inactive.

Input

const users = {
    u1: { name: "John", active: true },
    u2: { name: "Alice", active: false },
    u3: { name: "David", active: true },
    u4: { name: "Emma", active: true }
};

Expected Output

Active Users : 3

Inactive Users : 1

20. Find the Oldest Employee

Scenario

Find the employee with the maximum age.

Input

const employees = {
    emp1: { name: "John", age: 30 },
    emp2: { name: "Alice", age: 42 },
    emp3: { name: "David", age: 38 },
    emp4: { name: "Emma", age: 27 }
};

Expected Output

Oldest Employee

Alice

Age : 42

21. Generate Student Report Card

Scenario

Calculate total, average, percentage, and grade for each student.

Input

const students = {
    s1: {
        name: "Rahul",
        maths: 90,
        science: 85,
        english: 88
    },
    s2: {
        name: "Priya",
        maths: 75,
        science: 80,
        english: 70
    }
};

Expected Output

Student : Rahul

Total : 263

Average : 87.67

Grade : A

---------------------

Student : Priya

Total : 225

Average : 75

Grade : B

22. Find Duplicate Email Addresses

Scenario

Identify duplicate email addresses stored in employee records.

Input

const employees = {
    emp1: { email: "john@test.com" },
    emp2: { email: "alice@test.com" },
    emp3: { email: "john@test.com" },
    emp4: { email: "emma@test.com" }
};

Expected Output

Duplicate Emails

john@test.com

23. Sort Employees by Salary

Scenario

Display employees in ascending order of salary.

Input

const employees = {
    emp1: { name: "John", salary: 65000 },
    emp2: { name: "Alice", salary: 48000 },
    emp3: { name: "David", salary: 72000 },
    emp4: { name: "Emma", salary: 55000 }
};

Expected Output

Alice : 48000

Emma : 55000

John : 65000

David : 72000

24. Calculate Total Inventory Value

Scenario

Calculate inventory value using price ร— quantity.

Input

const inventory = {
    p1: { name: "Laptop", price: 50000, quantity: 4 },
    p2: { name: "Mouse", price: 800, quantity: 15 },
    p3: { name: "Keyboard", price: 1500, quantity: 10 }
};

Expected Output

Total Inventory Value

227000

25. Find Employees Working in Multiple Skills

Scenario

Display employees having more than two skills.

Input

const employees = {
    emp1: {
        name: "John",
        skills: ["JavaScript", "React"]
    },
    emp2: {
        name: "Alice",
        skills: ["Java", "Spring", "Docker"]
    },
    emp3: {
        name: "David",
        skills: ["Python", "Django", "AWS", "Docker"]
    }
};

Expected Output

Employees with More Than 2 Skills

Alice

David

26. Create an Employee Directory

Scenario

Convert employee objects into a formatted directory.

Input

const employees = {
    emp1: {
        name: "John",
        phone: "9876543210"
    },
    emp2: {
        name: "Alice",
        phone: "9876500000"
    }
};

Expected Output

Employee Directory

John - 9876543210

Alice - 9876500000

27. Find Products Above Average Price

Scenario

Display products priced above the average price.

Input

const products = {
    p1: { name: "Laptop", price: 60000 },
    p2: { name: "Mouse", price: 900 },
    p3: { name: "Keyboard", price: 2000 },
    p4: { name: "Monitor", price: 18000 }
};

Expected Output

Average Price

20225

Products Above Average

Laptop

Monitor

28. Validate Employee Records

Scenario

Find employees whose records are missing mandatory fields such as name, email, or department.

Input

const employees = {
    emp1: {
        name: "John",
        email: "john@test.com",
        department: "IT"
    },
    emp2: {
        name: "Alice",
        department: "HR"
    },
    emp3: {
        email: "david@test.com",
        department: "Finance"
    }
};

Expected Output

Invalid Records

Alice : Missing Email

Employee 3 : Missing Name

29. Compare Two Objects

Scenario

Compare two employee objects and identify differing properties.

Input

const employee1 = {
    id: 101,
    name: "John",
    salary: 50000
};

const employee2 = {
    id: 101,
    name: "John",
    salary: 60000
};

Expected Output

Different Property

salary

Employee1 : 50000

Employee2 : 60000

30. Build a Sales Dashboard

Scenario

Calculate sales statistics for different regions.

Input

const sales = {
    north: 250000,
    south: 180000,
    east: 320000,
    west: 210000
};

Expected Output

Total Sales : 960000

Average Sales : 240000

Highest Sales : East (320000)

Lowest Sales : South (180000)

JavaScript Array Methods and Programs

An array is a collection of elements stored in a single variable.

let fruits = ["apple", "banana", "mango"];

๐Ÿ”น Categories of Array Methods

To make things easier, weโ€™ll group methods into:

  1. Basic / Access Methods
  2. Add / Remove Elements
  3. Iteration Methods
  4. Transformation Methods
  5. Search / Find Methods
  6. Utility Methods

๐Ÿ”น 1. Basic / Access Methods

โœ… length

Returns number of elements

let arr = [1, 2, 3];
console.log(arr.length); // 3

โœ… toString()

Converts array to string

let arr = [1, 2, 3];
console.log(arr.toString()); // "1,2,3"

โœ… at()

Access element using index (supports negative index)

let arr = [10, 20, 30];
console.log(arr.at(-1)); // 30

๐Ÿ”น 2. Add / Remove Elements

โœ… push()

Adds element at end

let arr = [1, 2];
arr.push(3); // [1,2,3]

โœ… pop()

Removes last element

arr.pop(); // removes 3

โœ… unshift()

Adds element at beginning

arr.unshift(0); // [0,1,2]

โœ… shift()

Removes first element

arr.shift(); // removes 0

โœ… splice()

Add/remove elements at specific index

let arr = [1, 2, 3, 4];
arr.splice(1, 2); // removes 2,3 โ†’ [1,4]

๐Ÿ”น 3. Iteration Methods

โœ… forEach()

Executes function for each element

arr.forEach((item) => console.log(item));

โœ… map()

Returns new array after transformation

let nums = [1, 2, 3];
let doubled = nums.map(n => n * 2);
// [2,4,6]

โœ… filter()

Returns elements that match condition

let nums = [1, 2, 3, 4];
let even = nums.filter(n => n % 2 === 0);
// [2,4]

โœ… reduce()

Reduces array to single value

let nums = [1, 2, 3];
let sum = nums.reduce((acc, n) => acc + n, 0);
// 6

๐Ÿ”น 4. Transformation Methods

โœ… concat()

Merges arrays

let a = [1,2];
let b = [3,4];
let result = a.concat(b); // [1,2,3,4]

โœ… slice()

Returns shallow copy

let arr = [1,2,3,4];
arr.slice(1,3); // [2,3]

โœ… flat()

Flattens nested arrays

let arr = [1, [2, [3]]];
arr.flat(2); // [1,2,3]

๐Ÿ”น 5. Search / Find Methods

โœ… indexOf()

Returns first index

let arr = [10, 20, 30];
arr.indexOf(20); // 1

โœ… includes()

Checks existence

arr.includes(30); // true

โœ… find()

Returns first matching element

let users = [{id:1}, {id:2}];
let user = users.find(u => u.id === 2);

โœ… findIndex()

Returns index of matching element

users.findIndex(u => u.id === 2); // 1

๐Ÿ”น 6. Utility Methods

โœ… sort()

Sorts array (mutates original)

let arr = [3,1,2];
arr.sort(); // [1,2,3]

โš ๏ธ For numbers:

arr.sort((a,b) => a - b);

โœ… reverse()

Reverses array

arr.reverse();

โœ… join()

Converts to string with separator

let arr = ["a", "b", "c"];
arr.join("-"); // "a-b-c"

15 JavaScript Array Programs with Solutions


1. Find Largest Number in Array

Solution

const numbers = [10, 45, 2, 99, 23];

const largest = Math.max(...numbers);

console.log(largest);

Output

99

2. Find Smallest Number in Array

Solution

const numbers = [10, 45, 2, 99, 23];

const smallest = Math.min(...numbers);

console.log(smallest);

Output

2

3. Sum of Array Elements

Solution

const arr = [1, 2, 3, 4, 5];

const sum = arr.reduce((total, num) => total + num, 0);

console.log(sum);

Output

15

4. Find Even Numbers

Solution

const numbers = [1, 2, 3, 4, 5, 6];

const even = numbers.filter(num => num % 2 === 0);

console.log(even);

Output

[2, 4, 6]

5. Find Odd Numbers

Solution

const numbers = [1, 2, 3, 4, 5, 6];

const odd = numbers.filter(num => num % 2 !== 0);

console.log(odd);

Output

[1, 3, 5]

6. Reverse an Array

Solution

const arr = [1, 2, 3, 4, 5];

const reversed = arr.reverse();

console.log(reversed);

Output

[5, 4, 3, 2, 1]

7. Remove Duplicate Elements

Solution

const arr = [1, 2, 2, 3, 4, 4, 5];

const unique = [...new Set(arr)];

console.log(unique);

Output

[1, 2, 3, 4, 5]

8. Sort Array in Ascending Order

Solution

const numbers = [40, 5, 100, 25];

numbers.sort((a, b) => a - b);

console.log(numbers);

Output

[5, 25, 40, 100]

9. Sort Array in Descending Order

Solution

const numbers = [40, 5, 100, 25];

numbers.sort((a, b) => b - a);

console.log(numbers);

Output

[100, 40, 25, 5]

10. Find Maximum and Minimum Together

Solution

const arr = [10, 20, 5, 90, 30];

const max = Math.max(...arr);
const min = Math.min(...arr);

console.log("Max:", max);
console.log("Min:", min);

Output

Max: 90
Min: 5

11. Merge Two Arrays

Solution

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

const merged = [...arr1, ...arr2];

console.log(merged);

Output

[1, 2, 3, 4, 5, 6]

12. Check if Element Exists

Solution

const fruits = ["apple", "banana", "mango"];

console.log(fruits.includes("banana"));
console.log(fruits.includes("orange"));

Output

true
false

13. Find Index of Element

Solution

const numbers = [10, 20, 30, 40];

const index = numbers.indexOf(30);

console.log(index);

Output

2

14. Convert Array to String

Solution

const fruits = ["apple", "banana", "mango"];

const result = fruits.join(", ");

console.log(result);

Output

apple, banana, mango

15. Find Second Largest Number

Solution

const arr = [10, 50, 20, 80, 60];

const sorted = [...arr].sort((a, b) => b - a);

console.log(sorted[1]);

Output

60

Bonus Program โ€” Flatten Nested Array

Solution

const arr = [1, [2, 3], [4, [5, 6]]];

const flatArray = arr.flat(2);

console.log(flatArray);

Output

[1, 2, 3, 4, 5, 6]

Topics Covered

These programs cover:

  • map()
  • filter()
  • reduce()
  • sort()
  • includes()
  • indexOf()
  • join()
  • Spread operator
  • Set
  • Array manipulation
  • Searching
  • Sorting
  • Flattening arrays

Playwright Interview Questions & Answers

๐ŸŸข 1. What is Playwright?

Answer:
Playwright is an open-source automation framework developed by Microsoft for end-to-end testing of web applications.

Key Features:

  • Cross-browser support (Chromium, Firefox, WebKit)
  • Auto-waiting
  • Headless & headed execution
  • Parallel execution
  • Network interception

๐ŸŸข 2. Why Playwright over Selenium?

Answer:

FeaturePlaywrightSelenium
Auto-waitโœ… Built-inโŒ Manual
SpeedFasterSlower
Multi-tabEasyComplex
Network mockingBuilt-inLimited
Modern supportYesLimited

๐ŸŸข 3. How to install Playwright?

Answer:

npm init playwright@latest

๐ŸŸข 4. Basic Test Example

import { test, expect } from '@playwright/test';test('Google search test', async ({ page }) => {
await page.goto('https://google.com');
await page.fill('input[name="q"]', 'Playwright');
await page.press('input[name="q"]', 'Enter');
await expect(page).toHaveTitle(/Playwright/);
});

๐ŸŸก 5. What is Auto-Waiting?

Answer:
Playwright automatically waits for:

  • Elements to be visible
  • Elements to be stable
  • Network to be idle

Example:

await page.click('#submit'); // waits automatically

๐ŸŸก 6. What are Locators?

Answer:
Locators are used to find elements.

page.locator('#id');
page.locator('.class');
page.getByText('Login');
page.getByRole('button', { name: 'Submit' });

๐ŸŸก 7. Difference between locator() and page.$()

Answer:

  • locator() โ†’ Auto-wait + retry
  • page.$() โ†’ Returns immediately (not reliable)

๐ŸŸก 8. How to handle dropdowns?

await page.selectOption('#dropdown', 'value1');

๐ŸŸก 9. Handling checkboxes

await page.check('#checkbox');
await page.uncheck('#checkbox');

๐ŸŸก 10. Handling alerts

page.on('dialog', async dialog => {
await dialog.accept();
});

๐Ÿ”ต 11. How to handle multiple tabs?

const [newPage] = await Promise.all([
context.waitForEvent('page'),
page.click('#openTab')
]);await newPage.waitForLoadState();

๐Ÿ”ต 12. File upload

await page.setInputFiles('#fileInput', 'test.pdf');

๐Ÿ”ต 13. File download

const [download] = await Promise.all([
page.waitForEvent('download'),
page.click('#downloadBtn')
]);await download.saveAs('file.pdf');

๐Ÿ”ต 14. What is Page Object Model (POM)?

Answer:
Design pattern to separate UI and test logic.

Example:

export class LoginPage {
constructor(private page) {} async login(username, password) {
await this.page.fill('#user', username);
await this.page.fill('#pass', password);
await this.page.click('#login');
}
}

๐Ÿ”ต 15. API Testing in Playwright

import { request } from '@playwright/test';test('API Test', async () => {
const apiContext = await request.newContext();
const response = await apiContext.get('/api/users');
console.log(await response.json());
});

๐Ÿ”ด 16. How to handle authentication?

test.use({ storageState: 'auth.json' });

Save session:

await page.context().storageState({ path: 'auth.json' });

๐Ÿ”ด 17. Parallel Execution

npx playwright test --workers=4

๐Ÿ”ด 18. Retry Failed Tests

// playwright.config.ts
retries: 2

๐Ÿ”ด 19. How to handle dynamic elements?

await page.locator('//button[text()="Submit"]').click();

Use:

  • XPath
  • contains()
  • text-based locators

๐Ÿ”ด 20. Network Interception

await page.route('**/api/users', route => {
route.fulfill({
status: 200,
body: JSON.stringify({ name: 'Mock User' })
});
});

๐Ÿง  Advanced Scenario-Based Questions


๐Ÿ”ฅ 21. Banking App Login + OTP

Solution Approach:

  • Mock OTP API
  • Use API interception
await page.route('**/otp', route => {
route.fulfill({ body: JSON.stringify({ otp: '123456' }) });
});

๐Ÿ”ฅ 22. E-commerce Add to Cart Flow

await page.click('text=Add to Cart');
await expect(page.locator('#cart')).toContainText('1 item');

๐Ÿ”ฅ 23. Handling Flaky Tests

Best Practices:

  • Use locators instead of selectors
  • Avoid hard waits
  • Use waitForLoadState()

๐Ÿ”ฅ 24. Multi-user Session (Admin + User)

const adminContext = await browser.newContext();
const userContext = await browser.newContext();const adminPage = await adminContext.newPage();
const userPage = await userContext.newPage();

๐Ÿ”ฅ 25. CI/CD Integration

Use:

  • GitHub Actions
  • Jenkins

Example:

- name: Run Playwright Tests
run: npx playwright test

26. What is Browser Context in Playwright?

Answer:
A Browser Context is an isolated session (like an incognito window).

Why important?

  • Test isolation
  • Multi-user testing
  • No shared cookies/session
const context = await browser.newContext();
const page = await context.newPage();

๐Ÿ‘‰ Think: One browser โ†’ multiple contexts โ†’ multiple users


๐Ÿ”ด 27. Difference between Browser, Context, and Page

ComponentDescription
BrowserActual browser instance
ContextIsolated session
PageTab inside context

๐Ÿ”ด 28. How to reuse login session across tests?

Answer:
Use storage state

// Save session
await context.storageState({ path: 'auth.json' });// Reuse session
test.use({ storageState: 'auth.json' });

๐Ÿ”ด 29. How to handle iFrames?

const frame = page.frameLocator('#frameId');
await frame.locator('#input').fill('Hello');

๐Ÿ”ด 30. Shadow DOM handling

await page.locator('css=custom-element >> text=Submit').click();

๐Ÿ”ด 31. How to debug Playwright tests?

Answer:

Run in debug mode:

npx playwright test --debug

Use:

await page.pause();

๐Ÿ”ด 32. Trace Viewer in Playwright

Answer:
Playwright provides a trace viewer for debugging failures.

npx playwright show-trace trace.zip

๐Ÿ”ด 33. How to capture screenshots?

await page.screenshot({ path: 'screenshot.png' });

Full page:

await page.screenshot({ path: 'full.png', fullPage: true });

๐Ÿ”ด 34. How to record videos?

const context = await browser.newContext({
recordVideo: { dir: 'videos/' }
});

๐Ÿ”ด 35. Handling dynamic waits (best approach)

Avoid:

await page.waitForTimeout(5000); โŒ

Use:

await page.waitForSelector('#element'); โœ…

๐Ÿ”ด 36. Soft Assertions in Playwright

import { expect } from '@playwright/test';await expect.soft(page.locator('#status')).toHaveText('Success');

๐Ÿ”ด 37. Hard vs Soft Assertions

TypeBehavior
HardStops execution
SoftContinues execution

๐Ÿ”ด 38. How to run specific test file?

npx playwright test login.spec.ts

๐Ÿ”ด 39. Run tests in headed mode

npx playwright test --headed

๐Ÿ”ด 40. Environment configuration

// playwright.config.ts
use: {
baseURL: 'https://staging.example.com'
}

Usage:

await page.goto('/');

๐Ÿง  Real-Time Scenario Questions (Very Important)


๐Ÿ”ฅ 41. Scenario: Element is visible but click fails

Possible reasons:

  • Overlay present
  • Element not stable
  • Animation

Solution:

await page.locator('#btn').click({ force: true });

Better:

await expect(locator).toBeVisible();
await locator.click();

๐Ÿ”ฅ 42. Scenario: Test passes locally but fails in CI

Reasons:

  • Timing issues
  • Environment difference
  • Headless issues

Fix:

  • Use proper waits
  • Enable retries
  • Use trace viewer

๐Ÿ”ฅ 43. Scenario: Handling infinite scrolling

await page.evaluate(() => window.scrollBy(0, window.innerHeight));

Loop until element appears:

while (!(await page.locator('#item').isVisible())) {
await page.mouse.wheel(0, 1000);
}

๐Ÿ”ฅ 44. Scenario: Validate table data

const rows = page.locator('table tr');const count = await rows.count();for (let i = 0; i < count; i++) {
const text = await rows.nth(i).textContent();
console.log(text);
}

๐Ÿ”ฅ 45. Scenario: Handling date picker

await page.click('#date');
await page.click('text=25');

๐Ÿ”ฅ 46. Scenario: Handling authentication popup

await page.goto('https://user:pass@example.com');

๐Ÿ”ฅ 47. Scenario: Drag and Drop

await page.dragAndDrop('#source', '#target');

๐Ÿ”ฅ 48. Scenario: Handling file download validation

const path = await download.path();
expect(path).toContain('file');

๐Ÿ”ฅ 49. Scenario: Validate API response + UI

const response = await page.waitForResponse('**/api/data');
const data = await response.json();expect(data.name).toBe('Test');

๐Ÿ”ฅ 50. Scenario: Retry only failed tests

npx playwright test --retries=2

๐ŸŽฏ Advanced Framework Design Questions


๐Ÿ”ท 51. How do you design a scalable Playwright framework?

Answer:

Structure:

tests/
pages/
utils/
fixtures/
config/

Best practices:

  • Use POM
  • Use fixtures
  • Use environment configs
  • Separate test data

๐Ÿ”ท 52. What are fixtures in Playwright?

test('example', async ({ page }) => {
// page is a fixture
});

Custom fixture:

test.extend({
loginPage: async ({ page }, use) => {
await use(new LoginPage(page));
}
});

๐Ÿ”ท 53. Data-driven testing

const users = ['user1', 'user2'];for (const user of users) {
test(`login test ${user}`, async ({ page }) => {
console.log(user);
});
}

๐Ÿ”ท 54. Parallel vs Serial execution

test.describe.configure({ mode: 'parallel' });

Serial:

test.describe.configure({ mode: 'serial' });

๐Ÿ”ท 55. Tags in Playwright

test('smoke test @smoke', async () => {});

Run:

npx playwright test -g "@smoke"

โš ๏ธ Tricky Interview Questions


โ“ 56. Why Playwright is faster?

  • WebSocket communication
  • No Selenium WebDriver layer
  • Direct browser control

โ“ 57. Can Playwright handle multiple browsers at once?

Yes:

projects: [
{ name: 'Chromium' },
{ name: 'Firefox' },
{ name: 'WebKit' }
]

โ“ 58. What happens if locator matches multiple elements?

  • Playwright throws strict mode error

Fix:

locator.first()
locator.nth(0)

โ“ 59. Difference between waitForSelector and locator wait

  • locator โ†’ auto-wait
  • waitForSelector โ†’ manual wait

โ“ 60. How do you reduce flakiness?

โœ” Use locators
โœ” Avoid hard waits
โœ” Use retries
โœ” Mock APIs
โœ” Stable selectors

๐Ÿ”ฅ 61. Scenario: Banking App โ€“ Secure Login with Token

Problem:
Login uses JWT token instead of UI login.

Solution:

  • Call API
  • Inject token into storage
const requestContext = await request.newContext();const response = await requestContext.post('/api/login', {
data: { username: 'user', password: 'pass' }
});const body = await response.json();await context.addCookies([{
name: 'token',
value: body.token,
domain: 'example.com',
path: '/'
}]);

๐Ÿ”ฅ 62. Scenario: Bypass CAPTCHA (Important Interview Question)

Reality:
Playwright cannot solve CAPTCHA

Best Practice:

  • Disable CAPTCHA in test environment
  • Mock API

๐Ÿ”ฅ 63. Scenario: Handling WebSocket Testing

page.on('websocket', ws => {
ws.on('framereceived', frame => {
console.log(frame.payload);
});
});

๐Ÿ”ฅ 64. Scenario: Test microservices-based UI

Approach:

  • Mock dependent APIs
  • Validate UI independently
await page.route('**/orders', route => {
route.fulfill({ body: JSON.stringify({ orders: [] }) });
});

๐Ÿ”ฅ 65. Scenario: Handling flaky network

await page.route('**/*', route => {
route.continue({ timeout: 10000 });
});

๐Ÿ”ฅ 66. Scenario: Validate PDF download content

const buffer = await download.createReadStream();

Then parse using Node libraries


๐Ÿ”ฅ 67. Scenario: Multi-language testing

await page.goto('/?lang=fr');
await expect(page.locator('h1')).toHaveText('Bonjour');

๐Ÿ”ฅ 68. Scenario: Geo-location testing

const context = await browser.newContext({
geolocation: { latitude: 28.6139, longitude: 77.2090 },
permissions: ['geolocation']
});

๐Ÿ”ฅ 69. Scenario: Timezone testing

const context = await browser.newContext({
timezoneId: 'Asia/Kolkata'
});

๐Ÿ”ฅ 70. Scenario: Testing notifications

await context.grantPermissions(['notifications']);

๐Ÿ—๏ธ Framework Architecture Questions (Very Important)


๐Ÿ”ท 71. How to design enterprise-level Playwright framework?

Layers:

1. Tests
2. Page Objects
3. API Layer
4. Utilities
5. Test Data
6. Config

Key Additions:

  • Logging
  • Reporting
  • Retry strategy
  • Test tagging

๐Ÿ”ท 72. How to implement reusable utilities?

Example:

export async function login(page, user) {
await page.fill('#user', user);
}

๐Ÿ”ท 73. Centralized test data management

Use:

  • JSON files
  • Environment variables
const data = require('./testData.json');

๐Ÿ”ท 74. Logging in Playwright

Use console or integrate with tools like:

  • Winston
  • Custom logger

๐Ÿ”ท 75. Reporting tools

Playwright supports:

  • HTML report
  • Allure report
npx playwright show-report

โš™๏ธ CI/CD + DevOps Questions


๐Ÿ”ง 76. How to run Playwright in CI/CD?

Using GitHub Actions:

name: Playwright Testson: [push]jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm install
- run: npx playwright install
- run: npx playwright test

๐Ÿ”ง 77. How to run tests in Docker?

FROM mcr.microsoft.com/playwright:v1.40.0
WORKDIR /app
COPY . .
RUN npm install
CMD ["npx", "playwright", "test"]

๐Ÿ”ง 78. Headless vs Headed execution

ModeUse Case
HeadlessCI/CD
HeadedDebugging

๐Ÿ”ง 79. How to reduce execution time?

โœ” Parallel execution
โœ” API mocking
โœ” Reuse authentication
โœ” Run only changed tests


๐Ÿ”ง 80. Sharding tests

npx playwright test --shard=1/3

๐Ÿ” Debugging & Optimization


๐Ÿ› ๏ธ 81. How to debug failed tests in CI?

  • Use trace viewer
  • Capture video
  • Capture logs

๐Ÿ› ๏ธ 82. Memory leak issues

Cause:

  • Not closing contexts
await context.close();

๐Ÿ› ๏ธ 83. Handling slow tests

  • Remove unnecessary steps
  • Use API setup instead of UI
  • Use fixtures

๐Ÿ› ๏ธ 84. Test retries strategy

retries: process.env.CI ? 2 : 0

๐Ÿ› ๏ธ 85. Fail fast strategy

maxFailures: 5

๐Ÿ” Security Testing (Important)


๐Ÿ”’ 86. How to test authentication security?

  • Validate token expiration
  • Test invalid login

๐Ÿ”’ 87. How to test authorization?

  • Admin vs user roles
expect(await page.isVisible('#adminPanel')).toBeFalsy();

๐Ÿ”’ 88. Sensitive data handling

  • Avoid hardcoding credentials
  • Use env variables

๐Ÿ”’ 89. HTTPS validation

expect(page.url()).toContain('https');

๐Ÿ”’ 90. Cookie testing

const cookies = await context.cookies();

๐ŸŽฏ Expert-Level Tricky Questions


โ“ 91. Difference between browser.newPage() and context.newPage()

  • browser.newPage() โ†’ new default context
  • context.newPage() โ†’ controlled session

โ“ 92. Why avoid waitForTimeout()?

  • Causes flaky tests
  • Slows execution

โ“ 93. How Playwright handles race conditions?

  • Auto-waiting
  • Event-based execution

โ“ 94. Can Playwright test backend?

Yes:

  • API testing
  • Contract testing

โ“ 95. How to test file upload without UI?

await request.post('/upload', {
multipart: { file: fs.createReadStream('file.txt') }
});

โ“ 96. What is test isolation?

Each test runs independently with:

  • New context
  • Clean state

โ“ 97. How to handle feature flags?

await page.goto('/?feature=true');

โ“ 98. How to test performance?

Basic:

const start = Date.now();
await page.goto('/');
console.log(Date.now() - start);

โ“ 99. Can Playwright run without UI?

Yes โ†’ headless mode


โ“ 100. When NOT to use Playwright?

  • Desktop app testing
  • Heavy performance testing (use JMeter)

Real-World Enterprise Scenarios in Playwright


๐Ÿฆ 1. Banking App โ€“ End-to-End Payment Flow

๐ŸŽฏ Problem

User logs in โ†’ adds beneficiary โ†’ transfers money โ†’ verifies transaction.

โœ… Approach

  • Reuse login session
  • Mock OTP service
  • Validate UI + API

๐Ÿ’ป Example

test('Fund transfer flow', async ({ page }) => {
await page.goto('/dashboard'); await page.click('text=Transfer');
await page.fill('#account', '123456');
await page.fill('#amount', '5000');
await page.click('#submit'); await expect(page.locator('#status')).toHaveText('Success');
});

๐Ÿง  Best Practices

  • Avoid real payment โ†’ mock API
  • Validate transaction via backend API
  • Use test accounts

๐Ÿ›’ 2. E-Commerce โ€“ Add to Cart + Checkout

๐ŸŽฏ Problem

User adds product โ†’ applies coupon โ†’ completes checkout.

โœ… Approach

  • Use stable locators
  • Mock payment gateway
  • Validate price calculation

๐Ÿ’ป Example

await page.click('text=Add to Cart');
await page.fill('#coupon', 'DISCOUNT10');
await page.click('#apply');await expect(page.locator('#total')).toContainText('900');

๐Ÿง  Best Practices

  • Mock payment APIs
  • Validate cart via API
  • Use data-driven tests

๐Ÿ‘ฅ 3. Multi-User Role Testing (Admin vs User)

๐ŸŽฏ Problem

Admin creates data โ†’ user verifies it.

โœ… Approach

  • Use multiple browser contexts

๐Ÿ’ป Example

const adminContext = await browser.newContext();
const userContext = await browser.newContext();const adminPage = await adminContext.newPage();
const userPage = await userContext.newPage();await adminPage.goto('/admin');
await adminPage.click('#createUser');await userPage.goto('/dashboard');

๐Ÿง  Best Practices

  • Keep sessions isolated
  • Avoid shared cookies

๐Ÿ” 4. Authentication Without UI (Token-Based Login)

๐ŸŽฏ Problem

Login via API instead of UI (faster + stable)

โœ… Approach

  • Call login API
  • Inject token

๐Ÿ’ป Example

const response = await request.post('/api/login', {
data: { username: 'user', password: 'pass' }
});const { token } = await response.json();await context.addCookies([{ name: 'token', value: token }]);

๐Ÿง  Best Practices

  • Avoid UI login in every test
  • Store auth state

๐ŸŒ 5. Microservices UI โ€“ API Mocking

๐ŸŽฏ Problem

Frontend depends on unstable backend services

โœ… Approach

  • Mock APIs

๐Ÿ’ป Example

await page.route('**/orders', route => {
route.fulfill({
body: JSON.stringify({ orders: [] })
});
});

๐Ÿง  Best Practices

  • Test UI independently
  • Simulate edge cases

๐Ÿ“Š 6. Data Validation Between UI and API

๐ŸŽฏ Problem

Ensure UI data matches backend response

๐Ÿ’ป Example

const response = await page.waitForResponse('**/api/user');
const apiData = await response.json();const uiText = await page.locator('#username').textContent();expect(uiText).toBe(apiData.name);

๐Ÿง  Best Practices

  • Validate critical fields
  • Avoid over-validating

๐Ÿ“ฑ 7. Mobile Device Testing

๐ŸŽฏ Problem

Test responsive UI

๐Ÿ’ป Example

import { devices } from '@playwright/test';test.use(devices['iPhone 13']);

๐Ÿง  Best Practices

  • Test key flows only
  • Avoid duplicating all tests

๐Ÿ“ฆ 8. File Upload & Download Validation

๐ŸŽฏ Problem

Upload invoice โ†’ download receipt โ†’ verify

๐Ÿ’ป Example

await page.setInputFiles('#upload', 'invoice.pdf');const [download] = await Promise.all([
page.waitForEvent('download'),
page.click('#download')
]);

๐Ÿง  Best Practices

  • Validate file name
  • Validate file content (if critical)

๐Ÿ” 9. Handling Retry & Flaky Tests

๐ŸŽฏ Problem

Tests fail intermittently in CI

โœ… Fix

retries: 2

๐Ÿง  Best Practices

  • Fix root cause (donโ€™t rely only on retry)
  • Use trace viewer

๐Ÿงพ 10. Infinite Scroll / Lazy Loading

๐ŸŽฏ Problem

Data loads on scroll

๐Ÿ’ป Example

while (!(await page.locator('#item').isVisible())) {
await page.mouse.wheel(0, 1000);
}

๐Ÿง  Best Practices

  • Add exit condition
  • Avoid infinite loops

๐Ÿงช 11. Feature Flag Testing

๐ŸŽฏ Problem

Feature enabled only for some users

๐Ÿ’ป Example

await page.goto('/?feature=true');

๐Ÿง  Best Practices

  • Test both ON and OFF states

๐ŸŒ 12. Localization Testing

๐ŸŽฏ Problem

App supports multiple languages

๐Ÿ’ป Example

await page.goto('/?lang=hi');
await expect(page.locator('h1')).toHaveText('เคจเคฎเคธเฅเคคเฅ‡');

๐Ÿง  Best Practices

  • Validate key UI texts
  • Avoid full UI comparison

๐Ÿ“ 13. Geo-Location Testing

๐ŸŽฏ Problem

Content varies by location

๐Ÿ’ป Example

await context.setGeolocation({ latitude: 28.61, longitude: 77.20 });

๐Ÿ”„ 14. Background Job Validation

๐ŸŽฏ Problem

Async job updates UI later

๐Ÿ’ป Example

await expect(page.locator('#status')).toHaveText('Completed', { timeout: 10000 });

โš™๏ธ 15. CI/CD Pipeline Execution

๐ŸŽฏ Problem

Run tests on every deployment

๐Ÿ’ป Example

Using Jenkins or GitHub Actions

npx playwright test

๐Ÿ”ฅ 16. Handling CAPTCHA in Enterprise Apps

โ— Reality

Automation tools should not bypass CAPTCHA

โœ… Approach

  • Disable in test env
  • Use mock/stub

๐Ÿง  17. High Data Volume Testing (Tables)

๐ŸŽฏ Problem

Validate large tables

๐Ÿ’ป Example

const rows = await page.locator('table tr');
expect(await rows.count()).toBeGreaterThan(0);

๐Ÿ” 18. Role-Based Access Testing

๐ŸŽฏ Problem

User should not access admin pages

๐Ÿ’ป Example

await page.goto('/admin');
await expect(page).toHaveURL('/unauthorized');

โšก 19. Performance Check (Basic)

๐Ÿ’ป Example

const start = Date.now();
await page.goto('/');
console.log(Date.now() - start);