1import { describe, expect, it, vi } from "vitest";23import {4 MIN_PASSPHRASE_LENGTH,5 checkPassphraseBreached,6 generateDicewarePassphrase,7 validateForExport,8} from "./cjkPassphrase";910describe("crypto cjkPassphrase", () => {11 it("generateDicewarePassphrase returns words from the EFF wordlist", () => {12 const phrase = generateDicewarePassphrase();13 const words = phrase.split(" ");1415 expect(words).toHaveLength(6);16 expect(words.every((word) => /^[a-z]+(?:-[a-z]+)?$/.test(word))).toBe(true);17 });1819 it("validateForExport fails when the passphrase is too short", () => {20 expect(21 validateForExport({22 passphrase: "too short",23 confirm: "too short",24 })25 ).toMatchObject({26 ok: false,27 error: "PASSPHRASE_TOO_SHORT",28 });29 expect(MIN_PASSPHRASE_LENGTH).toBe(16);30 });3132 it("validateForExport fails when zxcvbn rates the passphrase too weak", () => {33 expect(34 validateForExport({35 passphrase: "aaaaaaaaaaaaaaaa",36 confirm: "aaaaaaaaaaaaaaaa",37 })38 ).toMatchObject({39 ok: false,40 error: "PASSPHRASE_TOO_WEAK",41 });42 });4344 it("validateForExport accepts a strong long passphrase", () => {45 expect(46 validateForExport({47 passphrase: "correct horse battery staple drift waves",48 confirm: "correct horse battery staple drift waves",49 })50 ).toMatchObject({51 ok: true,52 });53 });5455 it("checkPassphraseBreached only sends the 5-char SHA-1 prefix", async () => {56 const fetchMock = vi.fn(async () => ({57 ok: true,58 text: async () => "",59 }));60 vi.stubGlobal("fetch", fetchMock);6162 await checkPassphraseBreached("correct horse battery staple drift waves");6364 expect(fetchMock).toHaveBeenCalledTimes(1);65 const [url] = fetchMock.mock.calls[0] as unknown as [string, RequestInit];66 expect(url).toMatch(/\/range\/[A-F0-9]{5}$/);67 expect(url).not.toContain("correct horse battery");68 });6970 it("checkPassphraseBreached handles network failure without throwing", async () => {71 vi.stubGlobal("fetch", vi.fn(async () => {72 throw new Error("network down");73 }));7475 await expect(76 checkPassphraseBreached("correct horse battery staple drift waves")77 ).resolves.toEqual({78 breached: false,79 apiReachable: false,80 });81 });82});