# Exercise: Ticket Booth Tests

Write the Vitest tests for a movie theater's working ticket booth, from its prices and discounts to its page, and prove they're good by catching three bugs the check plants in the code.

Freelancer · JavaScript · Unit Testing · Updated October 30, 2026

The Starlight Cinema's ticket booth works today. Matinees are $9 and evening shows $14, students save $2 and seniors $3, groups of 8 or more save $1 on every ticket, and the booth page adds up each order. Nobody wrote tests for it, though, so the next person who changes a price could break the booth and not find out until a customer does. This time the code is finished and the tests are yours to write. And to show your tests are worth having, a check plants three real bugs in the code, one at a time, and tells you whether your tests caught each one.

## Before you start

This exercise is a Vite project with Vitest and jsdom, at the exact versions the lessons use (Vite 8.3.5, Vitest 5.0.5, jsdom 30.1.3). You need Node.js 24 or later; `node --version` in a terminal shows yours.

## Get the exercise code

In the **Exercise** box beside the lesson, choose **Get the starter on GitHub** to open its GitHub repository. Click **Code**, then **Download ZIP**, and unzip it into a folder of your own. Or clone it with Git. Open the folder in VS Code, open its terminal with **Terminal > New Terminal**, and run `npm install` once.

The folder holds:

- `src/tickets.js`: the booth's prices and seats, five working functions with a comment and examples above each. Ready to use: don't change it.
- `src/booth.js`: the booth page's code. Pick who a ticket is for, click **Add ticket**, and the list and the total update. Ready to use.
- `src/tickets.test.js` and `src/booth.test.js`: your tests. Each has one worked example to show the shape.
- `index.html` and the rest of `src/`: the page itself, ready to use. `npm run dev` opens it.
- `check/`: the check, with its three planted-bug copies of `tickets.js`. You don't need to change it, and it's more fun not to read the copies until you're done.
- `README.md`: the list of behaviors your tests should cover.

## What to do

Every function in `tickets.js` has a comment that says what it does, with examples:

```javascript
/*
 * The total for a group: guests is an array of guest types.
 * Groups of 8 or more get $1 off every ticket.
 *
 * groupTotal(19, ['adult', 'student']) -> 26
 * groupTotal(19, []) -> 0
 */
```

1. **Read the README's list of behaviors.** There are twelve, for `showPrice`, `ticketPrice`, `groupTotal`, `bookSeats`, `loadOpenShowtimes` and the booth page.
2. **Write the tests for `tickets.js`** in `src/tickets.test.js`: one `describe` group per function, and one `it` per behavior, named in plain words.
3. **Test the errors and the async function.** `ticketPrice` and `bookSeats` throw on bad input, and `loadOpenShowtimes` waits for a server: hand it a stand-in of your own.
4. **Write the tests for the page** in `src/booth.test.js`. The file already runs in jsdom and builds the page before every test.

## Check your work

While you write, keep the tests running:

```bash
npm test
```

Every test you write should pass, because the code works. If one fails, work out the expected value again by hand: the test is the part to fix. Press **q** to stop watching.

Then see how good your tests are:

```bash
npm run check
```

It runs your tests four times: once on the working `tickets.js`, then once on each of three copies with a bug planted in it. One copy has an **off-by-one** (a limit that's out by one), one a **wrong discount**, and one a **missing `await`**. A bug counts as caught when at least one of your tests fails on its copy. At the start, check 1 passes (the worked examples pass) and checks 2 to 4 fail: that's expected, because two tests can't catch three bugs yet. A line that fails says what kind of test it's missing.

## Hints

- **Work out each expected value by hand,** from the comments in `tickets.js`. A test that copies whatever the code returns proves nothing.
- **Bugs hide at the edges.** For a rule such as "8 or more", test 7 and 8, not only 20. *Testing Edge Cases, Errors and Async Code* has the list of edges to look for.
- **Test every guest type,** at a matinee and at an evening show. A test for students alone can't tell whether seniors are charged right.
- **An error test needs an arrow:** `expect(() => ...).toThrow(...)`. An async test needs `async` and `await`, with `resolves` or `rejects`.
- **On the page,** set the picker's `value`, click **Add ticket** with `dispatchEvent`, and read `textContent`, as in *Testing a Page with jsdom*.

## When you're done

Every test is green in `npm test`, and `npm run check` shows four check marks:

```text
✔ 1) your tests run and pass on the working tickets.js (0.5402ms)
✔ 2) your tests catch planted bug 1, an off-by-one (1048.7512ms)
✔ 3) your tests catch planted bug 2, a wrong discount (1070.6139ms)
✔ 4) your tests catch planted bug 3, a missing await (1053.9799ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
```

Now open the three copies in `check/planted-bugs/` and find each bug. Which of your tests caught it? If you had to delete all but five of your tests, which five would you keep, and why?

## So what

Anyone can write tests that pass. Tests that fail when the code is wrong are the ones that protect customers, and planting a bug on purpose to see whether your tests notice is how professional teams check their tests too. It's called *mutation testing*, and there are tools that plant hundreds of bugs for you.

## Key terms

- [Vitest](https://www.ask-codey.com/glossary/vitest-unit-testing)
- [describe, it and expect](https://www.ask-codey.com/glossary/describe-it-and-expect)
- [Edge Case](https://www.ask-codey.com/glossary/edge-case)
- [Test Double](https://www.ask-codey.com/glossary/test-double)
- jsdom

## Related

- [Your First Tests with Vitest](https://www.ask-codey.com/lessons/javascript-testing-first-tests-with-vitest)
- [Testing Edge Cases, Errors and Async Code](https://www.ask-codey.com/lessons/javascript-testing-edge-cases-errors-async)
- [Testing a Page with jsdom](https://www.ask-codey.com/lessons/javascript-testing-the-dom)

Source: https://www.ask-codey.com/lessons/exercise-javascript-ticket-booth-tests
