mirror of
https://github.com/langgenius/dify.git
synced 2026-09-02 22:36:15 +08:00
117 lines
3.8 KiB
TypeScript
117 lines
3.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
QUERY_IMAGE_EXPANSION_METADATA_KEY,
|
|
QUERY_IMAGE_REFERENCES_METADATA_KEY,
|
|
QueryImageReferencesSchema,
|
|
QueryImageResolutionError,
|
|
assertResolvedQueryImages,
|
|
hasQueryInput,
|
|
queryImageExpansionFromMetadata,
|
|
queryImageReferencesFromMetadata,
|
|
} from "./query-images";
|
|
|
|
const IMAGE_ID = "00000000-0000-4000-8000-000000000001";
|
|
|
|
describe("query image contracts", () => {
|
|
it("accepts either text or images and permits an intentional mixed query", () => {
|
|
expect(hasQueryInput({ query: "find this" })).toBe(true);
|
|
expect(hasQueryInput({ queryImages: [{ uploadFileId: IMAGE_ID }] })).toBe(true);
|
|
expect(hasQueryInput({ query: "find this", queryImages: [{ uploadFileId: IMAGE_ID }] })).toBe(
|
|
true,
|
|
);
|
|
expect(hasQueryInput({ query: " ", queryImages: [] })).toBe(false);
|
|
expect(hasQueryInput({})).toBe(false);
|
|
});
|
|
|
|
it("rejects malformed, duplicate, and over-count references", () => {
|
|
expect(() => QueryImageReferencesSchema.parse([{ uploadFileId: "not-a-uuid" }])).toThrow();
|
|
expect(() =>
|
|
QueryImageReferencesSchema.parse([{ uploadFileId: IMAGE_ID }, { uploadFileId: IMAGE_ID }]),
|
|
).toThrow("duplicate");
|
|
expect(() =>
|
|
QueryImageReferencesSchema.parse(
|
|
Array.from({ length: 5 }, (_, index) => ({
|
|
uploadFileId: `00000000-0000-4000-8000-00000000000${index}`,
|
|
})),
|
|
),
|
|
).toThrow();
|
|
});
|
|
|
|
it("enforces per-image and aggregate resolved-byte bounds", () => {
|
|
const nineMiB = new Uint8Array(9 * 1024 * 1024);
|
|
expect(() =>
|
|
assertResolvedQueryImages(
|
|
Array.from({ length: 4 }, (_, index) => ({
|
|
body: nineMiB,
|
|
byteSize: nineMiB.byteLength,
|
|
mimeType: "image/png" as const,
|
|
sha256: `${index}`.repeat(64),
|
|
uploadFileId: `00000000-0000-4000-8000-00000000000${index}`,
|
|
})),
|
|
),
|
|
).toThrow(QueryImageResolutionError);
|
|
|
|
expect(() =>
|
|
assertResolvedQueryImages([
|
|
{
|
|
body: new Uint8Array([1]),
|
|
byteSize: 2,
|
|
mimeType: "image/png",
|
|
sha256: "a".repeat(64),
|
|
uploadFileId: IMAGE_ID,
|
|
},
|
|
]),
|
|
).toThrow("byte size is invalid");
|
|
|
|
expect(() =>
|
|
assertResolvedQueryImages(
|
|
Array.from({ length: 5 }, (_, index) => ({
|
|
body: new Uint8Array([index]),
|
|
byteSize: 1,
|
|
mimeType: "image/png" as const,
|
|
sha256: `${index}`.repeat(64),
|
|
uploadFileId: `00000000-0000-4000-8000-00000000000${index}`,
|
|
})),
|
|
),
|
|
).toThrow("max count");
|
|
|
|
const tooLarge = new Uint8Array(10 * 1024 * 1024 + 1);
|
|
expect(() =>
|
|
assertResolvedQueryImages([
|
|
{
|
|
body: tooLarge,
|
|
byteSize: tooLarge.byteLength,
|
|
mimeType: "image/webp",
|
|
sha256: "b".repeat(64),
|
|
uploadFileId: IMAGE_ID,
|
|
},
|
|
]),
|
|
).toThrow("max bytes");
|
|
|
|
const valid = {
|
|
body: new Uint8Array([1, 2]),
|
|
byteSize: 2,
|
|
mimeType: "image/jpeg" as const,
|
|
sha256: "c".repeat(64),
|
|
uploadFileId: IMAGE_ID,
|
|
};
|
|
expect(assertResolvedQueryImages([valid])).toEqual([valid]);
|
|
});
|
|
|
|
it("round-trips only validated durable references and normalized expansion text", () => {
|
|
const metadata = {
|
|
[QUERY_IMAGE_EXPANSION_METADATA_KEY]: " visible invoice ",
|
|
[QUERY_IMAGE_REFERENCES_METADATA_KEY]: [{ uploadFileId: IMAGE_ID }],
|
|
};
|
|
expect(queryImageReferencesFromMetadata(metadata)).toEqual([{ uploadFileId: IMAGE_ID }]);
|
|
expect(queryImageExpansionFromMetadata(metadata)).toBe("visible invoice");
|
|
expect(
|
|
queryImageExpansionFromMetadata({ [QUERY_IMAGE_EXPANSION_METADATA_KEY]: " " }),
|
|
).toBeUndefined();
|
|
expect(
|
|
queryImageReferencesFromMetadata({ [QUERY_IMAGE_REFERENCES_METADATA_KEY]: "invalid" }),
|
|
).toEqual([]);
|
|
});
|
|
});
|