itdoc Interface
This page comprehensively describes the itdoc
interface.
describeAPI()
The primary function for defining and documenting API endpoints.
Signature:
function describeAPI(
method: HttpMethod,
path: string,
options: ApiDocOptions,
app: Express.Application | any,
testCallback: (apiDoc: RootBuilder) => void,
): void
Example:
describeAPI(
HttpMethod.GET,
"/users",
{
summary: "Retrieve All Users",
tag: "User",
description: "Returns a list of all users in the system.",
},
app,
(apiDoc) => {
// Define your test cases here.
},
);
Parameters
method
The HTTP method of the API.
See examples here.
path
The URL path for the API endpoint.
Example: /users
If the path contains a PathVariable
, define it as shown below and set values with pathParam()
in req().
Example: /users/{id}
options
Configuration options for API documentation including summary, tag, and description.
Option | Description | Example | Required |
---|---|---|---|
summary | A brief summary of the API | "User Registration API" | x |
tag | Tag for grouping the API | "User" | x |
description | Detailed description of the API | "Returns a list of all users in the system." | x |
app
Express application instance used for testing.
itdoc
uses supertest to simulate HTTP requests. Thus, the app
parameter must be an Express instance compatible with supertest.
Example:
-
app.js
import express from "express";
const app = express()
app.use(express.json())
app.post("/signup", function (req, res) {
const { username, password } = req.body
if (!username || !password) {
return res.status(400).json({
error: "username and password are required",
})
}
if (password.length < 8) {
return res.status(400).json({
error: "password must be at least 8 characters",
})
}
// Skip user creation logic for brevity
return res.status(201).json()
})
export default app -
Test Code
import app from "./app.js"
describeAPI(
HttpMethod.GET,
"/signup",
{
summary: "Sign Up API",
description: "Registers a new user with username and password.",
},
app,
(apiDoc) => {},
)
testCallback
Callback function for defining tests for the API endpoint.
Inside this callback, you use itDoc()
to create test cases.
itDoc()
Defines individual test cases within a describeAPI
block.
Signature:
function itDoc(description: string, testFn: () => RootBuilder | Promise<RootBuilder>): void
Parameters:
description
: Description of the test case.testFn
: The actual test case function.
testFn
must return or execute the apiDoc
object received from describeAPI.
Example:
itDoc("Successfully retrieves all users", () => {
return apiDoc
.test()
.req()
.queryParam({ page: 1, limit: 10 })
.res()
.status(HttpStatus.OK)
.body({
users: field("List of users", [{ id: 1, name: "John" }]),
total: field("Total user count", 1),
});
});
apiDoc
An object for setting up test requests and expected responses.
Chain methods in the following mandatory order: test()
-> req()
-> res()
.
apiDoc
.test()
.req()
.body({...}) // Request body
.header({...}) // Request headers
.pathParam({...}) // Path parameters
.queryParam({...}) // Query parameters
.res()
.status(...) // Expected response status
.header({...}) // Expected response headers
.body({...}); // Expected response body
test()
Must be called in every test case.
-
prettyPrint()
: Pretty prints the request/response for the test.apiDoc
.test()
.prettyPrint()
.req()
...
req()
Defines values used in API requests.
body(body: object)
: Set request bodyheader(headers: object)
: Set request headerspathParam(params: object)
: Set path parametersqueryParam(params: object)
: Set query parametersexpectStatus(status: HttpStatus)
: Set expected response status (Required)
res()
Defines API response attributes. If the actual API response differs, the test will fail.
status(status: HttpStatus)
: Set expected response status- See all
HttpStatus
values here.
- See all
body(body: object)
: Set expected response bodyheader(headers: object)
: Set expected response headers
field()
Used for documenting fields in request and response bodies.
Signature:
function field<T>(description: string, value: T | ((val: any) => T)): T
Parameters:
description
: Field descriptionvalue
: Actual value or validation callback
Example
Using fixed values
.res()
.body({
token: field("JWT token", "eyJhbGciOi...")
})
Using callbacks (validation)
.res()
.body({
token: field("JWT token", val => {
const jwtPattern = /^([A-Za-z0-9\-_]+)\.([A-Za-z0-9\-_]+)\.([A-Za-z0-9\-_]+)$/;
if (!jwtPattern.test(val)) throw new Error(`Invalid JWT token format: ${val}`);
return val;
}),
})
You can omit field()
and directly use values.
However, omitting field()
means the field description won't be documented, so using field()
is recommended.
.req()
.body({ username: "john_doe" });
Enumerations
HttpMethod
Enumeration representing HTTP methods.
enum HttpMethod {
GET = "GET",
POST = "POST",
PUT = "PUT",
DELETE = "DELETE",
PATCH = "PATCH",
HEAD = "HEAD",
OPTIONS = "OPTIONS",
TRACE = "TRACE",
CONNECT = "CONNECT",
}
HttpStatus
Enumeration representing HTTP status codes.
export enum HttpStatus {
CONTINUE = 100,
SWITCHING_PROTOCOLS = 101,
PROCESSING = 102,
EARLY_HINTS = 103,
OK = 200,
CREATED = 201,
ACCEPTED = 202,
NON_AUTHORITATIVE_INFORMATION = 203,
NO_CONTENT = 204,
RESET_CONTENT = 205,
PARTIAL_CONTENT = 206,
MULTI_STATUS = 207,
ALREADY_REPORTED = 208,
IM_USED = 226,
MULTIPLE_CHOICES = 300,
MOVED_PERMANENTLY = 301,
FOUND = 302,
SEE_OTHER = 303,
NOT_MODIFIED = 304,
USE_PROXY = 305,
TEMPORARY_REDIRECT = 307,
PERMANENT_REDIRECT = 308,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
PAYMENT_REQUIRED = 402,
FORBIDDEN = 403,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
NOT_ACCEPTABLE = 406,
PROXY_AUTHENTICATION_REQUIRED = 407,
REQUEST_TIMEOUT = 408,
CONFLICT = 409,
GONE = 410,
LENGTH_REQUIRED = 411,
PRECONDITION_FAILED = 412,
PAYLOAD_TOO_LARGE = 413,
URI_TOO_LONG = 414,
UNSUPPORTED_MEDIA_TYPE = 415,
RANGE_NOT_SATISFIABLE = 416,
EXPECTATION_FAILED = 417,
IM_A_TEAPOT = 418,
MISDIRECTED_REQUEST = 421,
UNPROCESSABLE_ENTITY = 422,
LOCKED = 423,
FAILED_DEPENDENCY = 424,
TOO_EARLY = 425,
UPGRADE_REQUIRED = 426,
PRECONDITION_REQUIRED = 428,
TOO_MANY_REQUESTS = 429,
REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
UNAVAILABLE_FOR_LEGAL_REASONS = 451,
INTERNAL_SERVER_ERROR = 500,
NOT_IMPLEMENTED = 501,
BAD_GATEWAY = 502,
SERVICE_UNAVAILABLE = 503,
GATEWAY_TIMEOUT = 504,
HTTP_VERSION_NOT_SUPPORTED = 505,
VARIANT_ALSO_NEGOTIATES = 506,
INSUFFICIENT_STORAGE = 507,
LOOP_DETECTED = 508,
NOT_EXTENDED = 510,
NETWORK_AUTHENTICATION_REQUIRED = 511,
}