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

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);

Essential Linux Commands for Git Terminal

📁 1. File & Directory Navigation

1. pwd

Description: Shows the current working directory path.

pwd

2. ls

Description: Lists files and directories.

ls
ls -la # detailed list including hidden files

3. cd

Description: Changes directory.

cd project-folder
cd .. # move up one directory
cd ~ # go to home directory

📂 2. File & Directory Management

4. mkdir

Description: Creates a new directory.

mkdir my-repo

5. rmdir

Description: Removes an empty directory.

rmdir my-repo

6. rm

Description: Deletes files or directories.

rm file.txt
rm -r folder/ # remove directory recursively

7. cp

Description: Copies files or directories.

cp file.txt backup.txt
cp -r folder/ new-folder/

8. mv

Description: Moves or renames files.

mv file.txt newname.txt
mv file.txt folder/

📝 3. File Viewing & Editing

9. cat

Description: Displays file content.

cat README.md

10. less

Description: Views large files page by page.

less README.md

11. nano

Description: Simple terminal text editor.

nano file.txt

12. vim

Description: Advanced text editor.

vim file.txt

🔍 4. Search & Filtering

13. grep

Description: Searches text in files.

grep "function" file.js

14. find

Description: Finds files/directories.

find . -name "index.js"

⚙️ 5. Permissions & Ownership

15. chmod

Description: Changes file permissions.

chmod 755 script.sh

16. chown

Description: Changes file ownership.

chown user:user file.txt

🌐 6. Networking (Useful for Git)

17. ssh

Description: Connects securely to remote servers (used for GitHub SSH).

ssh -T git@github.com

18. curl

Description: Transfers data from URLs.

curl https://api.github.com

🧰 7. Archive & Compression

19. tar

Description: Creates/extracts archives.

tar -cvf project.tar folder/
tar -xvf project.tar

20. zip / unzip

Description: Compresses and extracts zip files.

zip -r project.zip folder/
unzip project.zip

🧪 8. System & Process Commands

21. clear

Description: Clears the terminal screen.

clear

22. history

Description: Shows previously used commands.

history

23. top

Description: Displays running processes.

top

🔄 How These Help in Git Workflow

When working with Git, these Linux commands help you:

  • Navigate to repositories (cd, ls)
  • Create/manage project files (mkdir, rm, cp)
  • Edit code before committing (nano, vim)
  • Inspect changes (cat, less)
  • Search code (grep, find)
  • Handle SSH authentication (ssh)

🚀 Example Git Workflow with Linux Commands

mkdir my-project
cd my-project
git inittouch README.md
nano README.mdgit add .
git commit -m "Initial commit"

JavaScript String Fundamentals

A string in JavaScript is a sequence of characters used to represent text.

✅ Ways to create strings

let str1 = "Hello";
let str2 = 'World';
let str3 = `Hello World`; // Template literal

String Methods

🔹 1. length

Description: Returns the number of characters in a string.

let str = "Hello";
console.log(str.length); // 5

🔹 2. toUpperCase()

Description: Converts all characters to uppercase.

"hello".toUpperCase(); // "HELLO"

🔹 3. toLowerCase()

Description: Converts all characters to lowercase.

"HELLO".toLowerCase(); // "hello"

🔹 4. trim()

Description: Removes whitespace from both ends.

"  hi  ".trim(); // "hi"

🔹 5. trimStart() / trimEnd()

Description: Removes whitespace from start or end only.

"  hi".trimStart(); // "hi"
"hi ".trimEnd(); // "hi"

🔹 6. includes(substring)

Description: Checks if string contains a substring → returns true/false.

"JavaScript".includes("Script"); // true

🔹 7. startsWith()

Description: Checks if string starts with given value.

"Hello".startsWith("He"); // true

🔹 8. endsWith()

Description: Checks if string ends with given value.

"Hello".endsWith("lo"); // true

🔹 9. indexOf()

Description: Returns first index of substring, or -1 if not found.

"Hello".indexOf("l"); // 2

🔹 10. lastIndexOf()

Description: Returns last occurrence index.

"Hello".lastIndexOf("l"); // 3

🔹 11. slice(start, end)

Description: Extracts part of string (supports negative index).

"JavaScript".slice(0, 4); // "Java"
"Hello".slice(-2); // "lo"

🔹 12. substring(start, end)

Description: Similar to slice() but does not accept negative index.

"JavaScript".substring(4, 10); // "Script"

🔹 13. substr(start, length) ⚠️ Deprecated

Description: Extracts substring using length (not recommended now).

"Hello".substr(1, 3); // "ell"

🔹 14. replace(search, value)

Description: Replaces first match.

"Hello World".replace("World", "JS"); // "Hello JS"

🔹 15. replaceAll()

Description: Replaces all occurrences.

"a-b-c".replaceAll("-", ","); // "a,b,c"

🔹 16. split(separator)

Description: Converts string into array.

"a,b,c".split(","); // ["a", "b", "c"]

🔹 17. concat()

Description: Joins two or more strings.

"Hello".concat(" ", "World"); // "Hello World"

🔹 18. charAt(index)

Description: Returns character at given index.

"Hello".charAt(1); // "e"

🔹 19. charCodeAt(index)

Description: Returns Unicode value of character.

"A".charCodeAt(0); // 65

🔹 20. repeat(n)

Description: Repeats string n times.

"Hi ".repeat(3); // "Hi Hi Hi "

🔹 21. padStart(length, char)

Description: Pads string from start.

"5".padStart(3, "0"); // "005"

🔹 22. padEnd(length, char)

Description: Pads string from end.

"5".padEnd(3, "0"); // "500"

🔹 23. match(regex)

Description: Returns matches based on regex.

"abc123".match(/\d+/); // ["123"]

🔹 24. matchAll(regex)

Description: Returns all matches (iterator).

[..."a1b2".matchAll(/\d/g)]; // ["1", "2"]

🔹 25. search(regex)

Description: Returns index of first match.

"hello123".search(/\d/); // 5

🔹 26. localeCompare()

Description: Compares two strings (useful for sorting).

"a".localeCompare("b"); // -1

🔹 27. normalize()

Description: Normalizes Unicode characters.

"é".normalize(); 

🔹 28. valueOf()

Description: Returns primitive string value.

let str = new String("hello");
str.valueOf(); // "hello"

🔹 29. toString()

Description: Converts object to string.

let str = new String("hello");
str.toString(); // "hello"

🔹 30. Template Literals (`)

Description: Allows interpolation and multi-line strings.

let name = "John";
console.log(`Hello ${name}`);

⚡ Quick Categorization

🔍 Search Methods

  • includes(), indexOf(), search()

✂️ Extract Methods

  • slice(), substring(), substr()

🔄 Modify Methods

  • replace(), replaceAll(), trim()

🔧 Utility Methods

  • split(), concat(), repeat()

🔡 Case Methods

  • toUpperCase(), toLowerCase()

🔥 20 JavaScript String Programs (with Solutions)


✅ 1. Reverse a string

let str = "hello";
let reversed = str.split("").reverse().join("");
console.log(reversed);

✅ 2. Check palindrome

let str = "madam";
let result = str === str.split("").reverse().join("");
console.log(result);

✅ 3. Count vowels

let str = "hello";
let count = str.match(/[aeiou]/gi)?.length || 0;
console.log(count);

✅ 4. Count consonants

let str = "hello";
let count = str.match(/[^aeiou]/gi).length;
console.log(count);

✅ 5. Remove spaces

let str = "h e l l o";
console.log(str.replaceAll(" ", ""));

✅ 6. Convert first letter to uppercase

let str = "hello";
console.log(str.charAt(0).toUpperCase() + str.slice(1));

✅ 7. Find longest word

let str = "I love JavaScript programming";
let words = str.split(" ");
let longest = words.reduce((a, b) => a.length > b.length ? a : b);
console.log(longest);

✅ 8. Count words

let str = "Hello world JS";
console.log(str.split(" ").length);

✅ 9. Check substring exists

let str = "JavaScript";
console.log(str.includes("Script"));

✅ 10. Replace all vowels with *

let str = "hello";
console.log(str.replace(/[aeiou]/gi, "*"));

✅ 11. Convert string to array

let str = "hello";
console.log(str.split(""));

✅ 12. Remove duplicate characters

let str = "aabbcc";
let unique = [...new Set(str)].join("");
console.log(unique);

✅ 13. Count character frequency

let str = "hello";
let obj = {};
for (let ch of str) {
obj[ch] = (obj[ch] || 0) + 1;
}
console.log(obj);

✅ 14. Check anagram

let a = "listen";
let b = "silent";let result = a.split("").sort().join("") === b.split("").sort().join("");
console.log(result);

✅ 15. Capitalize each word

let str = "hello world";
let result = str.split(" ").map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
console.log(result);

✅ 16. Extract numbers from string

let str = "abc123xyz";
console.log(str.match(/\d+/)[0]);

✅ 17. Check if string contains only digits

let str = "12345";
console.log(/^\d+$/.test(str));

✅ 18. Repeat string N times

let str = "hi";
console.log(str.repeat(3));

✅ 19. Truncate string

let str = "JavaScript";
console.log(str.slice(0, 4));

✅ 20. Convert string to title case

let str = "javascript is fun";
let result = str.split(" ")
.map(w => w[0].toUpperCase() + w.slice(1))
.join(" ");
console.log(result);

Github Interview Questions And Answers

1. What is GitHub? How is it different from Git?

👉 Answer:

  • Git is a distributed version control system used to track code changes.
  • GitHub is a cloud-based platform that hosts Git repositories and adds collaboration features.

👉 Use Case:
In a team project, developers use Git locally and push code to GitHub for collaboration, reviews, and CI/CD.


2. What is a Repository?

👉 Answer:
A repository (repo) is a storage space for your project that contains code, files, and version history.

👉 Use Case:
You create a repo for a Playwright automation project where all test scripts, configs, and reports are stored.


3. What is the difference between Fork and Clone?

👉 Answer:

  • Fork: Copy of someone else’s repo into your GitHub account.
  • Clone: Copy of a repo to your local machine.

👉 Use Case:

  • Fork: Contributing to open-source.
  • Clone: Working on your team project locally.

4. What is a Branch?

👉 Answer:
A branch is a separate line of development.

👉 Use Case:
You create:

  • main → production code
  • feature/login-test → new feature work

5. What is a Pull Request (PR)?

👉 Answer:
A PR is a request to merge changes from one branch to another.

👉 Use Case:
QA automation engineer raises a PR after adding test cases → Developer reviews → merges into main.


6. What is Merge Conflict?

👉 Answer:
Occurs when Git cannot automatically merge changes.

👉 Use Case:
Two developers modify the same file → conflict → manually resolved before merge.


7. What is GitHub Actions?

👉 Answer:
A CI/CD tool in GitHub used to automate workflows.

👉 Use Case:

  • Run Playwright tests automatically on every PR
  • Deploy app after merge

8. What is .gitignore?

👉 Answer:
A file that specifies which files Git should ignore.

👉 Use Case:
Ignore:

  • node_modules/
  • test-results/
  • .env

9. What is Git Workflow (Branching Strategy)?

👉 Answer:
A process defining how teams use branches.

👉 Common strategies:

  • Git Flow
  • Feature Branch Workflow

👉 Use Case:

  • Create feature branch
  • Push code
  • Raise PR
  • Review → Merge

10. What is Staging in Git?

👉 Answer:
Intermediate area before committing changes.

👉 Commands:

git add .
git commit -m "message"

👉 Use Case:
You selectively add only required files before committing.


11. Difference between Commit and Push?

👉 Answer:

  • Commit: Save changes locally
  • Push: Upload changes to GitHub

👉 Use Case:
You commit multiple times locally → push once after testing.


12. What is Rebase vs Merge?

👉 Answer:

  • Merge: Keeps history (creates merge commit)
  • Rebase: Rewrites history (linear)

👉 Use Case:
Rebase keeps clean commit history before merging feature branch.


13. What is Tag in Git?

👉 Answer:
A tag marks a specific version of code.

👉 Use Case:
Mark releases like:

v1.0
v2.0

14. What is Git Stash?

👉 Answer:
Temporarily saves uncommitted changes.

👉 Use Case:
You are working on a feature but need to switch branches quickly.


15. What is Code Review in GitHub?

👉 Answer:
Process of reviewing code before merging.

👉 Use Case:

  • Developer checks logic
  • QA verifies test coverage
  • Ensures code quality

🔹 Scenario-Based GitHub Interview Questions


16. You pushed wrong code to main branch. What will you do?

👉 Answer:

  • Revert commit:
git revert <commit-id>

OR

  • Reset (if safe):
git reset --hard HEAD~1

👉 Best Practice:
Avoid direct commits to main → use PR workflow.


17. Multiple developers working on same feature. How to manage?

👉 Answer:

  • Use feature branches
  • Regularly pull latest changes
  • Resolve conflicts early

👉 Use Case:
Each dev works on sub-features → merged via PR.


18. How do you handle large files in GitHub?

👉 Answer:
Use Git LFS (Large File Storage).

👉 Use Case:
Store large test data or binaries.


19. How do you secure sensitive data in GitHub?

👉 Answer:

  • Never commit secrets
  • Use GitHub Secrets
  • Use .gitignore

👉 Use Case:
Store API keys in environment variables.


20. Explain CI/CD pipeline using GitHub Actions

👉 Answer:

  1. Code pushed to GitHub
  2. Workflow triggers
  3. Build runs
  4. Tests execute
  5. Deploy

👉 Use Case:
Playwright tests run automatically on every commit.


🔹 Advanced Practical Questions


21. How do you revert a specific file to previous version?

git checkout <commit-id> -- file.js

22. How do you squash commits?

git rebase -i HEAD~3

👉 Combine multiple commits into one.


23. What is Detached HEAD?

👉 Answer:
When you’re not on any branch.

👉 Use Case:
Checking old commit without affecting current branch.


24. How do you delete a branch?

git branch -d branch-name
git push origin --delete branch-name

25. What is Upstream in Git?

👉 Answer:
Reference to original repository (especially in forks).

👉 Use Case:
Keep your fork updated with original repo.


Mock Interview: GitHub (Real Company Style)


🔹 Round 1: Basics + Practical Understanding

❓ Q1: Explain your GitHub workflow in your current project.

👉 Strong Answer:

“We follow a feature branch workflow. Each task starts with a new branch from main. After development, we push code and raise a pull request. CI runs automatically using GitHub Actions. After code review and approvals, we merge into main. Direct commits to main are restricted.”

👉 What interviewer checks:

  • Real experience
  • Collaboration understanding
  • CI/CD awareness

❓ Q2: What happens when you run git push?

👉 Strong Answer:

“It uploads local commits from my machine (using Git) to the remote repository on GitHub, making them available to the team.”

👉 Follow-up trap:
👉 “What if push is rejected?”

✔️ Answer:

“It usually means my branch is behind. I pull the latest changes, resolve conflicts if any, and push again.”


🔹 Round 2: Scenario-Based Questions


❓ Q3: You and another developer changed the same file. Your PR shows conflict. What do you do?

👉 Strong Answer:

“I pull the latest changes from main, resolve conflicts locally, test the code, commit the fix, and push again to update the PR.”

👉 Bonus point:
Mention testing after conflict resolution.


❓ Q4: You accidentally pushed sensitive data (API key) to GitHub. What will you do?

👉 Strong Answer:

“First, I revoke the key immediately. Then I remove it from the repository, rewrite history if needed, and ensure it’s added to .gitignore. Going forward, I store secrets using GitHub Secrets.”

👉 What interviewer checks:

  • Security awareness
  • Real-world handling

❓ Q5: Your teammate’s PR broke the build. What should happen?

👉 Strong Answer:

“The CI pipeline should fail automatically. The PR should not be merged until the issue is fixed. We enforce required checks before merging.”

👉 Extra credit:
Mention branch protection rules.


🔹 Round 3: CI/CD + Automation (Very Important)


❓ Q6: How do you integrate automation tests with GitHub?

👉 Strong Answer:

“We use GitHub Actions to trigger Playwright tests on every PR. The workflow installs dependencies, runs tests, and publishes reports.”

👉 Example flow:

  • PR created
  • Tests run automatically
  • Pass → merge allowed
  • Fail → fix required

❓ Q7: How do you ensure code quality before merging?

👉 Strong Answer:

“We use a combination of:

  • Pull request reviews
  • Automated tests
  • Linting checks
  • CI validation

Only after all checks pass, the PR is merged.”


🔹 Round 4: Advanced Problem Solving


❓ Q8: Your main branch is broken after a merge. What will you do?

👉 Strong Answer:

“I would quickly identify the faulty commit and revert it using git revert. Then fix the issue in a new branch and raise another PR.”

👉 Important:
Avoid rewriting history in shared branches.


❓ Q9: How do you handle multiple environments (dev, staging, prod)?

👉 Strong Answer:

“We use different branches or deployment workflows. For example:

  • develop → dev environment
  • main → production
    CI/CD pipelines deploy automatically based on branch.”

❓ Q10: How do you manage large teams working on the same repo?

👉 Strong Answer:

“We use:

  • Feature branches
  • Clear naming conventions
  • Code owners
  • Mandatory PR reviews
  • CI/CD checks

This ensures smooth collaboration and avoids conflicts.”


🔹 Round 5: Rapid Fire (Quick Checks)


❓ Difference between Fork and Clone?

👉 Fork = copy on GitHub
👉 Clone = copy on local machine


❓ What is HEAD in Git?

👉 Pointer to the current commit/branch


❓ What is Rebase?

👉 Rewrites commit history to make it linear


❓ What is Stash?

👉 Temporarily saves uncommitted changes


❓ What is a Tag?

👉 Marks a release/version


🔹 Real Interview Challenge (Hands-On Thinking)


❓ Q11: Design a GitHub workflow for automation testing.

👉 Strong Answer:

“I would:

  1. Trigger workflow on PR and push
  2. Install dependencies
  3. Run Playwright tests
  4. Generate reports
  5. Upload artifacts
  6. Fail build if tests fail

This ensures only tested code gets merged.”


🔹 Final HR + Practical Question


❓ Q12: Tell me a real problem you faced in GitHub and how you solved it.

👉 Sample Answer:

“We had frequent merge conflicts due to long-running branches. I suggested smaller PRs and frequent rebasing. This reduced conflicts and improved deployment speed.”



Playwright Save Login Session with POM

Here’s a complete, real-world Playwright POM framework showing how to:

  • Login once using beforeAll
  • Share the session across tests
  • Use Page Object Model (POM)
  • Follow best practices for scalability

✅ 1. Project Structure (Recommended)

playwright-project/

├── tests/
│ ├── login.setup.ts # Login once & save session
│ ├── example.spec.ts # Actual test cases

├── pages/
│ ├── LoginPage.ts
│ ├── DashboardPage.ts

├── utils/
│ ├── baseTest.ts # Custom fixture (optional advanced)

├── playwright.config.ts
└── package.json

✅ 2. Login Page (POM)

pages/LoginPage.ts

import { Page } from '@playwright/test';export class LoginPage {
readonly page: Page; constructor(page: Page) {
this.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');
}
}

✅ 3. Dashboard Page (POM)

pages/DashboardPage.ts

import { Page, expect } from '@playwright/test';export class DashboardPage {
readonly page: Page; constructor(page: Page) {
this.page = page;
} async verifyDashboardLoaded() {
await expect(this.page.locator('h1')).toHaveText('Dashboard');
}
}

✅ 4. Login Setup (Runs Once Before All Tests)

👉 This is the key part (beforeAll session handling)

tests/login.setup.ts

import { test as setup } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';setup('Login and save session', async ({ page }) => {
const loginPage = new LoginPage(page); await loginPage.navigate();
await loginPage.login('testuser', 'password123'); // Save session
await page.context().storageState({ path: 'storageState.json' });
});

✅ 5. Playwright Config (Use Stored Session)

playwright.config.ts

import { defineConfig } from '@playwright/test';export default defineConfig({
testDir: './tests', use: {
baseURL: 'https://example.com',
storageState: 'storageState.json', // reuse login session
headless: false
}, projects: [
{
name: 'setup',
testMatch: /login\.setup\.ts/,
},
{
name: 'tests',
dependencies: ['setup'], // ensures login runs first
testMatch: /.*\.spec\.ts/,
},
],
});

✅ 6. Test File (Uses Shared Session)

tests/example.spec.ts

import { test } from '@playwright/test';
import { DashboardPage } from '../pages/DashboardPage';test.describe('Dashboard Tests', () => { test.beforeAll(async () => {
console.log('Runs once before all tests');
}); test('Verify dashboard page', async ({ page }) => {
const dashboard = new DashboardPage(page); await page.goto('/dashboard');
await dashboard.verifyDashboardLoaded();
}); test('Another test using same session', async ({ page }) => {
await page.goto('/dashboard/settings');
console.log('User is already logged in');
});});

✅ 7. How This Works (Important)

🔹 Flow:

  1. login.setup.ts runs first
  2. Logs in and saves session → storageState.json
  3. All test files reuse this session
  4. No repeated login → faster execution

✅ 8. Alternative: Using beforeAll Without storageState (Not Recommended)

test.beforeAll(async ({ browser }) => {
const context = await browser.newContext();
const page = await context.newPage(); await page.goto('/login');
await page.fill('#username', 'user');
await page.fill('#password', 'pass');
await page.click('#loginBtn'); // ❌ This session is NOT shared across tests automatically
});

👉 Problem:

  • Each test gets a new context
  • Session is NOT reused

✅ 9. Best Practice Summary

✔ Use storageState (Recommended)
✔ Keep login logic in setup file
✔ Use POM for maintainability
✔ Use project dependencies
✔ Avoid login in every test


✅ 10. Pro Tips (Real Project)

  • Store credentials in .env
  • Use multiple storage states for multi-users
  • Use fixtures for advanced reuse
  • Add retry logic for flaky login

Here’s a complete, real-world Playwright setup for multi-user session handling (Admin + User) using POM + storageState + project dependencies.

This is how teams handle role-based testing at scale.


✅ 1. Goal

We want to:

  • Login as Admin
  • Login as Normal User
  • Save both sessions separately
  • Run tests using either role without logging in again

✅ 2. Project Structure

playwright-project/

├── tests/
│ ├── setup/
│ │ ├── admin.setup.ts
│ │ ├── user.setup.ts
│ │
│ ├── admin.spec.ts
│ ├── user.spec.ts

├── pages/
│ ├── LoginPage.ts
│ ├── DashboardPage.ts

├── storage/
│ ├── adminState.json
│ ├── userState.json

├── playwright.config.ts

✅ 3. Login Page (Reusable POM)

pages/LoginPage.ts

import { Page } from '@playwright/test';export class LoginPage {
constructor(private page: Page) {} async navigate() {
await this.page.goto('/login');
} async login(username: string, password: string) {
await this.page.fill('#username', username);
await this.page.fill('#password', password);
await this.page.click('#loginBtn');
}
}

✅ 4. Admin Login Setup

tests/setup/admin.setup.ts

import { test as setup } from '@playwright/test';
import { LoginPage } from '../../pages/LoginPage';setup('Login as Admin', async ({ page }) => {
const login = new LoginPage(page); await login.navigate();
await login.login('adminUser', 'adminPass'); await page.context().storageState({
path: 'storage/adminState.json',
});
});

✅ 5. User Login Setup

tests/setup/user.setup.ts

import { test as setup } from '@playwright/test';
import { LoginPage } from '../../pages/LoginPage';setup('Login as User', async ({ page }) => {
const login = new LoginPage(page); await login.navigate();
await login.login('normalUser', 'userPass'); await page.context().storageState({
path: 'storage/userState.json',
});
});

✅ 6. Playwright Config (Multi-User Projects)

playwright.config.ts

import { defineConfig } from '@playwright/test';export default defineConfig({
testDir: './tests', use: {
baseURL: 'https://example.com',
headless: false,
}, projects: [
// 🔹 Admin Setup
{
name: 'admin-setup',
testMatch: /admin\.setup\.ts/,
}, // 🔹 User Setup
{
name: 'user-setup',
testMatch: /user\.setup\.ts/,
}, // 🔹 Admin Tests
{
name: 'admin-tests',
dependencies: ['admin-setup'],
use: {
storageState: 'storage/adminState.json',
},
testMatch: /admin\.spec\.ts/,
}, // 🔹 User Tests
{
name: 'user-tests',
dependencies: ['user-setup'],
use: {
storageState: 'storage/userState.json',
},
testMatch: /user\.spec\.ts/,
},
],
});

✅ 7. Admin Test Example

tests/admin.spec.ts

import { test, expect } from '@playwright/test';test('Admin can access admin panel', async ({ page }) => {
await page.goto('/admin'); await expect(page.locator('h1')).toHaveText('Admin Dashboard');
});

✅ 8. User Test Example

tests/user.spec.ts

import { test, expect } from '@playwright/test';test('User cannot access admin panel', async ({ page }) => {
await page.goto('/admin'); await expect(page.locator('text=Access Denied')).toBeVisible();
});

✅ 9. Advanced: Use Fixtures (Cleaner Approach)

👉 Create a reusable fixture for roles

utils/fixtures.ts

import { test as base } from '@playwright/test';export const test = base.extend<{
adminPage: any;
userPage: any;
}>({
adminPage: async ({ browser }, use) => {
const context = await browser.newContext({
storageState: 'storage/adminState.json',
});
const page = await context.newPage();
await use(page);
await context.close();
}, userPage: async ({ browser }, use) => {
const context = await browser.newContext({
storageState: 'storage/userState.json',
});
const page = await context.newPage();
await use(page);
await context.close();
},
});

Use Fixture in Test

import { test } from '../utils/fixtures';test('Admin vs User behavior', async ({ adminPage, userPage }) => {
await adminPage.goto('/dashboard');
await userPage.goto('/dashboard'); console.log('Both sessions running in parallel');
});

✅ 10. Key Benefits

✔ No repeated login
✔ Faster test execution
✔ Role-based validation
✔ Parallel execution ready
✔ Clean separation of concerns


🚀 Real-World Use Cases

  • Admin vs Customer flows
  • RBAC (Role-Based Access Control) testing
  • Multi-tenant apps
  • Permission validation

⚠️ Common Mistakes

❌ Using same storageState for all users
❌ Logging in inside every test
❌ Hardcoding credentials
❌ Not using project dependencies


✅ Pro Tips

  • Use .env for credentials
  • Add API login for speed
  • Rotate test users (avoid blocking)
  • Keep session fresh (auto re-login if expired)