/*
Unit tests for text surface covering deriveFileLocale; extractTextSurface. It also guards the documented public contract and regression-sensitive edge cases.
- Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only.
- RFC-1068: initial creation.
- RFC-1324: coverage for the frontmatter `lang` override over directory locale.
*/
import { describe, it, expect } from "vitest";
import { extractTextSurface, deriveFileLocale } from "./text-surface.ts";
const LANGS = ["de", "uk", "en"];
describe("deriveFileLocale", () => {
it("derives locale from content path", () => {
expect(deriveFileLocale("src/content/pages/de/index.md", LANGS, "de")).toBe("de");
expect(deriveFileLocale("src/content/pages/uk/index.md", LANGS, "de")).toBe("uk");
expect(deriveFileLocale("src/content/pages/en/index.md", LANGS, "de")).toBe("en");
});
it("derives locale from mission workpiece content path", () => {
expect(
deriveFileLocale("missions/wg-m001/workpiece/src/content/pages/de/index.md", LANGS, "de"),
).toBe("de");
expect(
deriveFileLocale(
"missions/wg-m001/workpiece/src/content/business-profile/uk/offerings/x.md",
LANGS,
"de",
),
).toBe("uk");
});
it("falls back to default language for unknown locale", () => {
expect(deriveFileLocale("src/content/pages/fr/index.md", LANGS, "de")).toBe("de");
});
it("falls back to default language for non-content paths", () => {
expect(deriveFileLocale("src/pages/index.astro", LANGS, "de")).toBe("de");
});
});
describe("extractTextSurface", () => {
it("extracts frontmatter strings", () => {
const source = `---
title: Hello World
description: A test page
---
Body text here.
`;
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
expect(result.yamlError).toBeNull();
const fmSegments = result.segments.filter((s) => s.source === "frontmatter");
expect(fmSegments.length).toBeGreaterThanOrEqual(2);
expect(fmSegments.some((s) => s.text.includes("Hello World"))).toBe(true);
expect(fmSegments.some((s) => s.text.includes("A test page"))).toBe(true);
});
it("extracts body lines", () => {
const source = `---
title: Test
---
This is a body paragraph.
Second line of text.
`;
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
const bodySegments = result.segments.filter((s) => s.source === "body");
expect(bodySegments.length).toBe(2);
expect(bodySegments[0].text).toContain("This is a body paragraph");
expect(bodySegments[1].text).toContain("Second line of text");
});
it("honors a declared frontmatter lang over the directory locale (RFC-1329 binding docs)", () => {
const source = `---
kind: prose
lang: de
---
Deutsche Rechtstexte.
`;
const result = extractTextSurface("src/content/prose/uk/impressum.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
expect(result.segments.every((s) => s.locale === "de")).toBe(true);
});
it("falls back to the directory locale when no lang is declared", () => {
const source = `---
title: Test
---
Body text.
`;
const result = extractTextSurface("src/content/prose/uk/note.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
expect(result.segments.every((s) => s.locale === "uk")).toBe(true);
});
it("skips fenced code blocks", () => {
const source = `---
title: Test
---
Normal text.
\`\`\`js
const x = "code block";
\`\`\`
After code.
`;
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
const bodySegments = result.segments.filter((s) => s.source === "body");
expect(bodySegments.length).toBe(2);
expect(bodySegments.some((s) => s.text.includes("Normal text"))).toBe(true);
expect(bodySegments.some((s) => s.text.includes("After code"))).toBe(true);
expect(bodySegments.some((s) => s.text.includes("code block"))).toBe(false);
});
it("skips technical keys", () => {
const source = `---
title: Test
slug: my-page
id: abc123
href: https://example.com
description: Real text
---
Body.
`;
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
const fmSegments = result.segments.filter((s) => s.source === "frontmatter");
expect(fmSegments.some((s) => s.text.includes("Real text"))).toBe(true);
expect(fmSegments.some((s) => s.text.includes("abc123"))).toBe(false);
expect(fmSegments.some((s) => s.text.includes("my-page"))).toBe(false);
});
it("strips inline code from body lines", () => {
const source = `---
title: Test
---
Use the \`npm install\` command.
`;
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
const bodySegments = result.segments.filter((s) => s.source === "body");
expect(bodySegments.length).toBe(1);
expect(bodySegments[0].text).toContain("Use the");
expect(bodySegments[0].text).toContain("command");
expect(bodySegments[0].text).not.toContain("npm install");
});
it("strips HTML comments from body lines", () => {
const source = `---
title: Test
---
Text here.
`;
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
const bodySegments = result.segments.filter((s) => s.source === "body");
expect(bodySegments[0].text).not.toContain("comment");
expect(bodySegments[0].text).toContain("Text");
expect(bodySegments[0].text).toContain("here");
});
it("strips URLs from body lines", () => {
const source = `---
title: Test
---
Visit https://example.com for more.
`;
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
const bodySegments = result.segments.filter((s) => s.source === "body");
expect(bodySegments[0].text).not.toContain("https://example.com");
expect(bodySegments[0].text).toContain("Visit");
expect(bodySegments[0].text).toContain("for more");
});
it("detects YAML parse errors", () => {
const source = `---
title: Test
foo: [unclosed
---
Body.
`;
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
expect(result.yamlError).not.toBeNull();
expect(result.yamlError!.message).toBeTruthy();
});
it("marks table rows correctly", () => {
const source = `---
title: Test
---
| Col1 | Col2 |
|------|------|
| a | b |
Normal text.
`;
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
const bodySegments = result.segments.filter((s) => s.source === "body");
const tableRows = bodySegments.filter((s) => s.isTableRow);
const normalLines = bodySegments.filter((s) => !s.isTableRow);
expect(tableRows.length).toBe(3);
expect(normalLines.length).toBe(1);
expect(normalLines[0].text).toContain("Normal text");
});
it("handles files without frontmatter", () => {
const source = "Just body text.\nSecond line.\n";
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
expect(result.yamlError).toBeNull();
const bodySegments = result.segments.filter((s) => s.source === "body");
expect(bodySegments.length).toBe(2);
});
it("skips identifier-like values in frontmatter", () => {
const source = `---
title: Test
path: src/foo/bar.ts
description: Real text
---
Body.
`;
const result = extractTextSurface("src/content/pages/de/test.md", source, {
languages: LANGS,
defaultLanguage: "de",
});
const fmSegments = result.segments.filter((s) => s.source === "frontmatter");
expect(fmSegments.some((s) => s.text.includes("Real text"))).toBe(true);
expect(fmSegments.some((s) => s.text.includes("src/foo/bar.ts"))).toBe(false);
});
});
describe("extractTextSurface — attribution switches", () => {
it("does not treat labels attribution enum values as text", () => {
const source = `---
brandLabel: "DP7 Handels"
attribution:
credits: byIntent
proseAuthorship: shown
---
`;
const result = extractTextSurface("src/content/site/de/labels.md", source, {
languages: ["de"],
defaultLanguage: "de",
});
const texts = result.segments.map((s) => s.text);
expect(texts).toContain("DP7 Handels");
expect(texts).not.toContain("byIntent");
expect(texts).not.toContain("shown");
});
});