Practise JavaScript loops 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 Loops lesson first.
- Beginner programs (1–10)
- Intermediate programs (11–20)
- Real-world QA scenario programs (21–32)
JavaScript Beginner Programs
1. Print 1 to 5 with a for loopBeginner
Print the numbers 1 to 5 on one line.
Show solution
let line = '';
for (let i = 1; i <= 5; i++) {
line += i + ' ';
}
console.log(line.trim());
Output
1 2 3 4 5
Explanation: a for loop has a start (let i = 1), a condition (i <= 5) and an update (i++).
2. Countdown with a while loopBeginner
Print a countdown from 5 to 1 followed by 'Go!'.
Show solution
let n = 5;
while (n > 0) {
console.log(n);
n--;
}
console.log('Go!');
Output
5
4
3
2
1
Go!
Explanation: while repeats as long as its condition is true. Update the variable inside, or the loop never ends.
3. Sum of 1 to 100Beginner
Add up all numbers from 1 to 100.
Show solution
let sum = 0;
for (let i = 1; i <= 100; i++) {
sum += i;
}
console.log('Sum:', sum);
Output
Sum: 5050
Explanation: an accumulator variable collects the running total on each iteration.
4. Multiplication tableBeginner
Print the multiplication table of 7 from 1 to 10.
Show solution
for (let i = 1; i <= 10; i++) {
console.log(`7 x ${i} = ${7 * i}`);
}
Output
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70
Explanation: the loop counter supplies the multiplier on each pass.
5. Even numbers up to 20Beginner
Print all even numbers from 2 to 20 by stepping 2 at a time.
Show solution
const evens = [];
for (let i = 2; i <= 20; i += 2) {
evens.push(i);
}
console.log(evens.join(', '));
Output
2, 4, 6, 8, 10, 12, 14, 16, 18, 20
Explanation: the update step can be any expression, such as i += 2.
6. Loop over an array with for…ofBeginner
Print each browser name from an array.
Show solution
const browsers = ['chromium', 'firefox', 'webkit'];
for (const browser of browsers) {
console.log('Running on', browser);
}
Output
Running on chromium
Running on firefox
Running on webkit
Explanation: for...of gives each value directly, which is the cleanest way to read an array.
7. Index and value with entries()Beginner
Print each test name with its position, starting at 1.
Show solution
const tests = ['login', 'search', 'checkout'];
for (const [index, name] of tests.entries()) {
console.log(`${index + 1}. ${name}`);
}
Output
1. login
2. search
3. checkout
Explanation: entries() yields [index, value] pairs that you can destructure.
8. Loop over object keys with for…inBeginner
Print every key and value of a config object.
Show solution
const config = { browser: 'chromium', retries: 2, headless: true };
for (const key in config) {
console.log(`${key} = ${config[key]}`);
}
Output
browser = chromium
retries = 2
headless = true
Explanation: for...in iterates over an object’s keys. Use bracket notation to read each value.
9. Characters of a stringBeginner
Print each character of 'QA' and count the letters in 'Playwright'.
Show solution
for (const ch of 'QA') console.log(ch);
let count = 0;
for (const ch of 'Playwright') count++;
console.log('Letters:', count);
Output
Q
A
Letters: 10
Explanation: strings are iterable, so for...of visits each character.
10. do…while runs at least onceBeginner
Show that do...while runs its body once even when the condition is false.
Show solution
let attempts = 10;
do {
console.log('Attempt', attempts);
attempts++;
} while (attempts < 3);
console.log('Finished');
Output
Attempt 10
Finished
Explanation: do...while checks the condition after the body, so the body always runs at least once.
JavaScript Intermediate Programs
11. FactorialIntermediate
Calculate 5! and 10! with a loop.
Show solution
function factorial(n) {
let result = 1;
for (let i = 2; i <= n; i++) result *= i;
return result;
}
console.log(factorial(5));
console.log(factorial(10));
Output
120
3628800
Explanation: multiply an accumulator by each number from 2 to n.
12. Fibonacci seriesIntermediate
Print the first 10 Fibonacci numbers.
Show solution
const fib = [0, 1];
for (let i = 2; i < 10; i++) {
fib.push(fib[i - 1] + fib[i - 2]);
}
console.log(fib.join(' '));
Output
0 1 1 2 3 5 8 13 21 34
Explanation: each new term is the sum of the previous two.
13. Reverse a numberIntermediate
Reverse the digits of 12345 using a while loop and %.
Show solution
let num = 12345;
let reversed = 0;
while (num > 0) {
reversed = reversed * 10 + (num % 10);
num = Math.floor(num / 10);
}
console.log(reversed);
Output
54321
Explanation: % 10 takes the last digit and Math.floor(num / 10) removes it.
14. Prime check with breakIntermediate
Check whether 29 and 33 are prime, stopping as soon as a divisor is found.
Show solution
for (const n of [29, 33]) {
let isPrime = n > 1;
for (let d = 2; d * d <= n; d++) {
if (n % d === 0) {
isPrime = false;
break;
}
}
console.log(n, isPrime ? 'is prime' : 'is not prime');
}
Output
29 is prime
33 is not prime
Explanation: break exits the loop early. Checking divisors up to √n is enough.
15. Skip values with continueIntermediate
Print numbers 1 to 10, skipping multiples of 3.
Show solution
const result = [];
for (let i = 1; i <= 10; i++) {
if (i % 3 === 0) continue;
result.push(i);
}
console.log(result.join(' '));
Output
1 2 4 5 7 8 10
Explanation: continue skips the rest of the current iteration and moves to the next one.
16. Nested loops: star patternIntermediate
Print a right-angled triangle of stars with 4 rows.
Show solution
for (let row = 1; row <= 4; row++) {
let line = '';
for (let col = 1; col <= row; col++) line += '*';
console.log(line);
}
Output
*
**
***
****
Explanation: the inner loop runs once per row and its length depends on the outer counter.
17. Count vowelsIntermediate
Count the vowels in 'Automation Testing'.
Show solution
const text = 'Automation Testing';
let vowels = 0;
for (const ch of text.toLowerCase()) {
if ('aeiou'.includes(ch)) vowels++;
}
console.log('Vowels:', vowels);
Output
Vowels: 8
Explanation: loop over each character and count the ones that match a condition.
18. Find the maximum without Math.maxIntermediate
Find the largest value in [34, 78, 12, 99, 45] with a loop.
Show solution
const values = [34, 78, 12, 99, 45];
let max = values[0];
for (const v of values) {
if (v > max) max = v;
}
console.log('Max:', max);
Output
Max: 99
Explanation: keep the best value seen so far and replace it whenever a larger one appears.
19. Labeled break out of nested loopsIntermediate
Search a grid for the value 7 and stop both loops when it is found.
Show solution
const grid = [[1, 2, 3], [4, 7, 6], [7, 8, 9]];
outer: for (let r = 0; r < grid.length; r++) {
for (let c = 0; c < grid[r].length; c++) {
if (grid[r][c] === 7) {
console.log(`Found 7 at row ${r}, col ${c}`);
break outer;
}
}
}
Output
Found 7 at row 1, col 1
Explanation: a label lets break exit the outer loop, not just the inner one.
20. Palindrome checkIntermediate
Check whether 'level' and 'test' are palindromes using two pointers.
Show solution
for (const word of ['level', 'test']) {
let isPalindrome = true;
for (let i = 0, j = word.length - 1; i < j; i++, j--) {
if (word[i] !== word[j]) {
isPalindrome = false;
break;
}
}
console.log(word, isPalindrome);
}
Output
level true
test false
Explanation: compare characters from both ends moving inwards. A for loop can update two variables at once.
JavaScript Real-World QA Scenario Programs
21. Run tests in every browserReal-world
Simulate running three tests in three browsers and print each combination.
Show solution
const browsers = ['chromium', 'firefox', 'webkit'];
const tests = ['login', 'search', 'checkout'];
let runs = 0;
for (const browser of browsers) {
for (const test of tests) {
runs++;
}
}
console.log(`${tests.length} tests x ${browsers.length} browsers = ${runs} runs`);
Output
3 tests x 3 browsers = 9 runs
Explanation: nested loops visit every combination, just like Playwright projects multiply test runs.
22. Retry until successReal-world
Retry a flaky action up to 3 times, where it succeeds on the 3rd attempt.
Show solution
const MAX = 3;
let attempt = 0;
let success = false;
while (attempt < MAX && !success) {
attempt++;
success = attempt === 3;
console.log(`Attempt ${attempt}: ${success ? 'passed' : 'failed'}`);
}
console.log(success ? 'Action succeeded' : 'Gave up');
Output
Attempt 1: failed
Attempt 2: failed
Attempt 3: passed
Action succeeded
Explanation: the loop stops when it succeeds or runs out of attempts, whichever comes first.
23. Poll for a status changeReal-world
Poll a job status list until it reports 'done', with a maximum of 5 polls.
Show solution
const statuses = ['queued', 'running', 'running', 'done', 'done'];
let polls = 0;
let status;
do {
status = statuses[polls];
polls++;
console.log(`Poll ${polls}: ${status}`);
} while (status !== 'done' && polls < 5);
Output
Poll 1: queued
Poll 2: running
Poll 3: running
Poll 4: done
Explanation: polling loops need both a success condition and a limit, so tests never hang forever.
24. Summarise test resultsReal-world
Count passed, failed and skipped results in one loop.
Show solution
const results = ['passed', 'failed', 'passed', 'skipped', 'passed', 'failed'];
const summary = { passed: 0, failed: 0, skipped: 0 };
for (const r of results) summary[r]++;
console.log(summary);
Output
{ passed: 3, failed: 2, skipped: 1 }
Explanation: use each status as a key in a counter object and increment it inside the loop.
25. Find the first failed testReal-world
Stop at the first failed test and print its name and position.
Show solution
const runs = [
{ name: 'login', status: 'passed' },
{ name: 'search', status: 'failed' },
{ name: 'checkout', status: 'failed' }
];
for (let i = 0; i < runs.length; i++) {
if (runs[i].status === 'failed') {
console.log(`First failure: ${runs[i].name} (#${i + 1})`);
break;
}
}
Output
First failure: search (#2)
Explanation: break stops as soon as the first match is found, so later items are not checked.
26. Total a shopping cartReal-world
Loop over cart items and calculate the total price.
Show solution
const cart = [
{ item: 'Keyboard', price: 1499, qty: 1 },
{ item: 'Mouse', price: 599, qty: 2 },
{ item: 'Cable', price: 199, qty: 3 }
];
let total = 0;
for (const { price, qty } of cart) total += price * qty;
console.log('Cart total:', total);
Output
Cart total: 3294
Explanation: destructuring in the for...of header reads just the fields the calculation needs.
27. Generate test usersReal-world
Generate 3 test users with numbered usernames and emails.
Show solution
const users = [];
for (let i = 1; i <= 3; i++) {
users.push({ username: `qa_user${i}`, email: `qa_user${i}@example.com` });
}
for (const u of users) console.log(u.username, u.email);
Output
qa_user1 qa_user1@example.com
qa_user2 qa_user2@example.com
qa_user3 qa_user3@example.com
Explanation: a counter loop is a simple way to build numbered test data.
28. Validate every emailReal-world
Check each email in a list and print the invalid ones.
Show solution
const emails = ['a@test.com', 'bad-email', 'qa@shop.in', 'no@domain'];
const pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
for (const email of emails) {
if (!pattern.test(email)) console.log('Invalid:', email);
}
console.log('Checked', emails.length, 'emails');
Output
Invalid: bad-email
Invalid: no@domain
Checked 4 emails
Explanation: a loop applies the same validation to every item and reports only the failures.
29. Paginate through resultsReal-world
Read pages of results until a page is empty, counting the total items.
Show solution
const pages = [[1, 2, 3], [4, 5, 6], [7], []];
let page = 0;
let total = 0;
while (pages[page].length > 0) {
total += pages[page].length;
page++;
}
console.log(`Read ${page} pages, ${total} items`);
Output
Read 3 pages, 7 items
Explanation: pagination loops continue until the server returns an empty page.
30. Compare two listsReal-world
Find expected menu items missing from the actual menu.
Show solution
const expected = ['Home', 'Products', 'About', 'Contact'];
const actual = ['Home', 'About', 'Blog'];
const missing = [];
for (const item of expected) {
if (!actual.includes(item)) missing.push(item);
}
console.log('Missing:', missing.join(', '));
Output
Missing: Products, Contact
Explanation: loop over one list and check membership in the other to find differences.
31. Table rows to objectsReal-world
Convert table rows (arrays) into objects using a header row.
Show solution
const header = ['id', 'name', 'status'];
const rows = [['1', 'login', 'pass'], ['2', 'search', 'fail']];
for (const row of rows) {
const record = {};
for (let i = 0; i < header.length; i++) record[header[i]] = row[i];
console.log(record);
}
Output
{ id: '1', name: 'login', status: 'pass' }
{ id: '2', name: 'search', status: 'fail' }
Explanation: the inner loop pairs each header with the value at the same position, which is how web tables are usually read.
32. Wait with async delays in a loopReal-world
Simulate three steps that each wait 20 ms, running one after another with for...of and await.
Show solution
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const steps = ['open page', 'fill form', 'submit'];
for (const step of steps) {
await sleep(20);
console.log('Done:', step);
}
console.log('All steps finished in order');
Output
Done: open page
Done: fill form
Done: submit
All steps finished in order
Explanation: for...of with await runs async steps sequentially, which is how Playwright actions run. forEach would not wait. (Top-level await works in ES modules, such as .mjs files or "type": "module".)
1 thought on “JavaScript Loop Practice Programs with Solutions (32 Programs)”