API Hooks
Why API Hooks?
In API testing, modifying requests dynamically before sending and processing responses after receiving is essential for handling real-world scenarios. Without these capabilities, tests can become rigid and fail to address dynamic requirements. API Hooks allow you to:
-
Modify Requests Dynamically:
- Encrypt request data before sending.
- Apply dynamic query parameters or headers based on runtime configurations, such as
prettyPrint=true
.
-
Modify and Extract Response Data:
- Decrypt encrypted responses for validation.
- Transform XML responses into JSON for easier assertions.
- Apply complex validations that go beyond simple assertions.
API Hooks solve these challenges by injecting custom logic at specific points in the request lifecycle, enhancing test flexibility and accuracy.
Hook Types
beforeRequest
Hook
This hook runs before the request is sent, allowing you to modify the request and access contextual data.
Accessible APIs:
$context
: Shared variables for the test flow.$request
: The request object (modifiable).
Example Scenario: Add Dynamic Authentication Headers
async function beforeRequest() {
const authToken = $context.variables.authToken; // Fetch token from context
if (!authToken) {
throw new Error("Authentication token is missing!");
}
$request.headers["Authorization"] = `Bearer ${authToken}`; // Add header
}
afterResponse
Hook
This hook runs after the response is received, enabling you to validate or transform data, and add assertions.
Accessible APIs:
$context
: Shared variables for the test flow.$response
: The response object (modifiable).$request
(read-only): The original request object.$addAssertionResult
: Add custom assertions.
Example Scenario: Validate JWT Token Format in the Response
async function afterResponse() {
const token = $response.body.token; // Extract token from response body
const jwtRegex = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$/;
if (jwtRegex.test(token)) {
$addAssertionResult({ passed: true, message: "Valid JWT token format." });
} else {
$addAssertionResult({
passed: false,
message: "Invalid JWT token format.",
});
}
}
Hook Levels and Execution Order
Each level can enable multiple hooks, forming a composition pattern that allows you to design modular and reusable hooks. This approach helps break down complex logic into smaller, focused components for better maintainability and reusability.
Hooks can be defined at various levels for granular control:
- Single API Level: Hook specific to an individual API node.
- Test Case Level: Hook applied to all APIs in a test case.
- Folder Level: Hook applied to all test cases in a folder.
- Global Level (Coming Soon): Hook applied to all test cases in the project.
Execution Order:
beforeRequest
: Global → Folder → Test Case → API.afterResponse
: API → Test Case → Folder → Global.
Coming Soon: We will support more flexible execution orders in a future release.
Examples for Each Level
Single API Level
Add a timestamp to a specific API request:
async function beforeRequest($context, $request) {
$request.headers["X-Timestamp"] = new Date().toISOString();
}
Test Case Level
Validate all responses in a test case for successful status codes:
async function afterResponse() {
const successCodes = [200, 201, 202, 204];
if (successCodes.includes($response.status)) {
$addAssertionResult({
passed: true,
message: `Response status ${$response.status} is successful.`
});
} else {
$addAssertionResult({
passed: false,
message: `Unexpected status: ${$response.status}`,
});
}
}
Folder Level
Encrypt all request payloads in a folder before sending:
async function beforeRequest() {
if ($request.body) {
$request.body = $$EncryptUtils.encryptPayload(
$request.body,
$context.variables.encryptionKey
);
}
}
Tips for Effective Hook Usage
- Chaining Logic: Chain logic across levels by setting headers at the folder level and modifying them at the API level.
- Using Context Variables: Use
$context
to share and store data across hooks for consistent test execution. - Error Handling: Use
throw new Error("Message")
to fail tests with clear error messages. - Performance: Keep hooks lightweight and avoid unnecessary operations.
- Debugging: Use
console.log()
sparingly and remove it before production.
Registering API Hooks from External Libraries
API Hooks can be written directly within the web editor or registered from an external library. This allows developers to write hook logic in their preferred IDE, leverage AI assistance, and include dependencies from the npm ecosystem. Hooks registered from external libraries function the same way as those written in the web editor.
For more details on setting up and registering hooks from external libraries, refer to the External Library Guide.
Next Steps
Start using API Hooks to enhance your testing workflows with dynamic modifications and validations. Experiment with different levels to optimize your test automation strategies.