ec66f22212b6
test: add atomic-persist regression — a slot-B write failure must restore slot A so no phantom entry is left on disk (covers v3.6.137)
- time
- 2026-05-30 07:32 UTC · 5 months ago
- machine
- koh2
- parent
- ebb7bd2456e6
↓ peach-browser-ec66f222.tar.gzatlas at this save
files changed1 file
src/background/vault-history.test.ts+28 −0src/background/vault-history.test.ts+28 −0
@@ -98,6 +98,34 @@9898 expect(readHistory().snapshots).toHaveLength(5);9999 });100100 101+ it("atomic persist: a slot-B write failure restores slot A — no phantom entry (v3.6.137)", async () => {102+ const vault = await import("./vault");103+ await vault.createVault("atomic-pass-12345");104+ await vault.addEntry({ title: "A", username: "", password: "p1", url: "" });105+106+ // Slot A as committed by the first, fully-successful save.107+ const slotABefore = JSON.stringify(storage.peach_vault_a);108+ expect(slotABefore).toBeTruthy();109+110+ // Fail ONLY the slot-B write — this mimics the mid-persist storage error111+ // (quota overflow) that left a committed slot A behind and produced112+ // duplicate entries before v3.6.137. beforeEach rebuilds chrome per test,113+ // so this override does not leak.114+ (chrome.storage.local as unknown as { set: (n: Record<string, unknown>) => Promise<void> }).set =115+ async (next) => {116+ if ("peach_vault_b" in next) throw new Error("QUOTA_BYTES quota exceeded");117+ Object.assign(storage, next);118+ };119+120+ await expect(121+ vault.addEntry({ title: "B", username: "", password: "p2", url: "" }),122+ ).rejects.toThrow();123+124+ // Slot A on disk must be byte-identical to before: the failed entry B was125+ // rolled back on disk too, so it can never resurface as a phantom/duplicate.126+ expect(JSON.stringify(storage.peach_vault_a)).toBe(slotABefore);127+ });128+101129 it("entryCount reflects current in-memory active count at snapshot time", async () => {102130 const vault = await import("./vault");103131 await vault.createVault("count-pass-12345");