Lesson 1 of 10 · Lesson + Lab · 60 min · Free preview

JavaScript (ES6+) Essentials for Testers & Node.js Setup

Learn exactly the modern JavaScript a Cypress tester needs and set up a Node.js LTS workspace with npm scripts that you will grow into a framework.

Why this matters on the job

Every Cypress test you will ever write is plain JavaScript running in Node.js and in the browser. In interviews at Indian service companies (TCS, Infosys, Wipro, Cognizant) and product companies alike, the first Cypress round almost always starts with JavaScript basics: "What is the difference between let and const?", "What does an arrow function return?", "Why can't you use async/await with Cypress commands?". Testers who switch from manual testing or from Selenium-Java often struggle not with Cypress itself but with JavaScript syntax. This lesson gives you exactly the JavaScript a tester needs — no more, no less — and sets up a clean Node.js workspace that you will reuse for the whole course.

On a real project you will receive a repository, run npm install, and be expected to add tests the same day. If you understand package.json, npm scripts, modules and array helpers, you will be productive from day one.

Concepts

The JavaScript a tester actually uses

FeatureExampleWhere you will use it in Cypress
const / letconst url = '/inventory.html'Test data, selectors, configuration values
Arrow functions(a, b) => a - bEvery describe, it, .then() callback
Template literals`Logged in as ${name}`Dynamic selectors and URLs
Destructuringconst { status, body } = resReading API responses and fixtures
Spread{ ...user, zip: '' }Building negative test data from a base object
map / filter / reduceprices.reduce((s, p) => s + p, 0)Verifying sorting, totals, list contents
Modulesmodule.exports / export defaultPage objects, helpers, config files
Promises / async-awaitawait fetch(url)Node scripts and setupNodeEvents tasks — not inside Cypress command chains

Node.js, npm and package.json

Node.js is the JavaScript runtime that runs Cypress, its config file and its plugins. npm installs packages listed in package.json into node_modules. Two sections matter most: devDependencies (tools like Cypress, reporters, Faker) and scripts (shortcuts such as npm run cy:run that your CI pipeline will call). Always commit package-lock.json so every teammate and the CI server install identical versions.

Tip: Use an LTS version of Node (20 or 22). Cypress 14 and later do not support Node versions older than 18, and CI images default to LTS, so matching it locally avoids "works on my machine" surprises.

Hands-on Lab: Set up Node.js and practise tester-grade JavaScript

  1. Install Node.js LTS. On macOS/Linux use nvm; on Windows use the installer from nodejs.org or nvm-windows. Then verify:
    # macOS / Linux with nvm
    nvm install 22
    nvm use 22
    
    # verify (any OS)
    node -v     # v22.x.x
    npm -v      # 10.x.x
  2. Create the course workspace that you will grow into a Cypress framework:
    mkdir cypress-qaji && cd cypress-qaji
    npm init -y
    git init
    echo "node_modules/" > .gitignore
    Open the folder in VS Code. Install the extensions ESLint and Prettier.
  3. Create basics.js with the code below. Every line is a pattern you will reuse in Cypress tests.
    // basics.js — run with: node basics.js
    const users = [
      { username: 'standard_user', locked: false },
      { username: 'locked_out_user', locked: true },
      { username: 'problem_user', locked: false },
    ];
    
    // 1. Arrow function + template literal
    const greet = (name) => `Logging in as ${name}`;
    console.log(greet(users[0].username));
    
    // 2. Destructuring
    const { username, locked } = users[1];
    console.log(username, 'locked?', locked);
    
    // 3. filter + map: which users can log in?
    const activeUsers = users.filter((u) => !u.locked).map((u) => u.username);
    console.log('Active:', activeUsers);
    
    // 4. reduce: cart total (what a checkout test verifies)
    const prices = [29.99, 9.99, 15.99, 49.99];
    const total = prices.reduce((sum, p) => sum + p, 0);
    console.log('Cart total:', total.toFixed(2));
    
    // 5. Sorting a COPY so the original stays untouched
    const sortedAsc = [...prices].sort((a, b) => a - b);
    console.log('Sorted:', sortedAsc, 'Original:', prices);
    
    // 6. Spread to derive negative test data from a valid object
    const buyer = { firstName: 'Asha', lastName: 'Rao', zip: '411001' };
    const buyerWithoutZip = { ...buyer, zip: '' };
    console.log(buyerWithoutZip);
    
    // 7. Promise + async/await (fine in Node scripts, NOT inside Cypress chains)
    const fakeApi = (ms) =>
      new Promise((resolve) => setTimeout(() => resolve({ status: 200 }), ms));
    
    (async () => {
      const res = await fakeApi(300);
      console.log('API status:', res.status);
    })();
    Run it with node basics.js. Expected output:
    Logging in as standard_user
    locked_out_user locked? true
    Active: [ 'standard_user', 'problem_user' ]
    Cart total: 105.96
    Sorted: [ 9.99, 15.99, 29.99, 49.99 ] Original: [ 29.99, 9.99, 15.99, 49.99 ]
    { firstName: 'Asha', lastName: 'Rao', zip: '' }
    API status: 200
  4. Practise modules. Create utils.js and import it from app.js (CommonJS — the same style cypress.config.js uses):
    // utils.js
    const toNumber = (priceText) => Number(priceText.replace('$', ''));
    const isSortedAsc = (arr) => arr.every((v, i) => i === 0 || arr[i - 1] <= v);
    module.exports = { toNumber, isSortedAsc };
    // app.js — run with: node app.js
    const { toNumber, isSortedAsc } = require('./utils');
    
    const uiPrices = ['$7.99', '$9.99', '$15.99', '$29.99'];
    const numbers = uiPrices.map(toNumber);
    console.log(numbers, 'sorted?', isSortedAsc(numbers)); // [ 7.99, 9.99, 15.99, 29.99 ] sorted? true
  5. Call a real API from Node (Node 18+ has fetch built in). Save as fetch-demo.mjs — the .mjs extension enables ES modules and top-level await:
    // fetch-demo.mjs — run with: node fetch-demo.mjs
    const res = await fetch('https://jsonplaceholder.typicode.com/users/1');
    const user = await res.json();
    console.log(res.status, user.name, user.email);
    // Expected: 200 Leanne Graham Sincere@april.biz
  6. Add npm scripts so commands are discoverable by anyone who clones the repo:
    npm pkg set scripts.basics="node basics.js"
    npm pkg set scripts.api="node fetch-demo.mjs"
    npm run basics
    npm run api
    Open package.json and confirm a scripts block now exists. Commit: git add . && git commit -m "chore: node workspace".

Why Cypress commands are not promises

Cypress commands such as cy.get() do not run immediately. They are queued and executed later, one after another, with automatic retries. That is why you never write const el = await cy.get('#id'). To use a value produced by Cypress, you chain .then() or use an alias. You will practise this in Lesson 3, but remember the rule now: plain JavaScript runs instantly, Cypress commands run later in a queue.

// WRONG — text is undefined because the command has not run yet
// const text = cy.get('.title').invoke('text');

// RIGHT — work with the yielded value inside .then()
cy.get('.title').invoke('text').then((text) => {
  expect(text).to.equal('Products');
});

Common mistakes

  • Using var — it is function-scoped and leaks across blocks. Default to const; use let only when you reassign.
  • Calling .sort() on the original array — it mutates it. Copy first with [...arr].sort().
  • Sorting numbers without a comparator: [10, 9, 100].sort() gives [10, 100, 9] because the default sort compares strings.
  • Mixing require and import in the same file, or using import in a .js file run directly by Node without "type": "module".
  • Deleting package-lock.json to "fix" install errors — it changes versions silently for the whole team.

Real-world assignment

Your lead shares this list of product prices scraped from a UI: ['$49.99', '$7.99', '$15.99', '$29.99', '$9.99', '$15.99']. Write price-check.js that (1) converts them to numbers, (2) prints the total rounded to 2 decimals, (3) prints the cheapest and most expensive item using Math.min/Math.max with spread, (4) prints how many duplicates exist using a Set, and (5) exits with code 1 (process.exit(1)) if the list is not sorted ascending. Add it as npm run price-check and push the repo to GitHub.

Key takeaways

  • Cypress = JavaScript on Node.js; know const/let, arrow functions, template literals, destructuring, spread and array helpers.
  • Use Node LTS, commit package-lock.json, and expose every command through npm scripts.
  • async/await is for Node scripts and plugin tasks; Cypress commands are queued and use .then().
  • Always copy before sorting and pass a numeric comparator.

🧪 Practical checklist

Do each task yourself and tick it off. All tasks are required to complete this lesson.

🎤 Interview questions

What is the difference between let, const and var?

var is function-scoped and hoisted; let and const are block-scoped. const prevents reassignment of the binding (object contents can still change), so it is the default choice in test code.

Why can't you use async/await with Cypress commands?

Cypress commands are enqueued and executed later with built-in retries; they return chainable objects, not real promises. You access yielded values through .then(), aliases or assertions instead.

What is the difference between dependencies and devDependencies?

dependencies are needed at runtime by the application; devDependencies are only needed for development and testing, which is where Cypress, reporters and Faker belong.

How would you verify that a list of prices shown on the UI is sorted ascending?

Convert the text to numbers with map, create a sorted copy with [...arr].sort((a, b) => a - b) and deep-compare the two arrays.

📝 Quiz, progress tracking & certificate

You're reading a free preview. Premium members tick off labs, take the quiz, unlock all 10 lessons and earn a verifiable certificate.

💎 Unlock with Premium Premium login
✓ You're subscribed! Job alerts arrive daily at 9 AM.
Scroll to Top