Nomad changes
All checks were successful
Deploy fil (kreuzberg) / deploy (push) Successful in 49s

This commit is contained in:
Henrik Jess Nielsen
2026-06-01 23:40:55 +02:00
parent 72b1a0a6ed
commit b4c07d3693
5723 changed files with 1130655 additions and 0 deletions

173
e2e/node/tests/test_plugins.test.ts generated Normal file
View File

@@ -0,0 +1,173 @@
/**
* Bridge registry error-path tests for document extractor and renderer plugins.
*
* These tests cover the observable behaviour of register/unregister/clear at
* the TypeScript/Node layer. register_document_extractor and register_renderer
* are generated by the alef trait-bridge codegen and present on the native
* kreuzberg module at runtime; they do not appear in the curated index.d.ts
* re-export because the TypeScript wrapper only surfaces a subset of the API.
*
* A DocumentExtractor bridge object must expose:
* name(): string
* extract_bytes(content, mimeType, configJson): string (JSON InternalDocument)
* supported_mime_types(): string[]
*
* A Renderer bridge object must expose:
* name(): string
* render(docJson): string
*/
import { describe, it, expect } from "vitest";
import { extractBytesSync, listDocumentExtractors, listRenderers } from "kreuzberg";
// The register/unregister/clear functions are exported by the native module but
// not re-typed in the public TypeScript wrapper. Import the native binding
// directly so we can reach the full API surface without 'any' sprawl.
import kreuzberg from "kreuzberg";
const native = kreuzberg as unknown as Record<string, (...args: unknown[]) => unknown>;
function registerDocumentExtractor(obj: unknown): void {
(native["registerDocumentExtractor"] as (o: unknown) => void)(obj);
}
function unregisterDocumentExtractor(name: string): void {
(native["unregisterDocumentExtractor"] as (n: string) => void)(name);
}
function clearDocumentExtractors(): void {
(native["clearDocumentExtractors"] as () => void)();
}
function registerRenderer(obj: unknown): void {
(native["registerRenderer"] as (o: unknown) => void)(obj);
}
function unregisterRenderer(name: string): void {
(native["unregisterRenderer"] as (n: string) => void)(name);
}
function clearRenderers(): void {
(native["clearRenderers"] as () => void)();
}
// ---------------------------------------------------------------------------
// Minimal stub factory helpers
// ---------------------------------------------------------------------------
function makeExtractor(name: string, mimeType = "application/x-test"): object {
return {
name: (): string => name,
version: (): string => "0.0.1",
initialize: (): void => {
/* no-op */
},
shutdown: (): void => {
/* no-op */
},
supported_mime_types: (): string[] => [mimeType],
extract_bytes: (_content: Uint8Array, _mimeType: string, _configJson: string): string =>
JSON.stringify({
source_format: "plain",
mime_type: "text/plain",
elements: [],
relationships: [],
images: [],
tables: [],
}),
};
}
function makeRenderer(name: string): object {
return {
name: (): string => name,
version: (): string => "0.0.1",
initialize: (): void => {
/* no-op */
},
shutdown: (): void => {
/* no-op */
},
render: (_docJson: string): string => "rendered",
};
}
// ---------------------------------------------------------------------------
// DocumentExtractor tests
// ---------------------------------------------------------------------------
describe("plugins: document extractor registry", () => {
it("register_duplicate_extractor_replaces: second registration silently replaces first", () => {
const name = "_test_ts_dup_extractor";
try {
registerDocumentExtractor(makeExtractor(name, "application/x-ts-dup1"));
registerDocumentExtractor(makeExtractor(name, "application/x-ts-dup2"));
const listed = listDocumentExtractors();
const count = listed.filter((n) => n === name).length;
expect(count).toBe(1);
} finally {
unregisterDocumentExtractor(name);
}
});
it("unregister_unknown_extractor_returns_ok: unregistering unknown name is a no-op", () => {
// Must not throw
expect(() => {
unregisterDocumentExtractor("_test_ts_never_registered_extractor_xyz");
}).not.toThrow();
});
it("clear_then_list_extractor_empty: list is empty after clear", () => {
registerDocumentExtractor(makeExtractor("_test_ts_clear_a", "application/x-ts-clear-a"));
registerDocumentExtractor(makeExtractor("_test_ts_clear_b", "application/x-ts-clear-b"));
clearDocumentExtractors();
const listed = listDocumentExtractors();
expect(listed).toEqual([]);
});
it("extract_after_unregister_uses_builtin: built-in extractor is used after custom removed", () => {
const name = "_test_ts_unreg_plain";
registerDocumentExtractor(makeExtractor(name, "text/plain"));
unregisterDocumentExtractor(name);
// Must not throw; falls back to the built-in plain-text extractor.
const encoded = new TextEncoder().encode("hello world");
const result = extractBytesSync(encoded, "text/plain", undefined);
expect(result).toBeDefined();
});
});
// ---------------------------------------------------------------------------
// Renderer tests
// ---------------------------------------------------------------------------
describe("plugins: renderer registry", () => {
it("register_duplicate_renderer_replaces: second registration silently replaces first", () => {
const name = "_test_ts_dup_renderer";
try {
registerRenderer(makeRenderer(name));
registerRenderer(makeRenderer(name));
const listed = listRenderers();
const count = listed.filter((n) => n === name).length;
expect(count).toBe(1);
} finally {
unregisterRenderer(name);
}
});
it("unregister_unknown_renderer_returns_ok: unregistering unknown name is a no-op", () => {
expect(() => {
unregisterRenderer("_test_ts_never_registered_renderer_xyz");
}).not.toThrow();
});
it("clear_then_list_renderer_empty: list is empty after clear", () => {
registerRenderer(makeRenderer("_test_ts_renderer_clear_a"));
registerRenderer(makeRenderer("_test_ts_renderer_clear_b"));
clearRenderers();
const listed = listRenderers();
expect(listed).toEqual([]);
});
it("list_renderers_after_unregister_does_not_include_removed: name absent after unregister", () => {
const name = "_test_ts_unregister_renderer_check";
registerRenderer(makeRenderer(name));
expect(listRenderers()).toContain(name);
unregisterRenderer(name);
expect(listRenderers()).not.toContain(name);
});
});