API cheat sheet
import { World } from '../eberly/generated'
const world = new World() // reads eberly.ts: url, stores, hooksconst alice = world.createUser() // a user with their own variables and tokenawait world.reset() // a worldStore scenario
const res = await alice.posts.get({ path: { postId: '1' } }) // also: body, queryres.status // numberres.body // union of the declared response bodiesres.data // 2xx body; any other status throwsres.assert(200) // status onlyres.assert(200, { title: 'Hello' }) // + deep-partial body checkres.assert(200, { id: z.number() }) // a schema or expect.any(…) instead of a valueres.assert(200).body.title // body narrowed to the 200 typeres.assert(403) // any undeclared 4xx/5xx works without a cast
alice.set({ key: 'lastPostId', value: 1 })alice.get({ key: 'lastPostId' }) // number, throws if not setalice.getSafe({ key: 'lastPostId' }) // number | undefinedStores
Section titled “Stores”eberly/userStore.ts: variables and scenarios of one user.
this.api.<group>.<method>(…) calls the API as this user
(the Nest example):
export class UserStore extends BaseStore<UserVars, WorldApi> { /** * Scenario: register (201) → login (200) → save the token. * No email/password passed → a unique random one is generated. */ public async signUp(args: { email?: string; password?: string } = {}): Promise<void> { const { email = `user-${randomUUID()}@example.com`, password = 'secret123' } = args
const registered = await this.api.auth.register({ body: { email, password } }) registered.assert(201, { email, avatarUrl: null })
const loggedIn = await this.api.auth.login({ body: { email, password } }) // assert narrows the body to the 200 type (TokenDto): `accessToken` without a cast. const { accessToken } = loggedIn.assert(200, { user: { email } }).body
this.set({ key: 'email', value: email }) this.set({ key: 'password', value: password }) this.set({ key: 'accessToken', value: accessToken }) }}eberly/hooks.ts:
| Hook | When | Arguments |
|---|---|---|
h.globalBefore(fn) |
before every request | { request, ctx } |
h.<group>.<method>.before(fn) |
before this endpoint, after global ones | { request, ctx } |
h.<group>.<method>.after(fn) |
after this endpoint | { request, response, ctx } |
h.globalAfter(fn) |
after every request, after endpoint ones | { request, response, ctx } |
h.globalRetry(fn) |
after every request; return true to replay it |
{ request, response, ctx } |
request has method, path, headers, query, body; ctx is the store
of the user who made the request. Examples: auth and token refresh,
save ids with hooks.
Privacy-friendly analytics, no cookies.