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 JSON request bodyfile(description: string, descriptor: { path?: string; buffer?: Buffer; stream?: Readable; filename?: string; contentType?: string }): Send a single binary payload. Provide exactly one ofpath,buffer, orstream. Mutually exclusive withbody().file(requestFile: DSLRequestFile): Advanced form for custom integrations (expects the same structure as the descriptor above).header(headers: object): Set request headers (Content-Type is managed automatically for.file()).pathParam(params: object): Set path parametersqueryParam(params: object): Set query parameters
apiDoc
    .test()
    .req()
    .file("업로드할 파일", {
        stream: fs.createReadStream(filePath),
        filename: "sample.bin",
        contentType: "application/octet-stream",
    })
    .res()
    .status(HttpStatus.CREATED)
res()
Defines API response attributes. If the actual API response differs, the test will fail.
status(status: HttpStatus): Set expected response status- See all 
HttpStatusvalues 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,
}