alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
194 lines (163 loc) • 5.53 kB
text/typescript
import { $pipeline, Alepha } from "alepha";
import { describe, test } from "vitest";
import { $timeout } from "../primitives/$timeout.ts";
import { DateTimeProvider } from "../providers/DateTimeProvider.ts";
// -----------------------------------------------------------------------------------------------------------------
// $timeout — core behavior
// -----------------------------------------------------------------------------------------------------------------
describe("$timeout", () => {
test("handler that completes before deadline returns normally", async ({
expect,
}) => {
const alepha = Alepha.create();
class TestService {
fn = $pipeline({
use: [$timeout([1, "seconds"])],
handler: async () => "ok",
});
}
const svc = alepha.inject(TestService);
expect(await svc.fn()).toBe("ok");
});
test("handler that exceeds deadline rejects", async ({ expect }) => {
const alepha = Alepha.create();
const dt = alepha.inject(DateTimeProvider);
class TestService {
fn = $pipeline({
use: [$timeout([50, "milliseconds"])],
handler: async () => {
await dt.wait([200, "milliseconds"]);
return "too late";
},
});
}
const svc = alepha.inject(TestService);
await expect(svc.fn()).rejects.toThrowError(
"$timeout: handler exceeded deadline",
);
});
test("handler return value is preserved", async ({ expect }) => {
const alepha = Alepha.create();
class TestService {
fn = $pipeline({
use: [$timeout([1, "seconds"])],
handler: async () => ({ data: [1, 2, 3] }),
});
}
const svc = alepha.inject(TestService);
expect(await svc.fn()).toEqual({ data: [1, 2, 3] });
});
test("handler arguments are passed through", async ({ expect }) => {
const alepha = Alepha.create();
class TestService {
fn = $pipeline({
use: [$timeout([1, "seconds"])],
handler: async (a: number, b: number) => a + b,
});
}
const svc = alepha.inject(TestService);
expect(await svc.fn(3, 4)).toBe(7);
});
test("handler errors propagate (not masked by timeout)", async ({
expect,
}) => {
const alepha = Alepha.create();
class TestService {
fn = $pipeline({
use: [$timeout([1, "seconds"])],
handler: async () => {
throw new Error("Handler failed");
},
});
}
const svc = alepha.inject(TestService);
await expect(svc.fn()).rejects.toThrowError("Handler failed");
});
test("accepts number (milliseconds) as duration", async ({ expect }) => {
const alepha = Alepha.create();
class TestService {
fn = $pipeline({
use: [$timeout(1000)],
handler: async () => "ok",
});
}
const svc = alepha.inject(TestService);
expect(await svc.fn()).toBe("ok");
});
});
// -----------------------------------------------------------------------------------------------------------------
// $timeout — metadata
// -----------------------------------------------------------------------------------------------------------------
describe("$timeout metadata", () => {
test("has middleware metadata with name and options", ({ expect }) => {
const alepha = Alepha.create();
class TestService {
fn = $pipeline({
use: [$timeout([30, "seconds"])],
handler: async () => "ok",
});
}
const svc = alepha.inject(TestService);
const meta = svc.fn.middlewares;
expect(meta).toHaveLength(1);
expect(meta[0]).toEqual({
name: "$timeout",
options: { duration: [30, "seconds"] },
});
});
});
// -----------------------------------------------------------------------------------------------------------------
// $timeout — composition
// -----------------------------------------------------------------------------------------------------------------
describe("$timeout composition", () => {
test("composes with other middleware", async ({ expect }) => {
const calls: string[] = [];
const alepha = Alepha.create();
class TestService {
fn = $pipeline({
use: [
$timeout([1, "seconds"]),
// Inline logging middleware
((handler: any) =>
async (...args: any[]) => {
calls.push("log:before");
const result = await handler(...args);
calls.push("log:after");
return result;
}) as any,
],
handler: async () => {
calls.push("handler");
return "ok";
},
});
}
const svc = alepha.inject(TestService);
await svc.fn();
expect(calls).toEqual(["log:before", "handler", "log:after"]);
});
test("timeout fires even when inner middleware is slow", async ({
expect,
}) => {
const alepha = Alepha.create();
const dt = alepha.inject(DateTimeProvider);
class TestService {
fn = $pipeline({
use: [
$timeout([50, "milliseconds"]),
// Slow middleware that delays before calling handler
((handler: any) =>
async (...args: any[]) => {
await dt.wait([200, "milliseconds"]);
return handler(...args);
}) as any,
],
handler: async () => "ok",
});
}
const svc = alepha.inject(TestService);
await expect(svc.fn()).rejects.toThrowError(
"$timeout: handler exceeded deadline",
);
});
});