pairing-invitation.test.ts

1.8 KB · raw

1import { describe, expect, it } from "vitest";23import {4  PAIRING_INVITATION_PREFIX,5  createPairingInvitation,6  pairingInvitationUrl,7  parsePairingInvitation,8} from "./pairing-invitation";910const TOKEN = "AAECAwQFBgcICQoLDA0ODw";11const RELAY = "wss://relay.peachpasswords.com";12const KAT =13  "peach-pair-v1:eyJyZWxheSI6IndzczovL3JlbGF5LnBlYWNocGFzc3dvcmRzLmNvbSIsInRva2VuIjoiQUFFQ0F3UUZCZ2NJQ1FvTERBME9EdyJ9";1415describe("relay pairing invitation", () => {16  it("pins the cross-client compact JSON/base64url vector", () => {17    expect(createPairingInvitation(`${RELAY}/`, TOKEN)).toBe(KAT);18    expect(parsePairingInvitation(KAT)).toEqual({ relayUrl: RELAY, token: TOKEN });19  });2021  it("builds a room URL without identity or vault state", () => {22    const parsed = parsePairingInvitation(KAT);23    expect(parsed).not.toBeNull();24    expect(pairingInvitationUrl(parsed!)).toBe(`${RELAY}/r/${TOKEN}`);25    expect(KAT).not.toContain("device");26    expect(KAT).not.toContain("vault");27  });2829  it("fails closed on malformed, insecure, or short-token payloads", () => {30    expect(parsePairingInvitation("not-an-invitation")).toBeNull();31    expect(parsePairingInvitation(`${PAIRING_INVITATION_PREFIX}%%%`)).toBeNull();32    const insecure = createRaw({ relay: "ws://relay.example.test", token: TOKEN });33    expect(parsePairingInvitation(insecure)).toBeNull();34    const shortToken = createRaw({ relay: RELAY, token: "too-short" });35    expect(parsePairingInvitation(shortToken)).toBeNull();36  });37});3839function createRaw(value: unknown): string {40  const bytes = new TextEncoder().encode(JSON.stringify(value));41  let binary = "";42  for (const byte of bytes) binary += String.fromCharCode(byte);43  return `${PAIRING_INVITATION_PREFIX}${btoa(binary)44    .replace(/\+/g, "-")45    .replace(/\//g, "_")46    .replace(/=+$/g, "")}`;47}