2. Decisions and Loops
Make code choose with if and repeat with loops, the way a test checks and retries.
Chapter film (about 7m) is coming.
Comparisons and Truthiness
In plain English. A comparison asks JavaScript a yes/no question about two values: is this price bigger than that one, is this heading the same text as the one I expected? The answer is always true or false. Every check a test makes comes down to a comparison. JavaScript also has a rule for values that are not yes/no answers: when one is used as a yes/no check, it counts as true or false anyway. A value that counts as true is truthy, and one that counts as false is falsy. The falsy ones are a short list, so you can learn them all.
Comparing two values. The comparisons you will use are === (exactly equal), !== (not equal), >, <, >= and <=. JavaScript has two equality operators: loose equality (==) and strict equality (===). Loose equality performs type coercion before comparing (1 == '1' is true). That often leads to unexpected bugs. Always use strict equality (=== and !==), which checks both value and type.
Text compares letter by letter. '10' < '9' is true, because the text '1' sorts before '9'. A price read off a page is text, so convert it with Number() before you compare it (the Numbers & Type Coercion lesson showed how). Case matters too: 'Total' === 'total' is false.
Combining checks. && means "and": both sides must be true. || means "or": either side is enough. ! flips true to false and back. So loggedIn && isAdmin is true only when both are.
Truthy and falsy. The falsy values are false, 0, -0, 0n (the BigInt zero), "", null, undefined and NaN. Everything else is truthy, including "0", "false", the empty list [] and the empty record {} (the Arrays and Objects lessons come later in this course). That last pair catches people out: a check that tests whether [] is truthy passes. Ask JavaScript directly with Boolean(value).
Why a tester cares. A price of 0 is falsy, so a check that only asks "is there a price?" treats a free item as a missing one. When zero is a valid answer, compare against undefined or null instead. The next lesson, Decisions: if, else and switch, uses these answers to choose what the code does next.
Practise this. Read each line of the code box and predict what it prints before you press Run.
// Comparisons answer true or false
console.log('3 > 2:', 3 > 2);
console.log("'Total' === 'total':", 'Total' === 'total'); // false: case matters
// Strict (===) vs loose (==)
console.log("1 === '1':", 1 === '1'); // false: different types
console.log("1 == '1':", 1 == '1'); // true: coercion, the trap
// Text compares letter by letter. Convert before comparing prices.
console.log("'10' < '9':", '10' < '9'); // true (!)
console.log("Number('10') < Number('9'):", Number('10') < Number('9')); // false
// Combining checks
const loggedIn = true;
const isAdmin = false;
console.log('loggedIn && isAdmin:', loggedIn && isAdmin); // false: both needed
console.log('loggedIn || isAdmin:', loggedIn || isAdmin); // true: either is enough
console.log('!loggedIn:', !loggedIn); // false
// Truthy or falsy? Boolean() tells you.
console.log('Boolean(0):', Boolean(0)); // false
console.log("Boolean(''):", Boolean('')); // false
console.log('Boolean(null):', Boolean(null)); // false
console.log('Boolean(undefined):', Boolean(undefined)); // false
console.log('Boolean(NaN):', Boolean(NaN)); // false
console.log("Boolean('0'):", Boolean('0')); // true: text, not the number
console.log("Boolean('false'):", Boolean('false')); // true
console.log('Boolean([]):', Boolean([])); // true: an empty list is truthy
console.log('Boolean({}):', Boolean({})); // trueSign in to track your progress
Decisions: if, else and switch
In plain English. Control flow is how a program decides what to do next. Tests do this constantly: if the status code is 200, carry on; if it is 404, report a missing page. if and else choose between paths, and switch picks one path out of several for a single value. Each choice rests on a comparison, which the last lesson (Comparisons and Truthiness) covered. A block is the group of lines inside curly braces { } that belong to one path. This lesson is about choosing; repeating a step is the next lesson, Loops.
if, else if and else. The line if (status === 200) asks a yes/no question. If the answer is yes, the block after it runs. else if adds another question to try when the first was no, and else catches everything left over. The check inside the parentheses does not have to be a comparison: any value works, and a truthy one counts as yes.
The ternary operator. For a choice between two values, the ternary operator (condition ? trueValue : falseValue) fits on one line. It is shorthand, so keep it for short choices and use if when a path needs several lines.
switch. JavaScript has a switch statement for picking one path out of several for a single value. switch uses strict equality (===) for its comparisons under the hood. Each path ends with break; leave it out and the code carries on into the next path as well. default runs when no case matches.
const status = 200;
if (status === 200) {
console.log('Success!');
} else if (status === 404) {
console.log('Not Found');
} else {
console.log('Unknown error');
}
// The ternary operator: one value or the other, on one line
const label = status === 200 ? 'passed' : 'failed';
console.log('Result:', label);
const action = 'START';
switch (action) {
case 'START':
console.log('Starting...');
break;
default:
console.log('Idle');
}
// Leave out break and the code falls through into the next case
switch (404) {
case 404:
console.log('Not Found');
case 500:
console.log('...and this line runs too');
break;
default:
console.log('Unknown');
}Sign in to track your progress
Loops: for, while, for...of and for...in
In plain English. A loop repeats a step. Tests need this whenever there is a list: check every row of a table, try every user in a list, read every price on a page. To iterate means to go through a collection one item at a time. Two kinds of collection matter here. An array is an ordered list of values in square brackets, such as ['apple', 'banana']; the Arrays: The Complete Guide lesson covers them properly. An object is a set of named values, like a user record with a name and a role; each name is called a key. You will meet one loop for lists and a different one for an object's keys.
The classic loops. The classic for loop (for (let i = 0; i < 10; i++): start at 0, keep going while i < 10, and add 1 to i after each round with i++), while loop, and do...while loop are all available, as are the break keyword (leave the loop now) and continue (skip to the next round). Be mindful of scope: declaring loop variables with var leaks them outside the loop block, which is why let is strongly preferred for loop counters.
for...of walks a list. While the classic for loop is useful, JavaScript has a simpler way to go through a list or a string: the for...of loop, which hands you each value directly with no index to manage.
for...in walks an object's keys. JavaScript also has a for...in loop. It goes through the keys of an object, one per round. Inside it, user[key] reads the property whose name is held in key; the Objects & Destructuring lesson covers that bracket form. Do not use for...in on an array: it hands you the positions as text ('0', '1') instead of the values. Stick to for...of for arrays, and for...in for inspecting object keys.
Practise this. Change the lists in the code box and predict how many times each loop runs before you press Run.
// The classic for loop: start, stop condition, step
for (let i = 1; i <= 3; i++) {
console.log('Attempt', i);
}
// while: keep going as long as the check is true
let retries = 0;
while (retries < 2) {
retries++;
console.log('Retry', retries);
}
// break leaves the loop; continue skips to the next round
for (let n = 1; n <= 5; n++) {
if (n === 2) continue;
if (n === 4) break;
console.log('n =', n);
}
// for...of (iterates values directly)
const fruits = ['apple', 'banana', 'cherry'];
for (const fruit of fruits) {
console.log('Fruit:', fruit);
}
// for...in (for object properties)
const user = { name: 'Jatin', role: 'Developer' };
for (const key in user) {
console.log(`Key: ${key}, Value: ${user[key]}`);
}Sign in to track your progress
Practice and interview questions: JavaScript Basics
This is your first set of practice exercises. They use only what the last two chapters taught: values and variables, strings, numbers, comparisons, decisions and loops. Each one is a small script, themed on a job a tester does by hand: reading a value off a page, deciding what it means, and reporting it.
Write the code in a file or in the Run box, run it, and change the input to see whether it still behaves. Try the awkward inputs on purpose, such as an empty string, a missing @, or a value that is null. Remember that === checks exactly, while == converts types first, so === is almost always what you want.
Coding Exercises
-
Extract the Domain (Easy) Problem: Store an email address in a
const, such as'tester@playwright.dev'. Print only the part after the@. If the email has no@, printInvalid emailinstead. Hint:includes('@')tells you whether the@is there.email.split('@')cuts the text at the@and gives back a list of the pieces; the second piece isparts[1], because positions count from zero. -
Status Code Labels (Easy) Problem: Store an HTTP status code in a
const. PrintSuccessfor 200-299,Redirectfor 300-399,Client Errorfor 400-499 andServer Errorfor 500-599. PrintUnknownfor anything else. Hint: Anif / else ifchain, with two comparisons joined by&&for each range. -
Parse a UI Price (Medium) Problem: You read a price from a page:
"Total: $1,234.56 USD". Turn it into the number1234.56. Hint: Remove the pieces that are not part of the number withreplace, one piece at a time, then convert what is left withparseFloat(). -
First Plain Pattern (Medium) Problem: You have a list of text patterns, such as
['//button', '#save', '//a']. Print the first one that does NOT start with//. If every one starts with//, print the first one. Hint: Afor...ofloop withstartsWith, andbreakonce you have an answer.patterns[0]is the first item in the list. -
Safe Label (Medium) Problem: A label read from a page might be text, an empty string, or
null(missing). Print the label with spaces trimmed off, orNo labelwhen there is no text. Hint: A label with no text is falsy, so the ternarylabel ? label.trim() : 'No label'covers it. Try it with' Save ',''andnull.
Interview Questions
-
What is the difference between
var,let, andconst? Answer:varis function-scoped (it exists everywhere inside the function it is declared in; Functions Deep Dive introduces functions).letandconstare block-scoped, which means they exist only inside the{ }where they were declared.constprevents reassignment, though objects declared withconstcan still be mutated. -
Why should you use
===instead of==? Answer:==performs type coercion (e.g.,"1" == 1is true).===checks both value and type, preventing unexpected bugs. -
What is the difference between
nullandundefined? Answer:undefinedmeans a variable has been declared but not assigned a value.nullis an explicit assignment representing "no value". -
What is
NaNand how do you check for it? Answer:NaNstands for Not-a-Number, representing an invalid mathematical operation. Check it usingNumber.isNaN(value). Interestingly,typeof NaNreturns"number". -
Which values are falsy in JavaScript? Answer:
false,0,-0,0n,"",null,undefinedandNaN. Everything else is truthy, including"0","false",[]and{}. -
What does
'5' + 2give, and what does'5' * 2give? Answer:'5' + 2gives the text'52', because+joins text when either side is text.'5' * 2gives the number10, because*only does arithmetic and converts the text first.
// Exercise 1: Extract the Domain
const email = 'tester@playwright.dev';
if (email.includes('@')) {
const parts = email.split('@');
console.log(parts[1]); // Expected: playwright.dev
} else {
console.log('Invalid email');
}
// Exercise 2: Status Code Labels
const code = 404;
if (code >= 200 && code <= 299) {
console.log('Success');
} else if (code >= 300 && code <= 399) {
console.log('Redirect');
} else if (code >= 400 && code <= 499) {
console.log('Client Error'); // Expected for 404
} else if (code >= 500 && code <= 599) {
console.log('Server Error');
} else {
console.log('Unknown');
}
// Exercise 3: Parse a UI Price
const priceText = 'Total: $1,234.56 USD';
const cleaned = priceText.replace('Total: $', '').replace(' USD', '').replace(',', '');
console.log(parseFloat(cleaned)); // Expected: 1234.56
// Exercise 4: First Plain Pattern
const patterns = ['//button', '#save', '//a'];
let chosen = patterns[0]; // fall back to the first one
for (const pattern of patterns) {
if (!pattern.startsWith('//')) {
chosen = pattern;
break;
}
}
console.log(chosen); // Expected: #save
// Exercise 5: Safe Label
for (const label of [' Save ', '', null]) {
console.log(label ? label.trim() : 'No label'); // Expected: Save, No label, No label
}Sign in to track your progress
Common questions
Practice
1 exercise attached to this chapter, about 4m.