import test from "node:test"; import assert from "node:assert/strict"; import { getAdapter, normalizeUrl } from "../src/ingest/adapters/index.js"; const RSS = ` Test Feed https://example.com/blog First Post https://example.com/posts/first?utm_source=feed Some html description

]]>
Relative Link /posts/relative Relative one Atom style Atom styled link
`; test("rss adapter resolves each item's own link, not the feed url", async () => { // 保留原始 fetch:把 RSS 内容喂进去 const realFetch = globalThis.fetch; globalThis.fetch = async () => new Response(RSS, { status: 200 }); try { const items = await getAdapter("rss").fetch("https://example.com/feed.xml"); assert.equal(items.length, 3); assert.equal(items[0].title, "First Post"); // 关键:url 必须是条目的链接,而不是 https://example.com/feed.xml assert.equal(items[0].url, "https://example.com/posts/first"); // utm_ 参数被去掉 assert.ok(!items[0].url.includes("utm_source")); assert.match(items[0].description, /Some html description/); // 相对链接按 feed 地址解析成绝对地址 assert.equal(items[1].url, "https://example.com/posts/relative"); // 形式也能取到 assert.equal(items[2].url, "https://example.com/posts/atom"); assert.ok(items.every((i) => i.url !== "https://example.com/feed.xml")); } finally { globalThis.fetch = realFetch; } }); test("normalizeUrl drops tracking params and trailing slash", () => { assert.equal(normalizeUrl("https://a.com/x/?utm_src=b#frag"), "https://a.com/x"); assert.equal(normalizeUrl("https://a.com/x"), "https://a.com/x"); });