Test a loader
You'll test a loader with fsr test. The test runs your loader through the same interpreter that serves requests, with its services stubbed, so nothing else has to be running.
Before you start
Install from crates.io. You need no Node and no package manager.
cargo install snapfire_compiler
cargo install snapfire_fsr_cli
fsr --version
Every command and screenshot on this page was captured with fsr 0.x.
Write the test#
Tests live under app/tests/, mirroring routes/. Save this as app/tests/product/loader.test.ts:
;
;
;
"the loader hands the page the product the id names",
;ctx() builds what the request would have carried: params, session, services, input, query, identity, locale. The route in the type argument is what makes params type-check, so a typo in id is a build error.
A mocked service method is a function of its arguments. A plain value works when the arguments don't matter.
Run it#
It lowers the test, lowers the loader the way a build does and replays it.
Mocks and the contract#
Your mocks sit behind the same contract the real service does. A mock that returns a shape the API never could fails the test.
Drop a required field and see:
services: ,
It names the method and the field. It fails before your assertion is reached. The mock has to match the contract, so a test that passes ran the loader against the shape production returns.
The same check catches a mock for a method the contract doesn't declare and a call to a method you forgot to mock. The second is easy to miss: without the check the loader fails, the route falls through to your error component, then a page test passes against the wrong page.
What a test file can contain#
The runner accepts a small dialect and refuses anything else with the line number, so a test never quietly does less than it appears to. It accepts imports, const fixtures shared across tests and test blocks. Inside a block you build a context, run a loader or an action, then assert.
That restriction is the same one your loaders live under, for the same reason: the runner has to execute it in Rust.
What to test#
Test the loader and the action, which is where the logic is. The page is a function of its props, so there's little to test there. The build already refuses a page that destructures a field the loader doesn't return.
Next up: 410. Ship it.