Tutorial. Follow the steps in order. You change one line, add one test, and undo both at the end, so nothing stays in the repository.
In this tutorial, you add a status condition to the built-in list, prove it with a test, and see it in the browser. On the way, you run the four checks for every change: the unit tests, the linter, the typecheck, and a look at the page. The whole loop takes about fifteen minutes.
- A clone of the repository.
- Node. The suite runs on Node 22.
pnpm11.17 or later. ThedevEnginesfield inpackage.jsonasks for this version, andpnpmdownloads it if your copy is older.
-
Install the development tools:
pnpm install
-
Start the dev server:
pnpm run dev
The server bundles the sources into
dist/and prints its address:[watch] Server listening on http://127.0.0.1:8080 -
Open
http://127.0.0.1:8080in a browser.
The server rebuilds the bundle each time you save a source file. It does not reload the page, so reload the page yourself after each change.
Leave this terminal open, and use a second terminal for the commands below. If the server stops with an "address already in use" error, another process has port 8080. Stop that process and start the server again.
The status conditions live in one pure module:
src/entities/Conditions.js
Open the file. The CONDITIONS array is the pick-list that the Add
condition dialog offers. Each name is a plain string.
This module is pure logic. It takes values and returns new values, and it
never touches the DOM. Almost every rule in the app lives in a module like
this one, and the DOM code lives in src/ui/.
Architecture explains the split.
Add 'Cursed' to the array, in alphabetical order after CONCENTRATING:
export const CONDITIONS = [
'Blinded',
'Charmed',
CONCENTRATING,
'Cursed',
'Deafened',
// ... the rest
];CONCENTRATING is a constant for the string 'Concentrating', so
'Cursed' comes after it.
The tests live in tests/, and each test file pairs with one module.
-
Open
tests/Conditions.test.js. -
Add
CONDITIONSto the import at the top of the file:import { CONDITIONS, createCondition, addCondition, removeCondition, tickConditions, } from '../src/entities/Conditions.js';
-
Add this test at the end of the file:
test('the pick-list offers Cursed', () => { assert.ok(CONDITIONS.includes('Cursed')); });
Run the one test file. One file runs in well under a second, and the whole suite takes several seconds.
node --test tests/Conditions.test.jsThe summary at the end counts nine tests, one more than before:
# tests 9
# pass 9
# fail 0
If the test fails, read the first assertion in the output. It names the file and the line that failed.
Run each of these commands before a commit:
pnpm test
pnpm run lint
pnpm run typecheck| Command | What it checks | A clean run ends with |
|---|---|---|
pnpm test |
Every test file under tests/ |
3464 passed 0 failed, with your test included |
pnpm run lint |
Style and logic rules, such as unused variables and loose equality | No output after the eslint . line |
pnpm run typecheck |
The JSDoc types in the .js files against the declarations in src/types/ |
No output after the tsc --noEmit line |
The test count grows as the project grows, so your total can differ. The
count of failures must be 0.
The pre-commit hook runs the same three checks. To turn the hook on for this clone, run this command once:
git config core.hooksPath hooksThe unit tests build no DOM, so a change that reaches the UI also needs a look in the browser.
- Reload the browser tab with the app.
- Click Load example in the header, then click Load example in the confirmation dialog.
- Click Play in the mode switch.
- Open the Session tab in the sidebar, and find the Encounters panel.
- Open the Nearby encounters tab. If it reads "No encounters nearby.", click a tile a few steps from the party marker, and look again.
- On an encounter row, click the Condition button. The Add condition dialog opens.
- Open the Condition dropdown.
Cursedis in the list.
If the row already has condition chips, the button is a + icon with the label "Add condition".
Keep the browser console open while you check. A missing asset shows as a 404 error there and nowhere else.
- Remove
'Cursed'fromsrc/entities/Conditions.js. - Remove the test and the
CONDITIONSimport fromtests/Conditions.test.js. - Run
node --test tests/Conditions.test.jsagain. It reports eight passing tests. - Run
git status. It lists no changed files. - Stop the dev server with Ctrl+C.
- Read Testing a change for the preview pages and the other browser checks.
- Read Architecture to find where the other subsystems live.