Files

48 lines
1.3 KiB
TypeScript

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<string> {
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(/^<svg xmlns=/u);
expect(svg).toContain("<rect");
expect(svg).not.toContain("script");
});
it("rejects oversized values instead of allocating unbounded matrices", () => {
expect(() => encodeQr("x".repeat(500))).toThrow(/version 10/iu);
});
});