This commit is contained in:
13
site/tests/fixtures/podcast-feed.xml
vendored
Normal file
13
site/tests/fixtures/podcast-feed.xml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0">
|
||||
<channel>
|
||||
<title>Irregular Mind</title>
|
||||
<item>
|
||||
<guid>ep-001</guid>
|
||||
<title>Episode One</title>
|
||||
<link>https://example.com/podcast/ep-001</link>
|
||||
<pubDate>Tue, 10 Feb 2026 10:00:00 GMT</pubDate>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
|
||||
17
site/tests/fixtures/youtube-feed.xml
vendored
Normal file
17
site/tests/fixtures/youtube-feed.xml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>YouTube channel feed</title>
|
||||
<entry>
|
||||
<id>yt:video:abc123</id>
|
||||
<title>Test Video One</title>
|
||||
<published>2026-02-09T12:34:56+00:00</published>
|
||||
<link rel="alternate" href="https://www.youtube.com/watch?v=abc123"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>yt:video:def456</id>
|
||||
<title>Test Video Two</title>
|
||||
<published>2026-02-08T10:00:00+00:00</published>
|
||||
<link rel="alternate" href="https://www.youtube.com/watch?v=def456"/>
|
||||
</entry>
|
||||
</feed>
|
||||
|
||||
13
site/tests/fixtures/youtube-videos.json
vendored
Normal file
13
site/tests/fixtures/youtube-videos.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "abc123",
|
||||
"snippet": {
|
||||
"title": "API Video One",
|
||||
"publishedAt": "2026-02-09T12:34:56Z",
|
||||
"thumbnails": { "high": { "url": "https://img.example.com/1.jpg" } }
|
||||
},
|
||||
"statistics": { "viewCount": "12345" }
|
||||
}
|
||||
]
|
||||
}
|
||||
45
site/tests/ingest.test.ts
Normal file
45
site/tests/ingest.test.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { readFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
import Parser from "rss-parser";
|
||||
|
||||
import { normalizePodcastFeedItems } from "../src/lib/ingest/podcast";
|
||||
import { normalizeYoutubeApiVideos, normalizeYoutubeRssFeedItems } from "../src/lib/ingest/youtube";
|
||||
|
||||
const fixturesDir = path.join(process.cwd(), "tests", "fixtures");
|
||||
|
||||
describe("ingestion normalization", () => {
|
||||
it("normalizes YouTube RSS/Atom feed items", async () => {
|
||||
const xml = await readFile(path.join(fixturesDir, "youtube-feed.xml"), "utf8");
|
||||
const parser = new Parser();
|
||||
const feed = await parser.parseString(xml);
|
||||
const items = normalizeYoutubeRssFeedItems(feed.items || [], 10);
|
||||
|
||||
expect(items.length).toBeGreaterThan(0);
|
||||
expect(items[0].source).toBe("youtube");
|
||||
expect(items[0].title).toBeTruthy();
|
||||
expect(items[0].url).toMatch(/youtube\.com/);
|
||||
expect(items[0].publishedAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
|
||||
});
|
||||
|
||||
it("normalizes YouTube API videos and captures view count", async () => {
|
||||
const raw = await readFile(path.join(fixturesDir, "youtube-videos.json"), "utf8");
|
||||
const json = JSON.parse(raw) as any;
|
||||
const items = normalizeYoutubeApiVideos(json.items);
|
||||
|
||||
expect(items).toHaveLength(1);
|
||||
expect(items[0].metrics?.views).toBe(12345);
|
||||
});
|
||||
|
||||
it("normalizes podcast RSS items and ensures ISO dates", async () => {
|
||||
const xml = await readFile(path.join(fixturesDir, "podcast-feed.xml"), "utf8");
|
||||
const parser = new Parser();
|
||||
const feed = await parser.parseString(xml);
|
||||
const items = normalizePodcastFeedItems(feed.items || [], 10);
|
||||
|
||||
expect(items).toHaveLength(1);
|
||||
expect(items[0].source).toBe("podcast");
|
||||
expect(items[0].publishedAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
|
||||
});
|
||||
});
|
||||
31
site/tests/umami-attributes.test.ts
Normal file
31
site/tests/umami-attributes.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { readFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
async function read(rel: string) {
|
||||
return await readFile(path.join(process.cwd(), rel), "utf8");
|
||||
}
|
||||
|
||||
describe("umami event attributes", () => {
|
||||
it("instruments nav links using data-umami-event", async () => {
|
||||
const src = await read("src/layouts/BaseLayout.astro");
|
||||
expect(src).toContain('data-umami-event="click"');
|
||||
expect(src).toContain('data-umami-event-target_id="nav.videos"');
|
||||
expect(src).toContain('data-umami-event-placement="nav"');
|
||||
});
|
||||
|
||||
it("instruments CTAs using data-umami-event and unique target_id", async () => {
|
||||
const src = await read("src/components/CtaLink.astro");
|
||||
expect(src).toContain('data-umami-event="cta_click"');
|
||||
expect(src).toContain("data-umami-event-target_id");
|
||||
expect(src).toContain("data-umami-event-placement");
|
||||
});
|
||||
|
||||
it("instruments content cards using outbound_click", async () => {
|
||||
const src = await read("src/components/ContentCard.astro");
|
||||
expect(src).toContain('data-umami-event="outbound_click"');
|
||||
expect(src).toContain("data-umami-event-target_id");
|
||||
expect(src).toContain("data-umami-event-domain");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user