Files
local-cal/tests/multi-image.test.ts

157 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, expect, test } from "bun:test";
import {
appendImagesDeduped,
imageFileKey,
} from "@/lib/multi-image";
// ---------------------------------------------------------------------------
// Multi-image helpers behavioral tests
//
// These functions are pure; they own the "append + dedup" contract.
// Tests describe what the system DOES, not how it's implemented.
// ---------------------------------------------------------------------------
describe("imageFileKey stable identity for dedup", () => {
test("returns a string combining name and size", () => {
const file = new File(["hello"], "flyer.png", {
type: "image/png",
lastModified: 123,
});
const key = imageFileKey(file);
expect(typeof key).toBe("string");
expect(key).toContain("flyer.png");
expect(key).toContain(String(file.size));
expect(key).toContain(String(file.lastModified));
});
test("two files with the same name, size, and lastModified produce the same key", () => {
const a = new File(["hello"], "a.png", {
type: "image/png",
lastModified: 123,
});
const b = new File(["hello"], "a.png", {
type: "image/png",
lastModified: 123,
});
expect(imageFileKey(a)).toBe(imageFileKey(b));
});
test("two files with the same name but different content produce different keys", () => {
const a = new File(["hello"], "a.png", {
type: "image/png",
lastModified: 123,
});
const b = new File(["hello world"], "a.png", {
type: "image/png",
lastModified: 123,
});
expect(imageFileKey(a)).not.toBe(imageFileKey(b));
});
test("two files with different names but same content produce different keys", () => {
const a = new File(["hello"], "a.png", {
type: "image/png",
lastModified: 123,
});
const b = new File(["hello"], "b.png", {
type: "image/png",
lastModified: 123,
});
expect(imageFileKey(a)).not.toBe(imageFileKey(b));
});
test("clipboard fallback files with the same fallback name and size stay distinct when lastModified differs", () => {
const a = new File(["abcd"], "clipboard-image", {
type: "image/png",
lastModified: 100,
});
const b = new File(["wxyz"], "clipboard-image", {
type: "image/png",
lastModified: 101,
});
expect(a.size).toBe(b.size);
expect(imageFileKey(a)).not.toBe(imageFileKey(b));
});
});
describe("appendImagesDeduped append with deduplication", () => {
const makeFile = (
name: string,
content = "data",
lastModified = 123,
) => new File([content], name, { type: "image/png", lastModified });
test("appends new files to an empty list", () => {
const result = appendImagesDeduped([], [makeFile("a.png")]);
expect(result).toHaveLength(1);
expect(result[0].name).toBe("a.png");
});
test("appends new files to an existing list", () => {
const existing = [makeFile("a.png")];
const incoming = [makeFile("b.png")];
const result = appendImagesDeduped(existing, incoming);
expect(result).toHaveLength(2);
expect(result.map((f) => f.name)).toEqual(["a.png", "b.png"]);
});
test("silently ignores incoming files that are exact duplicates (same name+size)", () => {
const existing = [makeFile("a.png")];
const incoming = [makeFile("a.png")]; // identical name + content = same size
const result = appendImagesDeduped(existing, incoming);
expect(result).toHaveLength(1);
expect(result[0].name).toBe("a.png");
});
test("appends non-duplicate files even when some duplicates are in the batch", () => {
const existing = [makeFile("a.png")];
const incoming = [makeFile("a.png"), makeFile("b.png")];
const result = appendImagesDeduped(existing, incoming);
expect(result).toHaveLength(2);
expect(result.map((f) => f.name)).toEqual(["a.png", "b.png"]);
});
test("preserves existing list order — new files are appended at the end", () => {
const existing = [makeFile("first.png"), makeFile("second.png")];
const incoming = [makeFile("third.png")];
const result = appendImagesDeduped(existing, incoming);
expect(result.map((f) => f.name)).toEqual([
"first.png",
"second.png",
"third.png",
]);
});
test("returns a new array (does not mutate the existing list)", () => {
const existing = [makeFile("a.png")];
const incoming = [makeFile("b.png")];
const result = appendImagesDeduped(existing, incoming);
expect(result).not.toBe(existing); // new reference
expect(existing).toHaveLength(1); // original untouched
});
test("handles multiple incoming files with internal duplicates", () => {
// Two identical files in the same incoming batch
const existing: File[] = [];
const incoming = [makeFile("a.png"), makeFile("a.png"), makeFile("b.png")];
const result = appendImagesDeduped(existing, incoming);
expect(result).toHaveLength(2);
expect(result.map((f) => f.name)).toEqual(["a.png", "b.png"]);
});
test("keeps distinct clipboard fallback files that share the same name and byte size", () => {
const existing: File[] = [];
const incoming = [
makeFile("clipboard-image", "abcd", 100),
makeFile("clipboard-image", "wxyz", 101),
];
const result = appendImagesDeduped(existing, incoming);
expect(result).toHaveLength(2);
expect(result[0].lastModified).toBe(100);
expect(result[1].lastModified).toBe(101);
});
});