Variables ⭐

 
js
const apiUrl = 'https://api.com';   // ⭐ default — can't reassign
let counter = 0;                     // reassignable, block-scoped
var old = 'avoid';                   // function-scoped, hoisted — don't use
  var let const
Scope Function Block Block
Reassign
Hoisted

⚠️ const ≠ immutable — you can't reassign the variable, but you can mutate the object:

 
js
const user = { name: 'Nav' };
user.name = 'Alex';        // ✅ allowed
user = {};                 // ❌ TypeError

Equality: always === (value and type). == coerces: '5' == 5 is true, '5' === 5 is false.

null vs undefined: undefined = declared, not assigned. null = deliberately empty.

Advertisement

Functions

 
js
// Declaration — hoisted
function login(user, pass) { return true; }

// Arrow — no own `this`, concise
const login = (user, pass) => true;
const double = n => n * 2;              // implicit return
const getUser = () => ({ id: 1 });      // returning an object needs ( )

// Default + rest params
function search(term, limit = 10, ...filters) {}

Arrow vs regular: arrows don't have their own this, arguments, and can't be constructors. For test code, arrows are almost always fine.


Arrays ⭐

 
js
const users = ['admin', 'user', 'guest'];

users.length            // 3
users[0]                // 'admin'
users.push('new')       // add to end
users.pop()             // remove from end
users.includes('admin') // true
users.indexOf('user')   // 1
users.join(', ')        // 'admin, user, guest'
users.slice(0, 2)       // copy a portion
[...users, 'extra']     // spread

The four that matter most:

Method Returns Use
map() New array, transformed Extract/convert every item
filter() New array, subset Keep matching items
find() First match (or undefined) Locate one item
forEach() Nothing Just iterate
 
js
const names   = users.map(u => u.name);
const admins  = users.filter(u => u.role === 'admin');
const nav     = users.find(u => u.name === 'Nav');
users.forEach(u => console.log(u.name));

// Also useful
users.some(u => u.active)     // any match? → boolean
users.every(u => u.active)    // all match? → boolean
users.reduce((sum, u) => sum + u.age, 0);

Objects & JSON ⭐

 
js
const user = { id: 1, name: 'Nav', address: { city: 'Bangalore' } };

user.name                  // dot notation
user['name']               // bracket notation
user.address.city          // nested
user?.address?.zip         // optional chaining — safe if missing

Object.keys(user)          // ['id','name','address']
Object.values(user)
Object.entries(user)       // [['id',1], ...]
{ ...user, name: 'Alex' }  // spread + override

// Destructuring ⭐ — everywhere in API tests
const { id, name } = user;
const { address: { city } } = user;
const [first, second] = users;

JSON — the tester's daily bread:

 
js
JSON.parse(responseText);      // string → object
JSON.stringify(payload);       // object → string
JSON.stringify(obj, null, 2);  // pretty-printed

Async JavaScript ⭐⭐

The single most important section for automation. Browser actions and API calls are asynchronous — forgetting await is a top cause of flaky tests.

 
js
// Promise states: pending → fulfilled | rejected

// .then() chain (older style)
fetch(url)
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));

// ⭐ async/await — cleaner, use this
async function getUser(id) {
  try {
    const res  = await fetch(`/users/${id}`);
    const data = await res.json();
    return data;
  } catch (err) {
    console.error('Failed:', err);
  }
}

// Parallel — when calls don't depend on each other
const [users, orders] = await Promise.all([getUsers(), getOrders()]);

The rules:

  • await only works inside an async function
  • await pauses until the promise settles
  • Use try/catch for errors
  • Missing await = your assertion runs before the action finishes
 
js
// ❌ Flaky — no await
page.click('#submit');
expect(page.locator('#msg')).toBeVisible();

// ✅ Correct
await page.click('#submit');
await expect(page.locator('#msg')).toBeVisible();

Conditions & Loops

 
js
if (status === 200) {} else if (status === 404) {} else {}

const msg = status === 200 ? 'OK' : 'Failed';       // ternary
const name = user.name ?? 'Guest';                   // nullish coalescing
const city = user?.address?.city;                    // optional chaining

for (let i = 0; i < 5; i++) {}
for (const u of users) {}          // ⭐ values (arrays)
for (const k in obj) {}            // keys (objects)
while (retries < 3) { retries++; }

Falsy values: false 0 '' null undefined NaN — everything else is truthy.


Where You'll Use This

Tool JavaScript use
Playwright The whole test — async/await everywhere
Postman Tests tab — pm.expect, JSON parsing
Cypress Test code + chained commands
Selenium JavaScriptExecutor snippets

Go Deeper