Skip to content

HTTP client testing

We keep both online and offline coverage for HTTP clients so we can validate network behaviour when available while still running fast, deterministic tests in CI and locally without external calls.

  • Online tests hit the real service and are intentionally opt-in (see assets/lua/tests/test-hackernews-online.fnl).
  • Offline tests replay recorded responses from assets/lua/tests/data/*.json through a mock http binding so we still exercise the full client code path, including caching, status handling, and headers.

Recording fixtures

assets/lua/tests/http-fixtures.fnl includes record-responses! to capture HTTP replies into JSON fixtures. Example for the Hacker News client:

sh
SPACE_ASSETS_PATH=$(pwd)/assets ./build/space -c '(do
  (local fixtures (require :tests/http-fixtures))
  (fixtures.record-responses!
    [{:key "topstories" :url "https://hacker-news.firebaseio.com/v0/topstories.json"}
     {:key "item/8863" :url "https://hacker-news.firebaseio.com/v0/item/8863.json"}
     {:key "user/dhouston" :url "https://hacker-news.firebaseio.com/v0/user/dhouston.json"}
     {:key "updates" :url "https://hacker-news.firebaseio.com/v0/updates.json"}
     {:key "maxitem" :url "https://hacker-news.firebaseio.com/v0/maxitem.json"}]
    (app.engine.get-asset-path \"lua/tests/data/hackernews-fixture.json\")))'

The helper asserts that the http, fs, and json bindings are present, waits for each response, and writes a single JSON file containing status codes, headers, and bodies. We keep fixtures small and representative so they remain readable in version control.

Replaying fixtures in tests

Use install-mock from the same helper to replace _G.http with a replay-only binding:

fennel
(local fixtures (require :tests/http-fixtures))
(local fixture (fixtures.read-json (app.engine.get-asset-path "lua/tests/data/hackernews-fixture.json")))
(local handle (fixtures.install-mock fixture))
;; run client code
(handle.restore) ;; always restore in a finally block

The mock:

  • Matches requests by URL (after stripping .json and the /v0/ prefix) or by explicit key.
  • Returns recorded status, headers, body, and ok flags.
  • Surfaces requests through mock.requests so tests can assert on headers and status codes in addition to parsed bodies.

Hacker News offline coverage

assets/lua/tests/test-hackernews-offline.fnl installs the mock, runs the real client against assets/lua/tests/data/hackernews-fixture.json, and asserts:

  • Lists and items parse from the recorded bodies.
  • Status codes and content-type headers survive the replay.
  • Caching is exercised by fetching an item twice and verifying the second hit comes from disk.
  • Updates and maxitem parsing work without network access.

The module is registered in assets/lua/tests/fast.fnl, so the offline tests run with the rest of the suite by default. Refresh fixtures and rerun the suite whenever the client changes its request surface or response expectations.