letter-punk

Testing

Letter Punk uses Node’s built-in test runner (node:test + node:assert/strict). No test framework dependency is installed — this keeps the project’s zero-bundler, minimal-tooling posture intact.

Running the suite

npm test

This runs node --test, which auto-discovers every file under test/.

Layout

Why these two modules first

gameLogic.js and dictionaryValidator.js are both written as pure, dependency-injected factories (createGameEngine(options), createDictionaryValidator(options)) with no hard-coded DOM, fetch, or window access baked into their construction. Every test builds a small in-memory harness: a fixed test board, a mocked validateWord/fetchImpl/ptrieFactory, and plain callback arrays that record onStateChange/onMessage/onWordResult events for assertions. No network calls, no browser globals, no real dictionary files are touched.

One exception: dictionaryValidator.js’s API-fallback path reads window.location.href directly (a hard dependency on running in a browser). The one test exercising that path stubs a minimal globalThis.window for its duration and tears it down in t.after() — this is a test-environment workaround, not a source change.

Current coverage

gameLogic.js (createGameEngine):

dictionaryValidator.js (createDictionaryValidator):

buildLogic.js (partial — see “Not covered yet”):

shareLink.js (encodeShareHash/decodeShareHash):

The multi-word backspace path is worth calling out: after accepting two words, deleting back through the second word’s letters resets an internal starterLocked flag, so continued deletes fully empty the builder while the first word’s required starting letter is still active — typing the wrong letter at that point correctly triggers “This word must start with X.” That interaction isn’t obvious from reading appendToken or removeLastToken in isolation; test/gameLogic.test.js traces it step by step so a future refactor can’t silently break it.

Not covered yet

Adding a new test

Follow the harness pattern already in test/gameLogic.test.js and test/dictionaryValidator.test.js: inject mocks for anything that would otherwise touch the network, the DOM, or window, and assert against the returned snapshot/result objects and recorded callback events rather than internal state.