SPB Git

Repository Public

pipeline.test.ts 3.4 KB 69 lines typescript

1import { describe, expect, it } from "vitest";2import { canonical, hashOf, slugify } from "../src/lib/hash";3import { cosine, embed, sharedTerms } from "../src/lib/embedding";4import { redact } from "../src/lib/log";5import { videoCaps } from "../src/providers/capabilities";6import { isAllowedMediaHost } from "../src/providers/http";78// Pure helpers are re-declared here so the test does not need a database connection.9const LEAD = 0.5, TAIL = 0.9, MIN_SHOT = 5;10const shotDuration = (n: number | null) => Math.max(MIN_SHOT, Math.round(((n ?? 0) + LEAD + TAIL) * 100) / 100);1112describe("idempotency keys", () => {13  it("is independent of key order and sensitive to every input", () => {14    expect(hashOf({ a: 1, b: { c: 2, d: [1, 2] } })).toBe(hashOf({ b: { d: [1, 2], c: 2 }, a: 1 }));15    expect(hashOf({ prompt: "x", rev: 0 })).not.toBe(hashOf({ prompt: "x", rev: 1 }));16    expect(canonical({ b: undefined, a: 1 })).toBe('{"a":1}');17  });18  it("gives the same key to a repeated request (no duplicate paid generation)", () => {19    const key = (rev: number) => hashOf({ kind: "video", model: "m", input: { image: "sha", prompt: "p", duration: 6, resolution: "720p", rev } });20    expect(key(0)).toBe(key(0));21    expect(key(0)).not.toBe(key(1));       // an explicit regeneration bumps the revision22  });23});2425describe("timing grammar", () => {26  it("sizes a shot from its narration with a lead and a tail, never under four seconds", () => {27    expect(shotDuration(4.85)).toBe(6.25);28    expect(shotDuration(1)).toBe(5);29    expect(shotDuration(null)).toBe(5);30  });31});3233describe("slugs", () => {34  it("drops accents and apostrophes", () => {35    expect(slugify("The Keeper's Debt")).toBe("the-keepers-debt");36    expect(slugify("L’Été à Québec")).toBe("lete-a-quebec");37    expect(slugify("???")).toBe("film");38  });39});4041describe("lexical embedding", () => {42  it("is normalised, deterministic and ranks related text higher", () => {43    const a = embed("a lighthouse keeper and his pocket watch"), b = embed("the keeper's watch stops when the lighthouse goes dark"), c = embed("urban transit design for a future city");44    expect(cosine(a, a)).toBeCloseTo(1, 3);45    expect(cosine(a, b)).toBeGreaterThan(cosine(a, c));46    expect(embed("x y z")).toEqual(embed("x y z"));47    expect(sharedTerms("pocket watch on a table", "a watch in a pocket")).toEqual(expect.arrayContaining(["pocket", "watch"]));48  });49});5051describe("safety helpers", () => {52  it("redacts API keys from log lines", () => {53    expect(redact("Authorization failed for xai-ABCDEFGHIJKLMNOPQRSTUVWX123456")).toBe("Authorization failed for xai-[redacted]");54  });55  it("only downloads generated media from xAI hosts over https", () => {56    expect(isAllowedMediaHost("https://vidgen.x.ai/bucket/video.mp4")).toBe(true);57    expect(isAllowedMediaHost("http://vidgen.x.ai/video.mp4")).toBe(false);58    expect(isAllowedMediaHost("https://169.254.169.254/latest/meta-data")).toBe(false);59    expect(isAllowedMediaHost("https://x.ai.evil.example/video.mp4")).toBe(false);60    expect(isAllowedMediaHost("not a url")).toBe(false);61  });62  it("knows what each video model can do and refuses unknown models", () => {63    expect(videoCaps("grok-imagine-video-1.5").referenceToVideo).toBe(true);64    expect(videoCaps("grok-imagine-video-1.5-lite").referenceToVideo).toBe(false);65    expect(videoCaps("grok-imagine-video").editVideo).toBe(true);66    expect(() => videoCaps("made-up")).toThrow();67  });68});69
Files main
Menu

Theme