import { describe, it, expect } from "vitest"; import { encrypt, decrypt } from "../encrypt"; describe("encrypt / decrypt", () => { it("round-trips a short string", () => { const plain = "hello world"; expect(decrypt(encrypt(plain))).toBe(plain); }); it("round-trips an empty string", () => { expect(decrypt(encrypt(""))).toBe(""); }); it("round-trips a unicode string", () => { const plain = "café ☕ résumé"; expect(decrypt(encrypt(plain))).toBe(plain); }); it("round-trips a long string (API key-sized)", () => { const plain = "sk-proj-" + "a".repeat(128); expect(decrypt(encrypt(plain))).toBe(plain); }); it("produces different ciphertexts for same input (random IV)", () => { const plain = "same input"; const c1 = encrypt(plain); const c2 = encrypt(plain); expect(c1).not.toBe(c2); // but both decrypt to same value expect(decrypt(c1)).toBe(plain); expect(decrypt(c2)).toBe(plain); }); it("ciphertext format is iv:authTag:encrypted (3 hex segments)", () => { const ct = encrypt("test"); const parts = ct.split(":"); expect(parts).toHaveLength(3); parts.forEach((p) => expect(p).toMatch(/^[0-9a-f]+$/)); }); it("throws on malformed ciphertext (wrong segments)", () => { expect(() => decrypt("notvalid")).toThrow("Invalid ciphertext format"); expect(() => decrypt("a:b")).toThrow("Invalid ciphertext format"); }); it("throws on tampered ciphertext (auth tag mismatch)", () => { const ct = encrypt("sensitive"); const parts = ct.split(":"); // flip a byte in the encrypted payload const tampered = parts[0] + ":" + parts[1] + ":" + "00" + parts[2]!.slice(2); expect(() => decrypt(tampered)).toThrow(); }); });