|
| 1 | +import assert from "node:assert/strict" |
| 2 | +import fs from "node:fs" |
| 3 | +import test from "node:test" |
| 4 | +import { isPublished, postMetadataSource } from "./post-assets.ts" |
| 5 | +import { parseFrontmatter } from "../src/lib/post-frontmatter.ts" |
| 6 | + |
| 7 | +test("metadata keeps headers and reading time without article content", () => { |
| 8 | + const body = "본문에만있는검색어 ".repeat(450) |
| 9 | + const raw = `---\ntitle: "A title"\ndate: "2026-09-01"\nupdated: "2026-09-02"\ntags: ["a"]\n---\n${body}` |
| 10 | + const metadata = postMetadataSource(raw) |
| 11 | + const parsed = parseFrontmatter(metadata) |
| 12 | + assert.equal(parsed.data.title, "A title") |
| 13 | + assert.deepEqual(parsed.data.tags, ["a"]) |
| 14 | + assert.equal(parsed.data.readingMinutes, "3") |
| 15 | + assert.equal(parsed.content, "") |
| 16 | + assert.ok(!metadata.includes("본문에만있는검색어")) |
| 17 | +}) |
| 18 | + |
| 19 | +test("production indices exclude drafts and future posts", () => { |
| 20 | + const raw = (extra) => `---\ntitle: "Post"\n${extra}\n---\ncontent` |
| 21 | + assert.equal(isPublished(raw('draft: true'), "2026-09-22"), false) |
| 22 | + assert.equal(isPublished(raw('draft: "true"'), "2026-09-22"), false) |
| 23 | + assert.equal(isPublished(raw('publishDate: "2026-09-23"'), "2026-09-22"), false) |
| 24 | + assert.equal(isPublished(raw('publishDate: "2026-09-22"'), "2026-09-22"), true) |
| 25 | + assert.equal(isPublished(raw('draft: false'), "2026-09-22"), true) |
| 26 | +}) |
| 27 | + |
| 28 | +const manifest = JSON.parse(fs.readFileSync(new URL("../dist/.vite/manifest.json", import.meta.url), "utf8")) |
| 29 | +function staticImports(key, visited = new Set()) { |
| 30 | + if (visited.has(key)) return visited |
| 31 | + assert.ok(manifest[key], `Missing build manifest entry: ${key}`) |
| 32 | + visited.add(key) |
| 33 | + for (const dependency of manifest[key].imports ?? []) staticImports(dependency, visited) |
| 34 | + return visited |
| 35 | +} |
| 36 | + |
| 37 | +test("initial page and analytics shell do not wait for chart or body/search chunks", () => { |
| 38 | + for (const entry of ["index.html", "src/pages/AnalyticsPage.tsx"]) { |
| 39 | + const imports = [...staticImports(entry)] |
| 40 | + assert.deepEqual(imports.filter((key) => /AnalyticsCharts|post-body|post-search|_chart-/.test(key)), []) |
| 41 | + } |
| 42 | + assert.ok(manifest["src/components/AnalyticsCharts.tsx"]?.isDynamicEntry) |
| 43 | + assert.ok(manifest["virtual:post-search/ko"]?.isDynamicEntry) |
| 44 | + assert.ok(manifest["virtual:post-search/en"]?.isDynamicEntry) |
| 45 | +}) |
| 46 | + |
| 47 | +test("prerendered article keeps its body while analytics has stable chart placeholders", () => { |
| 48 | + const article = fs.readFileSync(new URL("../dist/posts/spring-ai-cs-automation/index.html", import.meta.url), "utf8") |
| 49 | + assert.match(article, /<h1/) |
| 50 | + assert.match(article, /class="prose/) |
| 51 | + assert.match(article, /배경과 운영 경계/) |
| 52 | + assert.match(article, /id="post-hydration-data"/) |
| 53 | + assert.ok(!article.includes("본문을 불러오는 중")) |
| 54 | + const analytics = fs.readFileSync(new URL("../dist/analytics/index.html", import.meta.url), "utf8") |
| 55 | + assert.match(analytics, /차트를 불러오는 중/) |
| 56 | + assert.ok(!analytics.includes('id="S:')) |
| 57 | +}) |
0 commit comments