Testing

Typeweaver projects are usually easiest to test in layers. You do not need special public Typeweaver testing packages for that. Your normal test framework is enough.

What to test

The most useful tests usually cover four things:

  1. spec-level expectations for important contract shapes
  2. generated validators for request and response boundaries
  3. generated clients for request and response behavior
  4. handlers for business logic and returned responses

Test validators directly

Validators are great small tests because they prove the contract still accepts and rejects what you expect.

Vitest example

import { describe, expect, it } from "vitest";
import { GetTodoRequestValidator } from "../api/generated";
import { HttpMethod } from "@rexeus/typeweaver-core";

describe("GetTodoRequestValidator", () => {
  it("accepts a valid request", () => {
    const validator = new GetTodoRequestValidator();

    const result = validator.safeValidate({
      method: HttpMethod.GET,
      path: "/todos/todo_123",
      param: {
        todoId: "todo_123",
      },
    });

    expect(result.isValid).toBe(true);
  });

  it("rejects a request with missing params", () => {
    const validator = new GetTodoRequestValidator();

    const result = validator.safeValidate({
      method: HttpMethod.GET,
      path: "/todos",
      param: {},
    });

    expect(result.isValid).toBe(false);
  });
});

Use the same idea in Jest if that is what your project already uses.

Test generated clients with a mocked fetch

Generated clients are easiest to test by mocking the transport and asserting on the typed response.

import { expect, it, vi } from "vitest";
import { GetTodoRequestCommand, TodoClient } from "../api/generated";

it("returns a typed success response", async () => {
  const fetchFn = vi.fn().mockResolvedValue(
    new Response(
      JSON.stringify({
        id: "todo_123",
        title: "Ship docs",
        completed: false,
      }),
      {
        status: 200,
        headers: {
          "Content-Type": "application/json",
        },
      }
    )
  );

  const client = new TodoClient({
    baseUrl: "https://api.example.com",
    fetchFn,
  });

  const response = await client.send(
    new GetTodoRequestCommand({
      param: {
        todoId: "todo_123",
      },
    })
  );

  expect(response.type).toBe("GetTodoSuccess");
});

This catches contract mismatches without needing a real server.

Test handlers as normal application code

Handlers are just functions with typed input and typed responses. Test them the same way you would test any business logic.

import { expect, it } from "vitest";
import { createGetTodoSuccessResponse } from "../api/generated";

const handleGetTodoRequest = async ({
  param,
}: {
  param: { todoId: string };
}) => {
  return createGetTodoSuccessResponse({
    body: {
      id: param.todoId,
      title: "Ship docs",
      completed: false,
    },
  });
};

it("returns the todo when it exists", async () => {
  const response = await handleGetTodoRequest({
    param: {
      todoId: "todo_123",
    },
  });

  expect(response).toEqual(
    createGetTodoSuccessResponse({
      body: {
        id: "todo_123",
        title: "Ship docs",
        completed: false,
      },
    })
  );
});

Keep testing practical

You usually do not need a separate test for every generated type. Focus on the places where drift would hurt:

  • required request fields
  • important response branches
  • client handling of normal success and error responses
  • handler behavior for your main business cases

Was this page helpful?