Files
OmniRoute/tests/unit/release-notes.test.ts
Praveen K Palaniswamy 65e81158ab fix(ollama): route models by advertised capability (#11088)
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host.

Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean.

Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
2026-08-23 11:45:01 -03:00

216 lines
6.3 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
const releaseNotes = await import("../../src/shared/utils/releaseNotes.ts");
test("parseActiveNewsPayload keeps the legacy singular contract", () => {
assert.deepEqual(
releaseNotes.parseActiveNewsPayload({
active: true,
title: "Launch",
message: "A short announcement",
link: "https://github.com/diegosouzapw/tOmni",
linkLabel: "Learn more",
icon: "campaign",
}),
{
id: "legacy-8d301d21",
active: true,
publishedAt: "1970-01-01T00:00:00.000Z",
title: "Launch",
message: "A short announcement",
link: "https://github.com/diegosouzapw/tOmni",
linkLabel: "Learn more",
icon: "campaign",
}
);
assert.equal(releaseNotes.parseActiveNewsPayload({ active: false }), null);
assert.equal(
releaseNotes.parseActiveNewsPayload({
active: true,
title: "Unsafe icon",
message: "Invalid icon names are rejected",
icon: "campaign<script>",
}),
null
);
});
test("parseNewsPayload validates the closed v2 feed and preserves inactive entries", () => {
const payload = {
schemaVersion: 2,
items: [
{
id: "radar-launch-2026-08",
active: false,
publishedAt: "2026-08-09T12:00:00.000Z",
text: {
en: { title: "Radar", message: "Opt-in catalog", linkLabel: "Learn more" },
"pt-BR": { title: "Radar", message: "Catálogo opt-in", linkLabel: "Saiba mais" },
},
link: "https://radar.omniroute.online/planos",
icon: "radar",
},
],
};
assert.deepEqual(releaseNotes.parseNewsPayload(payload), payload.items);
assert.deepEqual(releaseNotes.parseNewsPayload({ ...payload, unexpected: true }), []);
assert.deepEqual(
releaseNotes.parseNewsPayload({
...payload,
items: [{ ...payload.items[0], link: "http://radar.omniroute.online/planos" }],
}),
[]
);
assert.deepEqual(
releaseNotes.parseNewsPayload({
...payload,
items: [...payload.items, payload.items[0]],
}),
[]
);
});
test("listActiveNews localizes, filters future entries and sorts newest first", () => {
const payload = {
schemaVersion: 2,
items: [
{
id: "older",
active: true,
publishedAt: "2026-08-08T12:00:00.000Z",
text: { en: { title: "Older", message: "English" } },
icon: "info",
},
{
id: "newer",
active: true,
publishedAt: "2026-08-09T12:00:00.000Z",
text: {
en: { title: "Newer", message: "English" },
"pt-BR": { title: "Mais recente", message: "Português" },
},
icon: "campaign",
},
{
id: "future",
active: true,
publishedAt: "2026-08-11T12:00:00.000Z",
text: { en: { title: "Future", message: "Not published yet" } },
icon: "campaign",
},
{
id: "inactive",
active: false,
publishedAt: "2026-08-09T13:00:00.000Z",
text: { en: { title: "Inactive", message: "Hidden" } },
icon: "campaign",
},
],
};
const news = releaseNotes.listActiveNews(payload, "pt-BR", new Date("2026-08-10T00:00:00.000Z"));
assert.deepEqual(
news.map((item: { id: string; title: string; message: string }) => [
item.id,
item.title,
item.message,
]),
[
["newer", "Mais recente", "Português"],
["older", "Older", "English"],
]
);
assert.equal(
releaseNotes.listActiveNews(payload, "pt-PT", new Date("2026-08-10T00:00:00.000Z"))[0]?.message,
"English"
);
});
test("selectActiveNews skips dismissed ids while retaining new announcements", () => {
const payload = {
schemaVersion: 2,
items: [
{
id: "newer",
active: true,
publishedAt: "2026-08-09T12:00:00.000Z",
text: { en: { title: "Newer", message: "English" } },
icon: "campaign",
},
{
id: "older",
active: true,
publishedAt: "2026-08-08T12:00:00.000Z",
text: { en: { title: "Older", message: "English" } },
icon: "campaign",
},
],
};
assert.equal(
releaseNotes.selectActiveNews(
payload,
"en",
new Set(["newer"]),
new Date("2026-08-10T00:00:00.000Z")
)?.id,
"older"
);
});
test("dismissed announcement ids are sanitized, deduplicated and bounded", () => {
assert.deepEqual(
[...releaseNotes.parseDismissedNewsIds('["valid-id","valid-id","<script>",4]')],
["valid-id"]
);
assert.equal(releaseNotes.parseDismissedNewsIds("not-json").size, 0);
const ids = Array.from({ length: 60 }, (_, index) => `announcement-${index}`);
const serialized = releaseNotes.serializeDismissedNewsIds(ids);
assert.equal(JSON.parse(serialized).length, 50);
assert.deepEqual(JSON.parse(serialized).slice(-2), ["announcement-58", "announcement-59"]);
});
test("fetchNewsPayload is GET-only and keeps network failures inert", async () => {
let captured: { url: string; init: RequestInit } | undefined;
const payload = { schemaVersion: 2, items: [] };
const result = await releaseNotes.fetchNewsPayload(async (url: string, init: RequestInit) => {
captured = { url, init };
return { ok: true, json: async () => payload };
});
assert.deepEqual(result, payload);
assert.equal(captured?.url, releaseNotes.NEWS_JSON_URL);
assert.equal(captured?.init.method, undefined);
assert.equal(captured?.init.credentials, "omit");
assert.equal(
await releaseNotes.fetchNewsPayload(async () => {
throw new Error("offline");
}),
null
);
assert.equal(
await releaseNotes.fetchNewsPayload(async () => ({ ok: false, json: async () => payload })),
null
);
});
test("getLatestChangelogMarkdown keeps the title and the ten latest releases", () => {
const versions = Array.from({ length: 12 }, (_, index) => {
const version = `1.0.${12 - index}`;
return `## [${version}] - 2026-04-${String(28 - index).padStart(2, "0")}\n\n### Bug Fixes\n- Fix ${version}`;
});
const markdown = ["# Changelog", ...versions].join("\n\n");
const sliced = releaseNotes.getLatestChangelogMarkdown(markdown, 10);
assert.match(sliced, /^# Changelog/);
assert.equal((sliced.match(/^## \[/gm) || []).length, 10);
assert.match(sliced, /## \[1\.0\.12\]/);
assert.match(sliced, /## \[1\.0\.3\]/);
assert.doesNotMatch(sliced, /## \[1\.0\.2\]/);
});