Skip to main content

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

tip

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.

OptionDescriptionExampleRequired
summaryA brief summary of the API"User Registration API"x
tagTag for grouping the API"User"x
descriptionDetailed description of the API"Returns a list of all users in the system."x

app

Express application instance used for testing.

info

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.
warning

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.

info

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 body
  • header(headers: object): Set request headers
  • pathParam(params: object): Set path parameters
  • queryParam(params: object): Set query parameters
  • expectStatus(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.
  • body(body: object): Set expected response body
  • header(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 description
  • value: 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;
}),
})
tip

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,
}