Add HTML/Markdown ingest-to-anchor round-trip integration test
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s

Verifies evidence-source ingest pairs with evidence-anchor DOM selector
create/resolve for non-paginated formats (EANCH-WP-0003).
This commit is contained in:
tegwick 2026-07-09 09:29:50 +02:00
parent e087949642
commit 2b4500bc46

View file

@ -0,0 +1,68 @@
/**
* Integration round-trip: HTML/Markdown ingest createSelectors resolveSelectors.
*
* Crosses the source anchor boundary for non-paginated formats (EANCH-WP-0003).
*/
import { describe, expect, it } from "vitest";
import { ingestHtml, ingestMarkdown } from "@citation-evidence/evidence-source";
import { createSelectors, resolveSelectors } from "@citation-evidence/evidence-anchor/selectors";
import type { DomSelectionCapture } from "@citation-evidence/evidence-anchor/types";
const HTML_FIXTURE = `<!DOCTYPE html>
<html><body>
<h1>Hello World</h1>
<p>Known good quote for HTML ingest testing.</p>
</body></html>`;
const MARKDOWN_FIXTURE = `# Hello World
Known good quote for Markdown ingest testing.
**bold** text.
`;
const CASES = [
{
id: "html-basic",
ingest: () => ingestHtml(HTML_FIXTURE, { filename: "sample.html" }),
quote: "Known good quote for HTML ingest testing.",
},
{
id: "markdown-basic",
ingest: () => ingestMarkdown(MARKDOWN_FIXTURE, { filename: "sample.md" }),
quote: "Known good quote for Markdown ingest testing.",
},
] as const;
function domCapture(text: string): DomSelectionCapture {
return {
kind: "dom",
text,
startPath: [0, 0],
startOffset: 0,
endPath: [0, 0],
endOffset: text.length,
structuralPath: [{ kind: "section", index: 0 }],
};
}
describe("create + resolve round-trip — HTML/Markdown", () => {
for (const c of CASES) {
it(`${c.id}: known-good quote round-trips with confidence ≥ 0.9`, async () => {
const { representation } = await c.ingest();
const selectors = createSelectors(domCapture(c.quote), representation);
const resolution = resolveSelectors(selectors, representation);
expect(resolution.status).toBe("resolved");
expect(resolution.confidence).toBeGreaterThanOrEqual(0.9);
const span = resolution.candidates[0]?.textPosition;
expect(span).toBeDefined();
const canonical = representation.canonicalText ?? "";
expect(canonical.slice(span!.start, span!.end)).toBe(c.quote);
expect(selectors.some((s) => s.type === "DomRangeSelector")).toBe(true);
});
}
});