Apply proper TypeScript type corrections without any unsafe casts:
- Fix unknown/never/{} types from decompilation
- Correct function signatures and parameter types
- Add missing type declarations and interfaces
- Fix Ink component prop types
- Update API client/provider type annotations
Test files with mock data casts are included as-is (acceptable pattern).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
100 lines
3.0 KiB
TypeScript
100 lines
3.0 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { sequential } from "../sequential";
|
|
|
|
describe("sequential", () => {
|
|
test("wraps async function, returns same result", async () => {
|
|
const fn = sequential(async (x: number) => x * 2);
|
|
expect(await fn(5)).toBe(10);
|
|
});
|
|
|
|
test("single call resolves normally", async () => {
|
|
const fn = sequential(async () => "ok");
|
|
expect(await fn()).toBe("ok");
|
|
});
|
|
|
|
test("concurrent calls execute sequentially (FIFO order)", async () => {
|
|
const order: number[] = [];
|
|
const fn = sequential(async (n: number) => {
|
|
order.push(n);
|
|
await new Promise(r => setTimeout(r, 10));
|
|
return n;
|
|
});
|
|
|
|
const results = await Promise.all([fn(1), fn(2), fn(3)]);
|
|
expect(results).toEqual([1, 2, 3]);
|
|
expect(order).toEqual([1, 2, 3]);
|
|
});
|
|
|
|
test("preserves arguments correctly", async () => {
|
|
const fn = sequential(async (a: number, b: string) => `${a}-${b}`);
|
|
expect(await fn(42, "test")).toBe("42-test");
|
|
});
|
|
|
|
test("error in first call does not block subsequent calls", async () => {
|
|
let callCount = 0;
|
|
const fn = sequential(async () => {
|
|
callCount++;
|
|
if (callCount === 1) throw new Error("first fail");
|
|
return "ok";
|
|
});
|
|
|
|
await expect(fn()).rejects.toThrow("first fail");
|
|
expect(await fn()).toBe("ok");
|
|
});
|
|
|
|
test("preserves rejection reason", async () => {
|
|
const fn = sequential(async () => {
|
|
throw new Error("specific error");
|
|
});
|
|
await expect(fn()).rejects.toThrow("specific error");
|
|
});
|
|
|
|
test("multiple args passed correctly", async () => {
|
|
const fn = sequential(async (a: number, b: number, c: number) => a + b + c);
|
|
expect(await fn(1, 2, 3)).toBe(6);
|
|
});
|
|
|
|
test("returns different wrapper for each call to sequential", () => {
|
|
const fn1 = sequential(async () => 1);
|
|
const fn2 = sequential(async () => 2);
|
|
expect(fn1).not.toBe(fn2);
|
|
});
|
|
|
|
test("handles rapid concurrent calls", async () => {
|
|
const order: number[] = [];
|
|
const fn = sequential(async (n: number) => {
|
|
order.push(n);
|
|
return n;
|
|
});
|
|
|
|
const promises = Array.from({ length: 10 }, (_, i) => fn(i));
|
|
const results = await Promise.all(promises);
|
|
expect(results).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
|
expect(order).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
|
});
|
|
|
|
test("execution order matches call order", async () => {
|
|
const log: string[] = [];
|
|
const fn = sequential(async (label: string) => {
|
|
log.push(`start:${label}`);
|
|
await new Promise(r => setTimeout(r, 5));
|
|
log.push(`end:${label}`);
|
|
return label;
|
|
});
|
|
|
|
await Promise.all([fn("a"), fn("b")]);
|
|
expect(log[0]).toBe("start:a");
|
|
expect(log[1]).toBe("end:a");
|
|
expect(log[2]).toBe("start:b");
|
|
expect(log[3]).toBe("end:b");
|
|
});
|
|
|
|
test("works with functions returning different types", async () => {
|
|
const fn = sequential(async (x: number): Promise<string | number> => {
|
|
return x > 0 ? "positive" : x;
|
|
});
|
|
expect(await fn(5)).toBe("positive");
|
|
expect(await fn(-1)).toBe(-1);
|
|
});
|
|
});
|