yap-blog/tests/unit/excerpt.test.ts
2026-07-02 21:32:33 -04:00

53 lines
2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { generateExcerpt } from "@/lib/excerpt";
describe("generateExcerpt (HTML bodies)", () => {
it("strips tags but keeps the visible text", () => {
const html =
"<h2>Heading</h2><p>Some <strong>bold</strong> text with <a href='/x'>a link</a>. And more.</p>";
expect(generateExcerpt(html, 100)).toBe("Heading Some bold text with a link. And more.");
});
it("caps the excerpt at the word limit and appends an ellipsis", () => {
expect(generateExcerpt("<p>one two three four five six</p>", 3)).toBe("one two three…");
});
it("adds no ellipsis when the text fits exactly", () => {
expect(generateExcerpt("<p>one two three</p>", 3)).toBe("one two three");
});
it("skips code blocks entirely", () => {
const html = "<pre><code>const hidden = true;</code></pre><p>After the code.</p>";
expect(generateExcerpt(html, 50)).toBe("After the code.");
});
it("contributes nothing from images (alt text is not visible text)", () => {
const html = '<p><img src="/uploads/x.png" alt="decorative alt"></p><p>Caption text.</p>';
expect(generateExcerpt(html, 50)).toBe("Caption text.");
});
it("keeps inline code as text", () => {
expect(generateExcerpt("<p>Run <code>npm test</code> daily.</p>", 50)).toBe(
"Run npm test daily.",
);
});
it("separates list items and table cells with whitespace", () => {
expect(generateExcerpt("<ul><li>first item</li><li>second item</li></ul>", 50)).toBe(
"first item second item",
);
expect(
generateExcerpt("<table><tr><td>cell one</td><td>cell two</td></tr></table>", 50),
).toBe("cell one cell two");
});
it("returns an empty string for empty or non-textual bodies", () => {
expect(generateExcerpt("", 40)).toBe("");
expect(generateExcerpt('<p><img src="/uploads/only.png" alt="x"></p>', 40)).toBe("");
});
it("tolerates a nonsensical word limit", () => {
expect(generateExcerpt("<p>alpha beta</p>", 0)).toBe("alpha…");
});
});