vault.hibp-padding.test.ts

2.3 KB · raw

1// PCH-02-007 regression tests — the HIBP k-anonymity range request must ask2// for response padding, and the parser must stay correct on padded responses.34import { beforeEach, describe, expect, it, vi } from "vitest";56// SHA-1("password") = 5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD87const PREFIX = "5BAA6";8const SUFFIX = "1E4C9B93F3F0682250B6CF8331B7EE68FD8";910describe("PCH-02-007 — HIBP Add-Padding", () => {11  let fetchMock: ReturnType<typeof vi.fn>;1213  beforeEach(() => {14    vi.resetModules();1516    const chromeMock = {17      storage: {18        local: {19          get: vi.fn(async () => ({})),20          set: vi.fn(async () => undefined),21          remove: vi.fn(async () => undefined),22        },23      },24      alarms: {25        clear: vi.fn(),26        create: vi.fn(),27        onAlarm: { addListener: vi.fn() },28      },29      idle: {30        setDetectionInterval: vi.fn(),31        onStateChanged: { addListener: vi.fn() },32      },33    } as unknown as typeof chrome;34    (globalThis as { chrome?: typeof chrome }).chrome = chromeMock;3536    fetchMock = vi.fn(async () => ({37      ok: true,38      text: async () =>39        [40          "0018A45C4D1DEF81644B54AB7F969B88D65:1",41          `${SUFFIX}:3303003`,42          "FFFFFFAAAAAABBBBBBCCCCCCDDDDDDEEEEE:0",43        ].join("\r\n"),44    }));45    vi.stubGlobal("fetch", fetchMock);46  });4748  it("sends Add-Padding: true on the range request", async () => {49    const vault = await import("./vault");50    await vault.checkBreach("password");5152    expect(fetchMock).toHaveBeenCalledWith(53      `https://api.pwnedpasswords.com/range/${PREFIX}`,54      expect.objectContaining({55        headers: expect.objectContaining({ "Add-Padding": "true" }),56      }),57    );58  });5960  it("still parses the real breach count out of a padded response", async () => {61    const vault = await import("./vault");62    const count = await vault.checkBreach("password");63    expect(count).toBe(3303003);64  });6566  it("reports 0 when the response holds only padding lines", async () => {67    fetchMock.mockImplementationOnce(async () => ({68      ok: true,69      text: async () =>70        [71          "FFFFFFAAAAAABBBBBBCCCCCCDDDDDDEEEEE:0",72          "EEEEEEAAAAAABBBBBBCCCCCCDDDDDDFFFFF:0",73        ].join("\r\n"),74    }));7576    const vault = await import("./vault");77    const count = await vault.checkBreach("password");78    expect(count).toBe(0);79  });80});