import { describe, expect, it } from "vitest"; import { bytesToArrayBuffer, bytesToHex, utf8ToBytes, } from "../../src/crypto/encoding"; import { encodeQr, qrSvg } from "../../src/qr/encoder"; async function matrixHash(text: string): Promise { const bits = encodeQr(text) .map((row) => row.map((value) => (value ? "1" : "0")).join("")) .join(""); return bytesToHex( new Uint8Array( await crypto.subtle.digest( "SHA-256", bytesToArrayBuffer(utf8ToBytes(bits)), ), ), ); } describe("QR encoder", () => { it("matches the reviewed reference matrices", async () => { await expect(matrixHash("Hello")).resolves.toBe( "ac69828947e29c188c38459b3eab69d0071aeedc825c41277d82ca3141033afe", ); await expect( matrixHash( "otpauth://totp/Example:alice?secret=JBSWY3DPEHPK3PXP&issuer=Example", ), ).resolves.toBe( "d39d6eed126c0bc3ca92a851a062613e8cfa178adf9a8e2b3c399ba77cbb0187", ); }); it("emits a self-contained SVG with a quiet zone", () => { const svg = qrSvg("Hello"); expect(svg).toMatch(/^ { expect(() => encodeQr("x".repeat(500))).toThrow(/version 10/iu); }); });