mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-16 20:02:45 +03:00
Validado numa worktree combinada com a onda de dashboard/monitoring desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-api-typecheck OK (289), check-file-size OK após rebaseline, 130/131 nos testes focados — a falha restante é asserção de tempo de parede sob carga, verde 6/6 isolada. Paginar e completar o stream em `GET /v1/models` é a correção certa para catálogo grande: um payload único que cresce com o número de providers vira timeout silencioso no cliente, não erro.
80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import {
|
|
applyCatalogPage,
|
|
CATALOG_BODY_CHUNK_BYTES,
|
|
catalogJsonResponse,
|
|
catalogPageCacheKey,
|
|
catalogStringResponse,
|
|
parseCatalogPage,
|
|
} from "../../src/app/api/v1/models/catalogPagination.ts";
|
|
|
|
function req(url: string): Request {
|
|
return new Request(url);
|
|
}
|
|
|
|
test("parseCatalogPage treats missing params as a full list", () => {
|
|
assert.deepEqual(parseCatalogPage(req("http://local/v1/models")), { after: null, limit: null });
|
|
});
|
|
|
|
test("parseCatalogPage accepts OpenAI-compatible limit and after", () => {
|
|
assert.deepEqual(parseCatalogPage(req("http://local/v1/models?limit=20&after=gpt-4o")), {
|
|
after: "gpt-4o",
|
|
limit: 20,
|
|
});
|
|
});
|
|
|
|
test("parseCatalogPage ignores non-positive limits", () => {
|
|
assert.deepEqual(parseCatalogPage(req("http://local/v1/models?limit=0&after=")), {
|
|
after: null,
|
|
limit: null,
|
|
});
|
|
});
|
|
|
|
test("applyCatalogPage slices after a cursor and reports has_more", () => {
|
|
const models = [{ id: "a" }, { id: "b" }, { id: "c" }, { id: "d" }];
|
|
const page = applyCatalogPage(models, { after: "b", limit: 1 });
|
|
assert.deepEqual(page, { models: [{ id: "c" }], hasMore: true, lastId: "c" });
|
|
});
|
|
|
|
test("applyCatalogPage returns the remainder when limit exceeds the tail", () => {
|
|
const models = [{ id: "a" }, { id: "b" }, { id: "c" }];
|
|
const page = applyCatalogPage(models, { after: "b", limit: 10 });
|
|
assert.deepEqual(page, { models: [{ id: "c" }], hasMore: false, lastId: "c" });
|
|
});
|
|
|
|
test("catalogPageCacheKey distinguishes pages so cached bodies do not mix", () => {
|
|
assert.notEqual(
|
|
catalogPageCacheKey({ after: null, limit: 10 }),
|
|
catalogPageCacheKey({ after: "gpt-4o", limit: 10 })
|
|
);
|
|
});
|
|
|
|
test("catalogJsonResponse sets Content-Length to the full UTF-8 byte count", async () => {
|
|
const body = { object: "list", data: [{ id: "x", name: "café" }] };
|
|
const response = catalogJsonResponse(body, {});
|
|
const payload = JSON.stringify(body);
|
|
assert.equal(response.headers.get("content-length"), String(Buffer.byteLength(payload)));
|
|
assert.equal(await response.text(), payload);
|
|
});
|
|
|
|
test("catalogStringResponse streams large bodies without cutting mid-JSON", async () => {
|
|
const payload = JSON.stringify({
|
|
object: "list",
|
|
data: Array.from({ length: 80 }, (_, i) => ({
|
|
id: `model-${i}`,
|
|
filler: "x".repeat(2_000),
|
|
})),
|
|
});
|
|
assert.ok(Buffer.byteLength(payload) > CATALOG_BODY_CHUNK_BYTES);
|
|
|
|
const response = catalogStringResponse(payload, {});
|
|
assert.equal(response.headers.get("content-length"), String(Buffer.byteLength(payload)));
|
|
const text = await response.text();
|
|
assert.equal(text.length, payload.length);
|
|
assert.equal(text, payload);
|
|
const parsed = JSON.parse(text) as { data: unknown[] };
|
|
assert.equal(parsed.data.length, 80);
|
|
});
|