Practise JavaScript operators with 32 programs, each with a full solution, the exact output and a short explanation. The programs start with the basics, move to intermediate problems and finish with real-world scenarios from test automation, such as test data, prices, form inputs and test results. They are written for testers learning JavaScript for Playwright.
How to practise: read the task, write your own solution first, then open Show solution to compare. Run any program with node program.js.
New to this topic? Read the JavaScript Operators lesson first.
- Beginner programs (1–10)
- Intermediate programs (11–20)
- Real-world QA scenario programs (21–32)
JavaScript Beginner Programs
1. Basic arithmeticBeginner
Given a = 17 and b = 5, print their sum, difference, product, quotient and remainder.
Show solution
const a = 17;
const b = 5;
console.log('Sum:', a + b);
console.log('Difference:', a - b);
console.log('Product:', a * b);
console.log('Quotient:', a / b);
console.log('Remainder:', a % b);
Output
Sum: 22
Difference: 12
Product: 85
Quotient: 3.4
Remainder: 2
Explanation: % returns the remainder after division. / always gives a decimal result when the division is not exact.
2. Exponent operatorBeginner
Print 2 to the power of 10 using ** and Math.pow.
Show solution
console.log(2 ** 10);
console.log(Math.pow(2, 10));
Output
1024
1024
Explanation: ** is the exponent operator and gives the same result as Math.pow.
3. Even or odd with modulusBeginner
Use % to print whether 7 and 12 are even or odd.
Show solution
for (const n of [7, 12]) {
console.log(n, n % 2 === 0 ? 'is even' : 'is odd');
}
Output
7 is odd
12 is even
Explanation: a number is even when dividing by 2 leaves no remainder.
4. Compound assignmentBeginner
Start with total = 100 and apply +=, -=, *=, /= and %= one after another, printing each result.
Show solution
let total = 100;
total += 20; console.log(total);
total -= 10; console.log(total);
total *= 2; console.log(total);
total /= 4; console.log(total);
total %= 50; console.log(total);
Output
120
110
220
55
5
Explanation: compound operators update a variable using its current value, so total += 20 means total = total + 20.
5. Comparison operatorsBeginner
Compare score = 75 with 70 using >, <, >=, <=, === and !==.
Show solution
const score = 75;
console.log(score > 70, score < 70);
console.log(score >= 75, score <= 74);
console.log(score === 75, score !== 75);
Output
true false
true false
true false
Explanation: comparison operators return booleans that you can use in conditions and assertions.
6. Strict vs loose equalityBeginner
Compare '5' and 5 with == and ===.
Show solution
console.log('5' == 5);
console.log('5' === 5);
console.log('5' != 5);
console.log('5' !== 5);
Output
true
false
false
true
Explanation: == converts types before comparing, while === also checks the type. Prefer === in test code.
7. Logical AND, OR, NOTBeginner
With isLoggedIn = true and isAdmin = false, print the results of &&, || and !.
Show solution
const isLoggedIn = true;
const isAdmin = false;
console.log(isLoggedIn && isAdmin);
console.log(isLoggedIn || isAdmin);
console.log(!isAdmin);
Output
false
true
true
Explanation: && needs both sides true, || needs at least one, and ! flips a boolean.
8. Increment and decrementBeginner
Show the difference between x++ and ++x.
Show solution
let x = 5;
console.log(x++);
console.log(x);
let y = 5;
console.log(++y);
console.log(y);
Output
5
6
6
6
Explanation: postfix x++ returns the old value and then increments. Prefix ++y increments first and returns the new value.
9. String concatenation with +Beginner
Join a first name and last name with a space using +, then add a number to a string.
Show solution
const firstName = 'Neha';
const lastName = 'Verma';
console.log(firstName + ' ' + lastName);
console.log('Build #' + 42);
Output
Neha Verma
Build #42
Explanation: when either side of + is a string, the other side is converted and the values are joined.
10. Ternary operatorBeginner
Use the ternary operator to print 'PASS' when score >= 60 and 'FAIL' otherwise, for 72 and 45.
Show solution
for (const score of [72, 45]) {
const result = score >= 60 ? 'PASS' : 'FAIL';
console.log(score, result);
}
Output
72 PASS
45 FAIL
Explanation: condition ? a : b returns a when the condition is truthy, otherwise b.
JavaScript Intermediate Programs
11. Short-circuit with &&Intermediate
Call a function only when a flag is true, using &&.
Show solution
function takeScreenshot() {
console.log('Screenshot taken');
return true;
}
const debug = true;
const ci = false;
debug && takeScreenshot();
ci && takeScreenshot();
console.log('Done');
Output
Screenshot taken
Done
Explanation: && stops at the first falsy value, so the function on its right runs only when the left side is truthy.
12. || vs ?? for defaultsIntermediate
Use both || and ?? to default a timeout of 0, null and undefined to 5000.
Show solution
for (const value of [0, null, undefined]) {
console.log(String(value), '| ||:', value || 5000, '| ??:', value ?? 5000);
}
Output
0 | ||: 5000 | ??: 0
null | ||: 5000 | ??: 5000
undefined | ||: 5000 | ??: 5000
Explanation: || replaces every falsy value, including a valid 0. ?? only replaces null and undefined.
13. Logical assignment operatorsIntermediate
Use ||=, &&= and ??= on a settings object.
Show solution
const settings = { name: '', retries: null, headless: true };
settings.name ||= 'default-suite';
settings.retries ??= 2;
settings.headless &&= false;
console.log(settings);
Output
{ name: 'default-suite', retries: 2, headless: false }
Explanation: a ||= b assigns only if a is falsy, a ??= b only if a is null or undefined, and a &&= b only if a is truthy.
14. Optional chainingIntermediate
Safely read user.address.city when address may be missing.
Show solution
const withAddress = { name: 'Asha', address: { city: 'Delhi' } };
const withoutAddress = { name: 'Ravi' };
console.log(withAddress.address?.city);
console.log(withoutAddress.address?.city);
console.log(withoutAddress.address?.city ?? 'N/A');
Output
Delhi
undefined
N/A
Explanation: ?. returns undefined instead of throwing when the left side is null or undefined.
15. Operator precedenceIntermediate
Predict and print the results of 2 + 3 * 4, (2 + 3) * 4 and 10 - 4 - 3.
Show solution
console.log(2 + 3 * 4);
console.log((2 + 3) * 4);
console.log(10 - 4 - 3);
console.log(2 ** 3 ** 2);
Output
14
20
3
512
Explanation: * binds tighter than +, subtraction runs left to right, and ** runs right to left (3 ** 2 first).
16. typeof and instanceofIntermediate
Use typeof on a primitive and instanceof on an object.
Show solution
const today = new Date(0);
const tags = ['smoke'];
console.log(typeof 'text');
console.log(today instanceof Date);
console.log(tags instanceof Array);
console.log(tags instanceof Object);
Output
string
true
true
true
Explanation: typeof names primitive types, while instanceof checks whether an object was created by a constructor.
17. The in operatorIntermediate
Check whether a config object has the keys browser and proxy.
Show solution
const config = { browser: 'chromium', retries: 0 };
console.log('browser' in config);
console.log('proxy' in config);
console.log('retries' in config && config.retries === 0);
Output
true
false
true
Explanation: in checks whether a property exists, even when its value is falsy like 0.
18. Spread operatorIntermediate
Merge default and custom settings with the spread operator.
Show solution
const defaults = { browser: 'chromium', retries: 0, headless: true };
const custom = { retries: 2 };
const finalConfig = { ...defaults, ...custom };
console.log(finalConfig);
console.log([...[1, 2], ...[3]]);
Output
{ browser: 'chromium', retries: 2, headless: true }
[ 1, 2, 3 ]
Explanation: spread copies properties or elements. Later properties overwrite earlier ones with the same name.
19. Bitwise check of permission flagsIntermediate
Use bitwise operators to check which permissions a user has.
Show solution
const READ = 1, WRITE = 2, DELETE = 4;
const userPermissions = READ | WRITE;
console.log('Can read:', (userPermissions & READ) !== 0);
console.log('Can write:', (userPermissions & WRITE) !== 0);
console.log('Can delete:', (userPermissions & DELETE) !== 0);
Output
Can read: true
Can write: true
Can delete: false
Explanation: | combines flags into one number and & tests whether a flag is set.
20. Swap numbers with arithmeticIntermediate
Swap two numbers using only arithmetic operators.
Show solution
let a = 8;
let b = 3;
a = a + b;
b = a - b;
a = a - b;
console.log(a, b);
Output
3 8
Explanation: storing the sum lets you recover each original value with subtraction. Destructuring is clearer in real code.
JavaScript Real-World QA Scenario Programs
21. Calculate cart total with taxReal-world
Calculate the total for a cart of 1200 with 18% tax, and round to 2 decimals.
Show solution
const subtotal = 1200;
const taxRate = 0.18;
const tax = subtotal * taxRate;
const total = subtotal + tax;
console.log('Tax:', tax.toFixed(2));
console.log('Total:', total.toFixed(2));
Output
Tax: 216.00
Total: 1416.00
Explanation: multiplication gives the tax, addition gives the total, and toFixed formats money for display.
22. Apply a discountReal-world
Apply a 15% discount to 2499 and print the discount and final price.
Show solution
const price = 2499;
const discountPercent = 15;
const discount = (price * discountPercent) / 100;
const finalPrice = price - discount;
console.log(`Discount: ${discount.toFixed(2)}`);
console.log(`Final price: ${finalPrice.toFixed(2)}`);
Output
Discount: 374.85
Final price: 2124.15
Explanation: percentages are calculated with * and /. Format the results for display.
23. Pass percentage and gradeReal-world
With passed = 47 of total = 52 tests, calculate the pass rate and label it 'Green' (95%+), 'Amber' (80%+) or 'Red'.
Show solution
const passed = 47;
const total = 52;
const rate = (passed / total) * 100;
const label = rate >= 95 ? 'Green' : rate >= 80 ? 'Amber' : 'Red';
console.log(`${rate.toFixed(1)}% - ${label}`);
Output
90.4% - Amber
Explanation: chained ternaries pick one of several labels. For more than three cases, an if/else chain is clearer.
24. Check a value is within rangeReal-world
Check that a response time of 850 ms is between 0 and 1000 ms, and that 1200 ms is not.
Show solution
const MIN = 0, MAX = 1000;
for (const ms of [850, 1200]) {
const ok = ms >= MIN && ms <= MAX;
console.log(`${ms} ms within SLA: ${ok}`);
}
Output
850 ms within SLA: true
1200 ms within SLA: false
Explanation: combine two comparisons with && to test a range.
25. Validate login form fieldsReal-world
A login is valid when the username is not empty and the password has at least 8 characters. Test three cases.
Show solution
const cases = [['qa_user', 'Secret123'], ['', 'Secret123'], ['qa_user', 'short']];
for (const [username, password] of cases) {
const valid = username.length > 0 && password.length >= 8;
console.log(`'${username}' / ${password.length} chars -> ${valid ? 'valid' : 'invalid'}`);
}
Output
'qa_user' / 9 chars -> valid
'' / 9 chars -> invalid
'qa_user' / 5 chars -> invalid
Explanation: && requires every rule to pass. One false condition makes the whole expression false.
26. Decide whether to retry a testReal-world
Retry when the test failed AND attempts are below the limit, OR when the failure was a timeout.
Show solution
const MAX_RETRIES = 2;
const runs = [
{ failed: true, attempts: 1, timeout: false },
{ failed: true, attempts: 2, timeout: false },
{ failed: true, attempts: 3, timeout: true }
];
for (const run of runs) {
const retry = (run.failed && run.attempts < MAX_RETRIES) || run.timeout;
console.log(`attempts=${run.attempts} timeout=${run.timeout} -> retry: ${retry}`);
}
Output
attempts=1 timeout=false -> retry: true
attempts=2 timeout=false -> retry: false
attempts=3 timeout=true -> retry: true
Explanation: parentheses make the business rule explicit, because && binds tighter than ||.
27. Round-robin browser selectionReal-world
Assign 7 test cases to 3 browsers in turn using the modulus operator.
Show solution
const browsers = ['chromium', 'firefox', 'webkit'];
for (let i = 0; i < 7; i++) {
console.log(`TC-${i + 1} -> ${browsers[i % browsers.length]}`);
}
Output
TC-1 -> chromium
TC-2 -> firefox
TC-3 -> webkit
TC-4 -> chromium
TC-5 -> firefox
TC-6 -> webkit
TC-7 -> chromium
Explanation: i % length cycles through 0, 1, 2, 0, 1, … which is ideal for distributing work.
28. Convert milliseconds to h:m:sReal-world
Convert 3725000 ms into hours, minutes and seconds.
Show solution
const ms = 3725000;
const totalSeconds = Math.floor(ms / 1000);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
console.log(`${hours}h ${minutes}m ${seconds}s`);
Output
1h 2m 5s
Explanation: division gives the larger units and % gives what is left over.
29. Compare expected and actual countsReal-world
Compare the expected item count with the count shown in the UI, which is text, and print a clear message.
Show solution
const expectedCount = 3;
const uiText = '3';
const loose = expectedCount == uiText;
const strict = expectedCount === Number(uiText);
console.log('Loose match:', loose);
console.log('Strict match after conversion:', strict);
Output
Loose match: true
Strict match after conversion: true
Explanation: convert UI text explicitly and use ===, so a mismatch in types never hides a real bug.
30. Build a feature-flag decisionReal-world
Show a beta banner when the feature is enabled and the user is either a beta tester or an employee.
Show solution
const users = [
{ name: 'Asha', betaTester: true, employee: false },
{ name: 'Ravi', betaTester: false, employee: false },
{ name: 'Meera', betaTester: false, employee: true }
];
const featureEnabled = true;
for (const u of users) {
const showBanner = featureEnabled && (u.betaTester || u.employee);
console.log(u.name, showBanner);
}
Output
Asha true
Ravi false
Meera true
Explanation: grouping the || part with parentheses makes the rule read exactly like the requirement.
31. Average response timeReal-world
Calculate the average of the response times 120, 340, 95 and 410 ms.
Show solution
const times = [120, 340, 95, 410];
let sum = 0;
for (const t of times) sum += t;
const avg = sum / times.length;
console.log('Average:', avg, 'ms');
console.log('Above 200 ms:', avg > 200);
Output
Average: 241.25 ms
Above 200 ms: true
Explanation: += accumulates the total and / divides by the count to get the average.
32. Version comparisonReal-world
Compare two version strings '1.48.2' and '1.50.0' part by part.
Show solution
const current = '1.48.2'.split('.').map(Number);
const required = '1.50.0'.split('.').map(Number);
let result = 0;
for (let i = 0; i < 3 && result === 0; i++) {
result = current[i] > required[i] ? 1 : current[i] < required[i] ? -1 : 0;
}
console.log(result < 0 ? 'Upgrade needed' : 'Version OK');
Output
Upgrade needed
Explanation: comparing numbers part by part avoids string comparison bugs such as '1.9' > '1.10'.