Download src/media/document-extractors.runtime.test.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 7.54 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/media/document-extractors.runtime.test.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/media/document-extractors.runtime.test.ts
-
curl -L -o document-extractors.runtime.test.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/media/document-extractors.runtime.test.ts
7.54 kB
| // Document extractor runtime tests cover lazy document extraction adapters. | |
| import { beforeEach, describe, expect, it, vi } from "vitest"; | |
| import type { | |
| DocumentExtractionRequest, | |
| DocumentExtractionResult, | |
| } from "../plugins/document-extractor-types.js"; | |
| import type { resolvePluginDocumentExtractors } from "../plugins/document-extractors.runtime.js"; | |
| import { clearPluginMetadataLifecycleCaches } from "../plugins/plugin-metadata-lifecycle.js"; | |
| const { resolvePluginDocumentExtractorsMock } = vi.hoisted(() => ({ | |
| resolvePluginDocumentExtractorsMock: vi.fn<typeof resolvePluginDocumentExtractors>(), | |
| })); | |
| vi.mock("../plugins/document-extractors.runtime.js", () => ({ | |
| resolvePluginDocumentExtractors: resolvePluginDocumentExtractorsMock, | |
| })); | |
| import { extractDocumentContent } from "./document-extractors.runtime.js"; | |
| import { extractPdfContent } from "./pdf-extract.js"; | |
| describe("extractDocumentContent", () => { | |
| beforeEach(() => { | |
| resolvePluginDocumentExtractorsMock.mockReset(); | |
| }); | |
| it("passes only public extraction request fields to plugins", async () => { | |
| const extract = vi.fn().mockResolvedValue({ text: "pdf text", images: [] }); | |
| resolvePluginDocumentExtractorsMock.mockReturnValue([ | |
| { | |
| id: "pdf", | |
| pluginId: "document-extract", | |
| label: "PDF", | |
| mimeTypes: ["application/pdf"], | |
| extract, | |
| }, | |
| ]); | |
| await expect( | |
| extractDocumentContent({ | |
| buffer: Buffer.from("pdf"), | |
| mimeType: "application/pdf", | |
| maxPages: 1, | |
| maxPixels: 100, | |
| minTextChars: 10, | |
| config: { | |
| env: { | |
| vars: { | |
| SECRET_VALUE: "do-not-pass", | |
| }, | |
| }, | |
| }, | |
| }), | |
| ).resolves.toStrictEqual({ text: "pdf text", images: [], extractor: "pdf" }); | |
| expect(extract).toHaveBeenCalledWith({ | |
| buffer: Buffer.from("pdf"), | |
| mimeType: "application/pdf", | |
| maxPages: 1, | |
| maxPixels: 100, | |
| minTextChars: 10, | |
| }); | |
| }); | |
| it("surfaces matching extractor failures instead of reporting disablement", async () => { | |
| const cause = new Error("password required"); | |
| resolvePluginDocumentExtractorsMock.mockReturnValue([ | |
| { | |
| id: "pdf", | |
| pluginId: "document-extract", | |
| label: "PDF", | |
| mimeTypes: ["application/pdf"], | |
| extract: vi.fn().mockRejectedValue(cause), | |
| }, | |
| ]); | |
| let extractionError: unknown; | |
| try { | |
| await extractDocumentContent({ | |
| buffer: Buffer.from("pdf"), | |
| mimeType: "application/pdf", | |
| maxPages: 1, | |
| maxPixels: 100, | |
| minTextChars: 10, | |
| }); | |
| } catch (error) { | |
| extractionError = error; | |
| } | |
| expect(extractionError).toBeInstanceOf(Error); | |
| if (!(extractionError instanceof Error)) { | |
| throw new Error("expected extraction error"); | |
| } | |
| expect(extractionError.message).toBe("Document extraction failed for application/pdf"); | |
| expect(extractionError.cause).toBe(cause); | |
| }); | |
| it("forwards cancellation and does not try another extractor after the owner aborts", async () => { | |
| const abort = new AbortController(); | |
| const reason = new Error("owning turn cancelled"); | |
| const first = vi.fn(async (request: DocumentExtractionRequest) => { | |
| expect(request.signal).toBe(abort.signal); | |
| abort.abort(reason); | |
| throw reason; | |
| }); | |
| const second = vi.fn(); | |
| resolvePluginDocumentExtractorsMock.mockReturnValue( | |
| [first, second].map((extract, index) => ({ | |
| id: `pdf-${index}`, | |
| pluginId: "document-extract", | |
| label: "PDF", | |
| mimeTypes: ["application/pdf"], | |
| extract, | |
| })), | |
| ); | |
| await expect( | |
| extractPdfContent({ | |
| buffer: Buffer.from("pdf"), | |
| maxPages: 1, | |
| maxPixels: 100, | |
| minTextChars: 1, | |
| signal: abort.signal, | |
| }), | |
| ).rejects.toBe(reason); | |
| expect(first).toHaveBeenCalledOnce(); | |
| expect(second).not.toHaveBeenCalled(); | |
| }); | |
| it("replaces cached document extractor callbacks when plugin metadata changes", async () => { | |
| const oldExtract = vi.fn().mockResolvedValue({ text: "retired", images: [] }); | |
| const newExtract = vi.fn().mockResolvedValue({ text: "replacement", images: [] }); | |
| const config = {}; | |
| const createExtractor = (extract: typeof oldExtract) => ({ | |
| id: "pdf", | |
| pluginId: "document-extract", | |
| label: "PDF", | |
| mimeTypes: ["application/pdf"], | |
| extract, | |
| }); | |
| resolvePluginDocumentExtractorsMock | |
| .mockReturnValueOnce([createExtractor(oldExtract)]) | |
| .mockReturnValueOnce([createExtractor(newExtract)]); | |
| const request = { | |
| buffer: Buffer.from("pdf"), | |
| mimeType: "application/pdf", | |
| maxPages: 1, | |
| maxPixels: 100, | |
| minTextChars: 10, | |
| config, | |
| }; | |
| await expect(extractDocumentContent(request)).resolves.toMatchObject({ text: "retired" }); | |
| clearPluginMetadataLifecycleCaches(); | |
| await expect(extractDocumentContent(request)).resolves.toMatchObject({ text: "replacement" }); | |
| expect(resolvePluginDocumentExtractorsMock).toHaveBeenCalledTimes(2); | |
| expect(oldExtract).toHaveBeenCalledOnce(); | |
| expect(newExtract).toHaveBeenCalledOnce(); | |
| }); | |
| it.each([ | |
| { | |
| name: "populated optional fields", | |
| password: " retained ", | |
| pageNumbers: [2, 1], | |
| callback: true, | |
| }, | |
| { name: "empty password and pages", password: "", pageNumbers: [], callback: false }, | |
| ])("preserves the composed PDF request with $name", async (row) => { | |
| const { password, pageNumbers, callback } = row; | |
| const buffer = Buffer.from("%PDF-1.4"); | |
| const config = {}; | |
| const images: DocumentExtractionResult["images"] = []; | |
| const imageError = new Error("image rendering failed"); | |
| const onImageExtractionError = vi.fn<(error: unknown) => void>(); | |
| const extract = vi.fn(async (request: DocumentExtractionRequest) => { | |
| expect(request).toStrictEqual({ | |
| buffer, | |
| mimeType: "application/pdf", | |
| maxPages: 2, | |
| maxPixels: 100, | |
| minTextChars: 10, | |
| ...(password ? { password: " retained " } : {}), | |
| pageNumbers, | |
| ...(callback ? { onImageExtractionError } : {}), | |
| }); | |
| expect(request.buffer).toBe(buffer); | |
| expect(request.pageNumbers).toBe(pageNumbers); | |
| expect(request.onImageExtractionError).toBe(callback ? onImageExtractionError : undefined); | |
| request.onImageExtractionError?.(imageError); | |
| return { text: "pdf text", images }; | |
| }); | |
| resolvePluginDocumentExtractorsMock.mockReturnValue([ | |
| { | |
| id: "pdf", | |
| pluginId: "document-extract", | |
| label: "PDF", | |
| mimeTypes: ["application/pdf"], | |
| extract, | |
| }, | |
| ]); | |
| const result = await extractPdfContent({ | |
| buffer, | |
| maxPages: 2, | |
| maxPixels: 100, | |
| minTextChars: 10, | |
| password, | |
| pageNumbers, | |
| config, | |
| onImageExtractionError: callback ? onImageExtractionError : undefined, | |
| }); | |
| expect(resolvePluginDocumentExtractorsMock).toHaveBeenCalledOnce(); | |
| expect(resolvePluginDocumentExtractorsMock.mock.calls[0]?.[0]?.config).toBe(config); | |
| expect(extract).toHaveBeenCalledOnce(); | |
| expect(result).toStrictEqual({ text: "pdf text", images }); | |
| expect(result.images).toBe(images); | |
| if (callback) { | |
| expect(onImageExtractionError).toHaveBeenCalledOnce(); | |
| expect(onImageExtractionError).toHaveBeenCalledWith(imageError); | |
| } else { | |
| expect(onImageExtractionError).not.toHaveBeenCalled(); | |
| } | |
| }); | |
| }); | |