48 lines
1.3 KiB
TypeScript
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);
|
|
});
|
|
});
|