Skip to content

Hooks API Reference

Complete reference for the hooks utilities API provided to every hook function.

Modifies requests before they are sent.

import { BeforeEachRequestHook } from '@thymian/hooks';
const hook: BeforeEachRequestHook = async (request, context, utils) => {
// Modify request
return request;
};
export default hook;

Parameters:

  • request: HttpRequestTemplate - The request to be sent
  • context: ThymianHttpTransaction - Information about the current transaction
  • utils: HookUtils - Utility functions

Returns: HttpRequestTemplate - The modified request

Adds authentication credentials to requests.

import { AuthorizeHook } from '@thymian/hooks';
const hook: AuthorizeHook = async (request, context, utils) => {
// Add authentication
return request;
};
export default hook;

Parameters:

  • request: HttpRequestTemplate - The request to be sent
  • context: ThymianHttpTransaction - Information about the current transaction
  • utils: HookUtils - Utility functions

Returns: HttpRequestTemplate - The modified request

Validates or processes responses after they are received.

import { AfterEachResponseHook } from '@thymian/hooks';
const hook: AfterEachResponseHook = async (response, context, utils) => {
// Validate response
return response;
};
export default hook;

Parameters:

  • response: HttpResponse - The received response
  • context: { requestTemplate: HttpRequestTemplate; request: HttpRequest } - Request context
  • utils: HookUtils - Utility functions

Returns: HttpResponse - The response (possibly modified)

The utils object provides helper functions for common hook operations.

Make type-safe HTTP requests to endpoints defined in your OpenAPI specification.

async request<R extends keyof Endpoints>(
url: R,
args: Endpoints[R]['req'],
options?: {
runHooks?: boolean; // Default: true
authorize?: boolean; // Default: undefined (follows runHooks)
forStatusCode?: number; // Default: undefined (use default response)
}
): Promise<Endpoints[R]['res']>
  • url (string): Endpoint URL in format METHOD http://host:port/path
  • args (EndpointRequest): Request data
    • body: Request body
    • headers: HTTP headers
    • query: Query parameters
    • cookies: Cookies
    • path: Path parameters
  • options (optional): Request behavior options
    • runHooks: Execute hooks for this request (default: true)
    • authorize: Execute authorize hook for this request
    • forStatusCode: Use sample for specific status code

Promise resolving to response object:

{
statusCode: number;
body: unknown; // Automatically parsed if JSON
headers: Record<string, string | string[]>;
}

Basic request:

const response = await utils.request('POST http://localhost:3000/api/v1/launches', {
body: {
missionName: 'Apollo 11',
launchDate: '2026-12-31T00:00:00Z',
rocketType: 'Saturn V',
},
headers: {
'content-type': 'application/json',
},
});

Request without hooks:

const response = await utils.request(
'POST http://localhost:3000/api/v1/astronauts',
{
body: { name: 'Buzz', password: 'secret', role: 'Pilot' },
headers: { 'content-type': 'application/json' },
},
{
runHooks: false, // Don't execute hooks
},
);

Request specific status code:

const response = await utils.request(
'GET http://localhost:3000/api/v1/launches/123',
{},
{
forStatusCode: 404, // Use 404 response sample
},
);

Skip the current test. Execution stops immediately.

skip(message: string): never
  • message (string): Reason for skipping the test
const response = await utils.request('POST http://localhost:3000/api/v1/launches', {
body: {
/* ... */
},
headers: { 'content-type': 'application/json' },
});
if (response.statusCode !== 201) {
utils.skip('Cannot create launch for test');
}

Fail the current test. Execution stops immediately.

fail(message: string): never
  • message (string): Reason for test failure
const response = await utils.request('POST http://localhost:3000/api/v1/launches', {
body: {
/* ... */
},
headers: { 'content-type': 'application/json' },
});
if (response.statusCode !== 201) {
utils.fail(`Expected 201, got ${response.statusCode}`);
}
if (!response.body.id) {
utils.fail('Response missing required id field');
}

Log an informational message in test output.

info(message: string): void
  • message (string): Message to log
utils.info('Creating test user');
const response = await utils.request('POST http://localhost:3000/api/v1/astronauts', {
body: {
/* ... */
},
headers: { 'content-type': 'application/json' },
});
utils.info(`User created with ID: ${response.body.id}`);

Output:

POST /api/v1/launches
ℹ Creating test user
ℹ User created with ID: abc123
✓ 201 Created (15ms)

Log a warning message in test output.

warn(message: string, details?: string): void
  • message (string): Warning message
  • details (string, optional): Additional details
if (response.headers['x-rate-limit-remaining'] === '1') {
utils.warn('Rate limit almost exhausted', 'Only 1 request remaining');
}

Output:

POST /api/v1/launches
⚠ Rate limit almost exhausted (Only 1 request remaining)
✓ 201 Created (15ms)

Record a successful assertion.

assertionSuccess(message: string, assertion?: string): void
  • message (string): Assertion description
  • assertion (string, optional): Short assertion label
const response = await utils.request('GET http://localhost:3000/api/v1/launches', {});
if (response.body.length > 0) {
utils.assertionSuccess('Response contains launches', 'has launches');
}

Output:

GET /api/v1/launches
✓ has launches
✓ 200 OK (8ms)

Record a failed assertion. Test continues (unlike fail()).

assertionFailure(
message: string,
details?: {
assertion?: string;
expected?: unknown;
actual?: unknown;
}
): void
  • message (string): Assertion description
  • details (optional): Assertion details
    • assertion: Short assertion label
    • expected: Expected value
    • actual: Actual value
const body = JSON.parse(response.body || '{}');
if (!body.id) {
utils.assertionFailure('Missing id field', {
assertion: 'has id',
expected: 'id field present',
actual: 'id field missing',
});
}
if (!body.missionName) {
utils.assertionFailure('Missing missionName field', {
assertion: 'has missionName',
expected: 'missionName field present',
actual: 'missionName field missing',
});
}

Output:

POST /api/v1/launches
✗ has id (expected: "id field present", actual: "id field missing")
✗ has missionName (expected: "missionName field present", actual: "missionName field missing")
✓ 201 Created (12ms)

Record a timeout event in test results.

timeout(message: string, durationMs: number): void
  • message (string): Timeout description
  • durationMs (number): Duration in milliseconds
const start = Date.now();
const response = await utils.request('POST http://localhost:3000/api/v1/launches', {
body: {
/* ... */
},
headers: { 'content-type': 'application/json' },
});
const duration = Date.now() - start;
if (duration > 1000) {
utils.timeout('Launch creation took too long', duration);
}

Generate a random alphanumeric string.

randomString(length?: number): string
  • length (number, optional): String length (default: 10)

Random string containing letters (a-z, A-Z) and numbers (0-9)

const username = utils.randomString(); // "k8jF2mN9pL" (10 chars)
const password = utils.randomString(16); // "Lm8Np6Oq1sTk4Jh7" (16 chars)
const id = utils.randomString(32); // 32-character string

Use cases:

  • Generating unique usernames
  • Creating random passwords
  • Generating unique IDs
  • Creating random data for tests