1import { describe, expect, it } from "vitest";23import {4 exportEntriesToPeachJson,5 importEntriesFromPeachJson,6 type PeachExportEnvelope,7} from "./backup";89describe("shared backup", () => {10 const sampleEntries = [11 {12 id: "login-1",13 type: "login" as const,14 title: "GitHub",15 username: "june",16 password: "secret123",17 url: "https://github.com",18 notes: "2fa enabled",19 createdAt: 1,20 modifiedAt: 1,21 },22 ];2324 it("importEntriesFromPeachJson decrypts entries with the correct password", async () => {25 const envelope = await exportEntriesToPeachJson(sampleEntries, "export-pass");2627 await expect(28 importEntriesFromPeachJson(JSON.stringify(envelope), "export-pass")29 ).resolves.toMatchObject([30 {31 type: "login",32 title: "GitHub",33 username: "june",34 password: "secret123",35 url: "https://github.com",36 },37 ]);38 });3940 it("importEntriesFromPeachJson rejects the wrong password", async () => {41 const envelope = await exportEntriesToPeachJson(sampleEntries, "export-pass");4243 await expect(44 importEntriesFromPeachJson(JSON.stringify(envelope), "wrong-pass")45 ).rejects.toThrow("INVALID_EXPORT_PASSWORD");46 });4748 it("importEntriesFromPeachJson rejects malformed JSON", async () => {49 await expect(importEntriesFromPeachJson("{not json", "export-pass")).rejects.toThrow(50 "INVALID_PEACH_EXPORT"51 );52 });5354 it("export includes trashed entries; import preserves deletedAt", async () => {55 const trashedAt = 1_700_000_010_000;56 const entries = [57 ...sampleEntries,58 {59 id: "login-2",60 type: "login" as const,61 title: "Old Service",62 username: "june",63 password: "oldpass",64 url: "https://old.example.com",65 createdAt: 1,66 modifiedAt: 1,67 deletedAt: trashedAt,68 },69 ];7071 const envelope = await exportEntriesToPeachJson(entries, "export-pass");72 const imported = await importEntriesFromPeachJson(JSON.stringify(envelope), "export-pass");7374 expect(imported).toHaveLength(2);7576 const active = imported.filter((e) => !e.deletedAt);77 const trashed = imported.filter((e) => !!e.deletedAt);7879 expect(active).toHaveLength(1);80 expect(trashed).toHaveLength(1);81 expect(trashed[0].title).toBe("Old Service");82 expect(trashed[0].deletedAt).toBe(trashedAt);83 });8485 it("importEntriesFromPeachJson rejects envelopes with missing required fields", async () => {86 const envelope: Partial<PeachExportEnvelope> = {87 version: 2,88 type: "peach-export",89 kdf: "PBKDF2-SHA256",90 salt: "00",91 nonce: "00",92 ciphertext: "00",93 };9495 await expect(96 importEntriesFromPeachJson(JSON.stringify(envelope), "export-pass")97 ).rejects.toThrow("INVALID_PEACH_EXPORT");98 });99});