sync-wire.test.ts

2.8 KB · raw

1import { describe, expect, it } from "vitest";23import { decodeSyncMessage, encodeSyncMessage, isSyncMessage } from "./sync-wire";4import type { SyncMessage } from "./sync-types";56describe("sync wire codec", () => {7  it("round-trips SYNC_VAULT_SEND through base64url JSON", () => {8    const message: SyncMessage = {9      type: "SYNC_VAULT_SEND",10      vault_a: "ciphertext-a",11      vault_b: "ciphertext-b",12      sent_at: 1_778_000_000_000,13    };1415    const encoded = encodeSyncMessage(message);1617    expect(encoded).toMatch(/^[A-Za-z0-9_-]+$/);18    expect(encoded).not.toMatch(/[+/=]/);19    expect(decodeSyncMessage(encoded)).toEqual(message);20  });2122  it("round-trips ACK / ERROR / pairing messages", () => {23    const messages: SyncMessage[] = [24      { type: "SYNC_VAULT_ACK", received_at: 42 },25      { type: "SYNC_ERROR", reason: "vault_locked" },26      {27        type: "PAIR_REQUEST",28        public_key_hex: "ab".repeat(32),29        device_name: "June's Laptop",30      },31      {32        type: "PAIR_ACCEPT",33        public_key_hex: "cd".repeat(32),34        device_name: "June's Phone",35      },36      { type: "PAIR_REJECT", reason: "user_declined" },37    ];3839    for (const message of messages) {40      expect(decodeSyncMessage(encodeSyncMessage(message))).toEqual(message);41    }42  });4344  it("validates message-specific required fields", () => {45    expect(46      isSyncMessage({47        type: "SYNC_VAULT_SEND",48        vault_a: "a",49        vault_b: "b",50        sent_at: 1,51      }),52    ).toBe(true);53    expect(54      isSyncMessage({55        type: "PAIR_ACCEPT",56        public_key_hex: "deadbeef",57        device_name: "Phone",58      }),59    ).toBe(true);6061    // Missing sent_at62    expect(63      isSyncMessage({ type: "SYNC_VAULT_SEND", vault_a: "a", vault_b: "b" }),64    ).toBe(false);65    // Wrong type for received_at66    expect(isSyncMessage({ type: "SYNC_VAULT_ACK", received_at: "now" })).toBe(false);67    // Missing reason68    expect(isSyncMessage({ type: "SYNC_ERROR" })).toBe(false);69    // Missing device_name70    expect(isSyncMessage({ type: "PAIR_REQUEST", public_key_hex: "abc" })).toBe(false);71    // Unknown variant72    expect(isSyncMessage({ type: "UNKNOWN" })).toBe(false);73  });7475  it("rejects malformed wire payloads with a stable error", () => {76    const malformedJson = btoa("{").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");77    const unknownType = btoa(JSON.stringify({ type: "BOGUS" }))78      .replace(/\+/g, "-")79      .replace(/\//g, "_")80      .replace(/=+$/g, "");8182    expect(() => decodeSyncMessage("@@@")).toThrow("invalid sync message");83    expect(() => decodeSyncMessage("A")).toThrow("invalid sync message");84    expect(() => decodeSyncMessage(malformedJson)).toThrow("invalid sync message");85    expect(() => decodeSyncMessage(unknownType)).toThrow("invalid sync message");86  });87});