rag-service/tests/lifecycle-utils.test.ts

61 lines
2.4 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import {
buildMetadataHash,
buildProcessingFingerprint,
buildVersionedQdrantPointId,
hashOrderedPairs,
normalizeContentForHash,
sha256Hex
} from "../src/shared/utils/ids.js";
import { CatalogError } from "../src/modules/catalog/errors.js";
import { normalizeExpectedActiveVersion } from "../src/modules/catalog/lifecycle.js";
test("versioned Qdrant point IDs are deterministic UUIDv5 values", () => {
const versionId = "123e4567-e89b-12d3-a456-426614174000";
const chunkId = "chk:doc:src:default:folder:docs:readme.md:documental:0001";
const first = buildVersionedQdrantPointId(versionId, chunkId);
const second = buildVersionedQdrantPointId(versionId, chunkId);
const differentVersion = buildVersionedQdrantPointId("123e4567-e89b-12d3-a456-426614174001", chunkId);
assert.equal(first, second);
assert.notEqual(first, differentVersion);
assert.match(first, /^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
});
test("content hashing normalization is canonical", () => {
const left = normalizeContentForHash("\uFEFFTitle\r\nBody \r\n\r\n");
const right = normalizeContentForHash("Title\nBody\n");
assert.equal(left, "Title\nBody\n");
assert.equal(sha256Hex(left), sha256Hex(right));
});
test("ordered pair hashes are independent from input order", () => {
const first = hashOrderedPairs([["b.md", "hash-b"], ["a.md", "hash-a"]]);
const second = hashOrderedPairs([["a.md", "hash-a"], ["b.md", "hash-b"]]);
assert.equal(first, second);
assert.equal(hashOrderedPairs([["a.md", null]]), null);
});
test("processing and metadata fingerprints are stable with sorted keys", () => {
assert.equal(
buildProcessingFingerprint({ model: "qwen", provider: "openrouter" }),
buildProcessingFingerprint({ provider: "openrouter", model: "qwen" })
);
assert.equal(
buildMetadataHash(["b", "a"], { sourceRef: "docs" }),
buildMetadataHash(["a", "b"], { sourceRef: "docs" })
);
});
test("activation precondition is mandatory when activation is requested", () => {
assert.throws(
() => normalizeExpectedActiveVersion(undefined, true),
(error) => error instanceof CatalogError && error.statusCode === 400
);
assert.equal(normalizeExpectedActiveVersion(null, true), null);
assert.equal(normalizeExpectedActiveVersion(undefined, false), undefined);
});