Interview prep

The QA Wolf take-home, worked end to end

Edit a starter Playwright project to validate that the first 100 articles on Hacker News's newest page are sorted newest to oldest, then record a short video. It sounds like an hour. The page paginates at 30 — and that is where the actual test begins.

By Shahriyar · Updated

This task is reproduced across dozens of public candidate repos and has been stable for years. What follows is the thinking a reviewer wants to see, step by step — and the specific mistake that separates submissions.

Step 1 — Define the thing you're validating

Two words in the prompt are undefined, and both need a decision you write down.

"100." The newest page renders 30 items. You need four page loads. Nothing in the prompt says that — noticing it is the first checkpoint.

"Sorted newest to oldest." HN shows relative ages — "12 minutes ago". Comparing those as strings is wrong; parsing them as numbers is fragile, because "1 hour ago" and "59 minutes ago" can both be true of the same post. Look at the DOM instead: the age element carries an absolute timestamp in its title attribute.

// the age span holds the real timestamp
const ages = await page.locator("span.age").all();
const stamps = await Promise.all(
  ages.map(a => a.getAttribute("title"))   // "2026-08-02T14:07:11"
);

As a cross-check, HN item IDs increase monotonically — a correctly sorted list is also descending by ID. Two independent signals, and a timestamp-parsing mistake can no longer pass silently.

Step 2 — Find the bug the task is hiding

Between your first page load and your fourth, new posts arrive and everything shifts down. Naively clicking "More" three times and concatenating gives you duplicate items and silently missed ones — and your sort check may still pass. A green test, validating the wrong 100 articles. This is the moving-list bug, and not noticing it is what separates submissions.

Two defensible fixes. Dedupe by item ID as you collect, and keep paging until you hold 100 unique articles. Or walk the pagination cursor instead of the "More" link, which pins each page to a fixed position in the list. Either is fine — what gets scored is that you saw the problem and chose on purpose.

Step 3 — Structure

Keep index.js as the entry point they told you to run, and put the logic behind it:

index.js               // orchestration only, ~20 lines
src/hackerNews.js      // page interaction, pagination, extraction
src/validate.js        // pure function: array of articles -> result
tests/validate.spec.js // unit tests for the pure function
README.md

Making the comparison a pure function is the highest-leverage move in the whole exercise. It lets you unit test the sort logic against fixtures with no browser — three fixtures cover it: a sorted list, one swapped pair, one duplicate ID. That demonstrates you understand the test pyramid without writing a paragraph claiming you do.

Step 4 — Assert like you mean it

Don't print "articles are sorted". Throw, and exit non-zero. On failure, report the specific pair that broke the order:

Sort violation at index 41 -> 42:
  "Show HN: ..." (2026-08-02T14:07:11)
  is older than
  "Ask HN: ..."  (2026-08-02T14:09:03)

A reviewer who deliberately feeds your script a broken fixture wants a message they could act on. Handle the obvious failure paths the same way — page load timeout, fewer than 100 items available, a missing timestamp on some row. Three try/catch blocks with real messages beat one global catch.

Step 5 — The README and the video

Six short README sections: what it does; exact run commands from a clean clone; how you defined "sorted" and why; known limitations; what you'd do with more time; how long you spent. That last line is not humility theatre — it tells the reviewer how to calibrate everything else they read.

The video is the same content, spoken: two minutes on your decisions, not your code. Why timestamps over relative ages, the moving-list bug and your fix, one thing you'd add. The candidates who narrate their reasoning sound senior; the ones who read their file tree aloud do not.

Where this transfers

Every "validate this list" assignment has the same skeleton: an undefined ordering, a data source that changes underneath you, and a reviewer who will break your script on purpose. The take-home hub covers the other five assignment shapes and the reviewer scorecard — worth ticking through before you submit anything.

Frequently asked questions

What is the QA Wolf take-home assignment?

You edit a starter Playwright project so it visits Hacker News's newest page and validates that exactly the first 100 articles are sorted newest to oldest, then record a short video demoing your code. The page paginates at 30 items, which is the hidden difficulty.

What if new posts arrive while my script is running?

That is the bug the task is hiding. Between page loads the list shifts, so naive pagination collects duplicates and silently skips items — while the sort check stays green. Dedupe by item ID until you hold 100 unique articles, or walk the pagination cursor, and say in the README which you chose and why.

Does the video matter?

Yes — it is where you show the reasoning the code can't. Two minutes: why you defined "sorted" the way you did, the moving-list problem and your fix, and one thing you would do with more time. Talk decisions, not lines of code.