Skip to content

Status Specifiers

The first argument to expectStatus tells it which statuses count as “success”. Everything else is an error.

ValueMeaning
200Exact status code
[200, 201]Any of these codes
[200, '3xx']Mixed — numbers and ranges
['success', 404]Mixed — named groups and codes
'success'200–299
'error'400–599
'1xx'100–199 (informational)
'2xx'200–299 (same as 'success')
'3xx'300–399 (redirection)
'4xx'400–499 (client errors)
'5xx'500–599 (server errors)
'auth'Custom group (instance-defined)
'!4xx'Negation — anything except 400–499
'!error'Negation — anything except 400–599
'!success'Negation — anything except 200–299

The matching status returns the typed body. Everything else is an error.

The simplest form — a single numeric status code:

const org = await expectStatus(201, api.createOrg({ body: data }));
// ^? body of the 201 branch

For operations that can return multiple success statuses (e.g., upsert, sync-or-async):

const member = await expectStatus([200, 201], api.acceptInvite({ body }));
// ^? body of the 200 branch | body of the 201 branch

Match an entire HTTP class. All five hundred-level ranges are supported:

await expectStatus("2xx", response); // any 200–299
await expectStatus("3xx", response); // any 300–399
await expectStatus("4xx", response); // any 400–499
await expectStatus("5xx", response); // any 500–599

'1xx' (100–199) is also supported but rarely needed.

Semantic shortcuts that span multiple ranges:

SpecifierMatches
'success'200–299 (= '2xx')
'error'400–599 (= '4xx' + '5xx')
await expectStatus("success", healthCheck());
await expectStatus("error", response); // treat errors as expected

Prefix any specifier with ! to invert it:

await expectStatus("!error", response); // anything except 4xx/5xx
await expectStatus("!4xx", response); // anything except 400–499
await expectStatus("!success", response); // anything except 2xx

Negation also works with custom groups:

await expectStatus("!auth", response); // anything except 401/403

Define named groups in your instance, then use them as specifiers:

const expectStatus = createExpectStatus({
groups: {
auth: [401, 403],
retryable: [408, 429, 500, 502, 503, 504],
cacheable: [200, 203, 300, 301],
},
});
await expectStatus("auth", response); // matches 401 or 403
await expectStatus("retryable", response); // matches 408, 429, 500, ...
await expectStatus("!auth", response); // anything except 401/403

Custom groups also work as dispatch keys:

await expectStatus(200, response, {
auth: () => redirect("/sign-in"),
retryable: "Please try again shortly.",
});

Note: Built-in groups ('success', 'error') work as expected-status arguments but are not valid dispatch keys. Use ranges ('4xx', '5xx') or custom groups for dispatch.

Combine codes, ranges, groups, and specifiers in a single array:

await expectStatus([200, "3xx"], response);
await expectStatus([200, 201, 304], response);
await expectStatus(["success", "cacheable"], response);

expectStatus accepts either a value or a Promise — no double-await needed:

const body = await expectStatus(200, client.fetch());
// equivalent to:
// const res = await client.fetch()
// const body = await expectStatus(200, res)