Testing
Testing Fragno fragments
Fragno provides comprehensive testing utilities to help you test your fragments without running a
server. The createFragmentForTest function creates a test instance with type-safe route handling
and response parsing.
Creating a Test Fragment
import { createFragmentForTest } from "@fragno-dev/core/test";
import { routes } from "./fragment-definition";
const fragment = createFragmentForTest(myFragmentDefinition, routes, {
config: { apiKey: "test-key" },
// Optional: override dependencies
deps: { httpClient: mockHttpClient },
// Optional: override services
services: { getUserById: mockGetUserById },
});Testing Route Handlers
The callRoute method executes routes by method and path, returning a typed discriminated union:
const response = await fragment.callRoute("POST", "/users/:id", {
pathParams: { id: "123" },
body: { name: "John" },
query: { filter: "active" },
headers: { authorization: "Bearer token" },
});
// Response is a discriminated union
assert(response.type === "json");
expect(response.status).toBe(200);
expect(response.data).toEqual({ id: "123", name: "John" });The method and path parameters are strongly typed based on your fragment's routes, providing autocomplete and type checking.
Response Types
The callRoute method returns a discriminated union with four possible types:
JSON Response
assert(response.type === "json");
expect(response.status).toBe(200);
expect(response.headers).toBeInstanceOf(Headers);
expect(response.data).toEqual({ id: "123", name: "John" });Streaming Response
assert(response.type === "jsonStream");
const items = [];
for await (const item of response.stream) {
items.push(item);
}
expect(items).toEqual([...expected]);Empty Response
assert(response.type === "empty");
expect(response.status).toBe(204);Error Response
assert(response.type === "error");
expect(response.status).toBe(404);
expect(response.error).toEqual({
message: "Not found",
code: "NOT_FOUND",
});Testing Database Fragments
For Fragments that use @fragno-dev/db, use createDatabaseFragmentForTest from @fragno-dev/test
to automatically set up an in-memory database with migrations:
import { createDatabaseFragmentForTest } from "@fragno-dev/test";
const { fragment, test } = await createDatabaseFragmentForTest(
myDatabaseFragmentDefinition,
routes,
{
adapter: { type: "kysely-sqlite" },
config: { apiKey: "test-key" },
// Optional: migrate to specific schema version (defaults to latest)
migrateToVersion: 2,
},
);
// Access fragment methods as usual
await fragment.services.createUser({ name: "John" });
// Or test routes directly
const response = await fragment.callRoute("POST", "/users", {
body: { name: "John" },
});Cleanup
The test.cleanup() function closes database connections and deletes any database files created
during testing. This is useful in afterAll hooks to clean up resources:
describe("User tests", () => {
const { fragment, test } = await createDatabaseFragmentForTest(authFragmentDefinition, routes, {
adapter: { type: "kysely-sqlite" },
});
afterAll(async () => {
await test.cleanup();
});
it("test 1", async () => {
const response = await fragment.callRoute("POST", "/users", {
body: { name: "Alice" },
});
expect(response.type).toBe("json");
});
});Fragments tested in this way use an in-memory SQLite database with migrations automatically applied. This means that you can directly test the data layer of your Fragment.