Three lines
blog.test.ts
Nothing is sent: no URL, key or JSON. Every call answers a valid model. A
FakeSite is a SiteClient,
so hand it to the code under test.Answers
Give a method its answer by key,<accessor>.<method>:
Every kind of answer
Every kind of answer
A model, a plain object, a function
(args, site) => … (it may be async), an Error (thrown), or
sequence(first, second) (each call takes the next). blogPosts.* answers a whole accessor. A key that is no
method throws, suggesting the closest one.Answers in turn: sequence()
Answers in turn: sequence()
sequence(page1, page2) takes each answer as its own argument (not an array); each call takes the
next. One call past the end throws an Error: “The sequence for blogPosts.listBlogs ran out.” Give
one answer per call you expect.Errors, as the real SDK throws them
Errors, as the real SDK throws them
validationError({...}), notFound(), forbidden(), rateLimited(30), unreachable(),
siteError(500): the real error classes, for the faked site and route.Factories
Factories
Every answer model has
factories.<Model>(overrides): a valid model, the overrides a deep partial
(a nested object merges onto the nested fake; each item of a list of objects, given as a partial
object, is filled in over that item’s example the same way).Walks, finds, jobs and request()
Walks, finds, jobs and request()
A
listBlogsAll() walk is answered through blogPosts.listBlogs, a findBlog() through
blogPosts.getBlog, site.request() through the key request. A job’s wait() needs the
management SDK, under the fake too. fakeSite({}, { slug: 'globex' }) fakes another site.Your own values, nested
Fake one answer by key, override a nested field, and assert the call:media.test.ts
results is a partial object filled in over MediaImage’s example, like any nested
model, so every field you don’t name is still valid.
Assertions
They throw
node:assert’s AssertionError, listing what was called, so they work under node:test,
bun:test and Vitest alike.
Engine calls
fakeSite() fakes the SDK’s methods, not the engine: site.api() on it throws, saying so. For those,
pass a fetch to createSiteClient() (with retries: 0 unless the test checks retries), and a test
key that keeps to a real key’s characters:
Sweeping a real site
readSweep() calls every read a site offers and reports what each did: a health check.
Next: keeping keys secret
Where a key never shows up, and the one place it does.