JavaScript If-Else Practice Programs with Solutions (31 Programs)

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.

Advertisement

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.

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 &amp;&amp; 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 &gt; versus &gt;= 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.

Keep Practising

Leave a Comment