Practise JavaScript if-else conditions with 31 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 If Conditions lesson first.
- Beginner programs (1–10)
- Intermediate programs (11–20)
- Real-world QA scenario programs (21–31)
JavaScript Beginner Programs
1. Positive, negative or zeroBeginner
Print whether each of 5, -3 and 0 is positive, negative or zero.
Show solution
for (const n of [5, -3, 0]) {
if (n > 0) {
console.log(n, 'is positive');
} else if (n < 0) {
console.log(n, 'is negative');
} else {
console.log(n, 'is zero');
}
}
Output
5 is positive
-3 is negative
0 is zero
Explanation: an if / else if / else chain checks conditions in order and runs only the first matching branch.
2. Voting eligibilityBeginner
Print 'Eligible' when age is 18 or more, otherwise 'Not eligible', for ages 17 and 21.
Show solution
for (const age of [17, 21]) {
if (age >= 18) {
console.log(age, 'Eligible');
} else {
console.log(age, 'Not eligible');
}
}
Output
17 Not eligible
21 Eligible
Explanation: if/else chooses between two outcomes based on one condition.
3. Largest of two numbersBeginner
Print the larger of 42 and 57.
Show solution
const a = 42;
const b = 57;
if (a > b) {
console.log('Larger:', a);
} else {
console.log('Larger:', b);
}
Output
Larger: 57
Explanation: a single comparison decides which branch runs.
4. Largest of three numbersBeginner
Find the largest of 12, 45 and 30 using if statements.
Show solution
const a = 12, b = 45, c = 30;
let largest;
if (a >= b && a >= c) {
largest = a;
} else if (b >= a && b >= c) {
largest = b;
} else {
largest = c;
}
console.log('Largest:', largest);
Output
Largest: 45
Explanation: combine comparisons with && so each branch checks one number against both others.
5. Leap yearBeginner
Check whether 2024, 1900 and 2000 are leap years.
Show solution
for (const year of [2024, 1900, 2000]) {
const leap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
if (leap) console.log(year, 'is a leap year');
else console.log(year, 'is not a leap year');
}
Output
2024 is a leap year
1900 is not a leap year
2000 is a leap year
Explanation: a year divisible by 4 is a leap year unless it is divisible by 100, but years divisible by 400 are leap years again.
6. Grade from marksBeginner
Convert marks 92, 78, 65 and 40 into grades A (90+), B (75+), C (60+) or F.
Show solution
for (const marks of [92, 78, 65, 40]) {
let grade;
if (marks >= 90) grade = 'A';
else if (marks >= 75) grade = 'B';
else if (marks >= 60) grade = 'C';
else grade = 'F';
console.log(marks, grade);
}
Output
92 A
78 B
65 C
40 F
Explanation: check the highest threshold first, so each value lands in the correct band.
7. Vowel or consonantBeginner
Check whether the letters 'e', 'K' and 'u' are vowels.
Show solution
for (const letter of ['e', 'K', 'u']) {
if ('aeiou'.includes(letter.toLowerCase())) {
console.log(letter, 'is a vowel');
} else {
console.log(letter, 'is a consonant');
}
}
Output
e is a vowel
K is a consonant
u is a vowel
Explanation: includes checks membership, and toLowerCase makes the check case-insensitive.
8. Day name with switchBeginner
Print the day name for day numbers 1, 6 and 9 using switch.
Show solution
for (const day of [1, 6, 9]) {
switch (day) {
case 1: console.log(day, 'Monday'); break;
case 2: console.log(day, 'Tuesday'); break;
case 3: console.log(day, 'Wednesday'); break;
case 4: console.log(day, 'Thursday'); break;
case 5: console.log(day, 'Friday'); break;
case 6: console.log(day, 'Saturday'); break;
case 7: console.log(day, 'Sunday'); break;
default: console.log(day, 'Invalid day');
}
}
Output
1 Monday
6 Saturday
9 Invalid day
Explanation: switch compares one value against many cases. break stops execution falling into the next case.
9. Weekday or weekend with grouped casesBeginner
Use grouped case labels to print whether a day name is a weekday or the weekend.
Show solution
for (const day of ['Saturday', 'Tuesday']) {
switch (day) {
case 'Saturday':
case 'Sunday':
console.log(day, 'is the weekend');
break;
default:
console.log(day, 'is a weekday');
}
}
Output
Saturday is the weekend
Tuesday is a weekday
Explanation: stacked case labels without break share one block of code.
10. Check divisibilityBeginner
Check whether 30 is divisible by 3 and 5, and print FizzBuzz-style output.
Show solution
const n = 30;
if (n % 3 === 0 && n % 5 === 0) console.log('FizzBuzz');
else if (n % 3 === 0) console.log('Fizz');
else if (n % 5 === 0) console.log('Buzz');
else console.log(n);
Output
FizzBuzz
Explanation: check the most specific condition (both divisors) first, otherwise an earlier branch would catch it.
JavaScript Intermediate Programs
11. Nested conditionsIntermediate
Grant access when the user is logged in, then check the role inside.
Show solution
const users = [
{ name: 'Asha', loggedIn: true, role: 'admin' },
{ name: 'Ravi', loggedIn: true, role: 'viewer' },
{ name: 'Guest', loggedIn: false, role: 'viewer' }
];
for (const u of users) {
if (u.loggedIn) {
if (u.role === 'admin') console.log(u.name, '-> full access');
else console.log(u.name, '-> read-only access');
} else {
console.log(u.name, '-> please log in');
}
}
Output
Asha -> full access
Ravi -> read-only access
Guest -> please log in
Explanation: a nested if makes a second decision only after the first condition is true.
12. Guard clausesIntermediate
Rewrite nested checks as early returns in a validateAge function.
Show solution
function validateAge(age) {
if (typeof age !== 'number') return 'Age must be a number';
if (age < 0) return 'Age cannot be negative';
if (age > 120) return 'Age looks unrealistic';
return 'Age is valid';
}
console.log(validateAge('20'));
console.log(validateAge(-1));
console.log(validateAge(35));
Output
Age must be a number
Age cannot be negative
Age is valid
Explanation: guard clauses exit early on invalid input, keeping the main logic flat and readable.
13. Truthy checks in conditionsIntermediate
Print whether each value would enter an if block.
Show solution
const values = [0, 'qa', '', [], null];
const labels = ['0', "'qa'", "''", '[]', 'null'];
values.forEach((value, i) => {
if (value) console.log(labels[i], '-> runs');
else console.log(labels[i], '-> skipped');
});
Output
0 -> skipped
'qa' -> runs
'' -> skipped
[] -> runs
null -> skipped
Explanation: if checks truthiness, not just true. Empty arrays are truthy, while 0, '' and null are falsy.
14. switch with true for rangesIntermediate
Use switch (true) to classify response times of 120, 600 and 2500 ms.
Show solution
for (const ms of [120, 600, 2500]) {
switch (true) {
case ms < 200: console.log(ms, 'fast'); break;
case ms < 1000: console.log(ms, 'acceptable'); break;
default: console.log(ms, 'slow');
}
}
Output
120 fast
600 acceptable
2500 slow
Explanation: switch (true) runs the first case whose expression is true, which works for ranges.
15. Object lookup instead of switchIntermediate
Map HTTP status codes to messages with an object lookup and a default.
Show solution
const messages = { 200: 'OK', 201: 'Created', 404: 'Not Found', 500: 'Server Error' };
for (const code of [200, 404, 418]) {
console.log(code, messages[code] ?? 'Unknown status');
}
Output
200 OK
404 Not Found
418 Unknown status
Explanation: a lookup object replaces long switch statements when each case only returns a value.
16. Ternary for short decisionsIntermediate
Print '1 test' or 'N tests' using a ternary for the plural.
Show solution
for (const count of [1, 5, 0]) {
console.log(`${count} ${count === 1 ? 'test' : 'tests'}`);
}
Output
1 test
5 tests
0 tests
Explanation: a ternary is ideal for small inline decisions such as singular and plural words.
17. Check string patternsIntermediate
Classify inputs as an email, a phone number or unknown.
Show solution
const inputs = ['qa@example.com', '9876543210', 'hello'];
for (const input of inputs) {
if (input.includes('@') && input.includes('.')) console.log(input, '-> email');
else if (/^\d{10}$/.test(input)) console.log(input, '-> phone');
else console.log(input, '-> unknown');
}
Output
qa@example.com -> email
9876543210 -> phone
hello -> unknown
Explanation: conditions can combine string methods and regular expressions to classify text.
18. Triangle typeIntermediate
Classify triangles with sides (3,3,3), (3,4,4) and (3,4,5).
Show solution
const triangles = [[3, 3, 3], [3, 4, 4], [3, 4, 5]];
for (const [a, b, c] of triangles) {
let type;
if (a === b && b === c) type = 'equilateral';
else if (a === b || b === c || a === c) type = 'isosceles';
else type = 'scalene';
console.log(`${a},${b},${c} -> ${type}`);
}
Output
3,3,3 -> equilateral
3,4,4 -> isosceles
3,4,5 -> scalene
Explanation: check the strictest case (all equal) before the looser one (any two equal).
19. Electricity bill slabsIntermediate
Calculate a bill where the first 100 units cost 5, the next 100 cost 7 and the rest cost 10 each, for 250 units.
Show solution
const units = 250;
let bill;
if (units <= 100) {
bill = units * 5;
} else if (units <= 200) {
bill = 100 * 5 + (units - 100) * 7;
} else {
bill = 100 * 5 + 100 * 7 + (units - 200) * 10;
}
console.log('Bill:', bill);
Output
Bill: 1700
Explanation: each branch adds up the full slabs below it plus the partial slab the value falls in.
20. Optional values with ?? in conditionsIntermediate
Print a configured or default browser name, treating an empty string as a valid configured value.
Show solution
for (const configured of ['firefox', '', undefined]) {
const browser = configured ?? 'chromium';
console.log(JSON.stringify(configured) ?? 'undefined', '->', JSON.stringify(browser));
}
Output
"firefox" -> "firefox"
"" -> ""
undefined -> "chromium"
Explanation: ?? only falls back for null and undefined. Use || when empty strings should also fall back.
JavaScript Real-World QA Scenario Programs
21. Map a test status to an exit codeReal-world
Return exit code 0 for passed or skipped, 1 for failed and 2 for anything else.
Show solution
function exitCode(status) {
switch (status) {
case 'passed':
case 'skipped':
return 0;
case 'failed':
return 1;
default:
return 2;
}
}
for (const s of ['passed', 'failed', 'skipped', 'timedOut']) console.log(s, exitCode(s));
Output
passed 0
failed 1
skipped 0
timedOut 2
Explanation: CI systems read exit codes, and switch maps each status to its code clearly.
22. Validate a passwordReal-world
Check a password for length (8+), a digit and an uppercase letter, and print the first failing rule.
Show solution
function checkPassword(pw) {
if (pw.length < 8) return 'Too short';
if (!/\d/.test(pw)) return 'Needs a digit';
if (!/[A-Z]/.test(pw)) return 'Needs an uppercase letter';
return 'Strong';
}
for (const pw of ['abc', 'abcdefgh', 'abcdefg1', 'Abcdefg1']) console.log(pw, '->', checkPassword(pw));
Output
abc -> Too short
abcdefgh -> Needs a digit
abcdefg1 -> Needs an uppercase letter
Abcdefg1 -> Strong
Explanation: guard clauses report the first rule that fails, which mirrors how form validation messages appear.
23. Choose environment URLReal-world
Select a base URL from an ENV value, defaulting to QA for unknown values.
Show solution
function baseUrlFor(env) {
if (env === 'prod') return 'https://shop.test';
if (env === 'staging') return 'https://staging.shop.test';
return 'https://qa.shop.test';
}
for (const env of ['prod', 'staging', 'dev']) console.log(env, '->', baseUrlFor(env));
Output
prod -> https://shop.test
staging -> https://staging.shop.test
dev -> https://qa.shop.test
Explanation: conditions centralise environment selection, with a safe default for anything unexpected.
24. Shipping cost rulesReal-world
Free shipping over 999, 49 for 500–999 and 99 below 500. Calculate it for three cart totals.
Show solution
for (const total of [1200, 750, 300]) {
let shipping;
if (total > 999) shipping = 0;
else if (total >= 500) shipping = 49;
else shipping = 99;
console.log(`Cart ${total} -> shipping ${shipping}`);
}
Output
Cart 1200 -> shipping 0
Cart 750 -> shipping 49
Cart 300 -> shipping 99
Explanation: boundary values (999, 500) are where bugs hide, so test values on and around each threshold.
25. Boundary value checksReal-world
For the shipping rule above, generate the boundary inputs 499, 500, 999 and 1000 and print the result for each.
Show solution
const shippingFor = total => (total > 999 ? 0 : total >= 500 ? 49 : 99);
for (const total of [499, 500, 999, 1000]) {
console.log(total, shippingFor(total));
}
Output
499 99
500 49
999 49
1000 0
Explanation: boundary value analysis checks each edge, because off-by-one mistakes like > versus >= are common.
26. Decide test priorityReal-world
Mark a test as P1 if it is on the checkout path or a blocker, P2 if it is a regression test, otherwise P3.
Show solution
const tests = [
{ id: 'TC1', area: 'checkout', blocker: false, regression: true },
{ id: 'TC2', area: 'profile', blocker: true, regression: false },
{ id: 'TC3', area: 'search', blocker: false, regression: true },
{ id: 'TC4', area: 'help', blocker: false, regression: false }
];
for (const t of tests) {
let priority;
if (t.area === 'checkout' || t.blocker) priority = 'P1';
else if (t.regression) priority = 'P2';
else priority = 'P3';
console.log(t.id, priority);
}
Output
TC1 P1
TC2 P1
TC3 P2
TC4 P3
Explanation: ordered conditions turn a written triage rule into code that is easy to review.
27. Verify a sort orderReal-world
Check whether a list of prices from the UI is sorted ascending and print a message.
Show solution
const prices = [99, 149, 149, 299, 250];
let sorted = true;
for (let i = 1; i < prices.length; i++) {
if (prices[i] < prices[i - 1]) {
console.log(`Out of order at index ${i}: ${prices[i - 1]} > ${prices[i]}`);
sorted = false;
break;
}
}
if (sorted) console.log('Prices are sorted');
Output
Out of order at index 4: 299 > 250
Explanation: compare each item with the previous one. The if reports exactly where the order breaks.
28. Check an API responseReal-world
Report a clear message for different status and body combinations.
Show solution
const responses = [
{ status: 200, body: { items: [1, 2] } },
{ status: 200, body: { items: [] } },
{ status: 401, body: null },
{ status: 503, body: null }
];
for (const res of responses) {
if (res.status >= 500) console.log(res.status, 'Server error - retry later');
else if (res.status === 401) console.log(res.status, 'Unauthorized - check token');
else if (res.body.items.length === 0) console.log(res.status, 'OK but no items');
else console.log(res.status, `OK with ${res.body.items.length} items`);
}
Output
200 OK with 2 items
200 OK but no items
401 Unauthorized - check token
503 Server error - retry later
Explanation: check error statuses before reading the body, so you never access items on a null body.
29. Feature availability by planReal-world
Show which features a user can use based on their plan.
Show solution
function canUse(plan, feature) {
if (feature === 'reports') return plan === 'pro' || plan === 'enterprise';
if (feature === 'sso') return plan === 'enterprise';
return true;
}
for (const plan of ['free', 'pro', 'enterprise']) {
console.log(plan, 'reports:', canUse(plan, 'reports'), 'sso:', canUse(plan, 'sso'));
}
Output
free reports: false sso: false
pro reports: true sso: false
enterprise reports: true sso: true
Explanation: one function with clear conditions is easy to cover with a test per plan and feature.
30. Classify a flaky testReal-world
Classify a test as stable, flaky or broken from its pass count over 10 runs.
Show solution
for (const passes of [10, 7, 0]) {
const runs = 10;
let label;
if (passes === runs) label = 'stable';
else if (passes === 0) label = 'broken';
else label = 'flaky';
console.log(`${passes}/${runs} passed -> ${label}`);
}
Output
10/10 passed -> stable
7/10 passed -> flaky
0/10 passed -> broken
Explanation: a test that sometimes passes and sometimes fails is flaky. Always passing or always failing is deterministic.
31. Business days onlyReal-world
Skip weekend dates when scheduling a test run, using getUTCDay().
Show solution
const dates = ['2026-11-06', '2026-11-07', '2026-11-08', '2026-11-09'];
for (const d of dates) {
const day = new Date(d + 'T00:00:00Z').getUTCDay();
if (day === 0 || day === 6) console.log(d, 'weekend - skip');
else console.log(d, 'run tests');
}
Output
2026-11-06 run tests
2026-11-07 weekend - skip
2026-11-08 weekend - skip
2026-11-09 run tests
Explanation: getUTCDay() returns 0 for Sunday and 6 for Saturday. Using UTC avoids time-zone surprises.