import { describe, test, expect } from 'bun:test'; import { SubtleCryptoProvider } from '@shade/crypto-web'; import { ValidationError } from '@shade/core'; import { generateStreamId, generateStreamSecret, streamIdToString, streamIdFromString, STREAM_ID_BYTES, STREAM_SECRET_BYTES, } from '../src/index.js'; const crypto = new SubtleCryptoProvider(); describe('streamId / streamSecret generators', () => { test('streamId is 16 bytes', () => { expect(generateStreamId(crypto).length).toBe(STREAM_ID_BYTES); }); test('streamSecret is 32 bytes', () => { expect(generateStreamSecret(crypto).length).toBe(STREAM_SECRET_BYTES); }); test('successive generations are not equal (high-entropy)', () => { const a = generateStreamId(crypto); const b = generateStreamId(crypto); expect(a).not.toEqual(b); }); }); describe('base64url encode/decode roundtrip', () => { test('roundtrips arbitrary 16-byte streamIds', () => { for (let i = 0; i < 50; i++) { const id = generateStreamId(crypto); const s = streamIdToString(id); expect(streamIdFromString(s)).toEqual(id); } }); test('emits URL-safe alphabet (no +, /, =)', () => { for (let i = 0; i < 50; i++) { const s = streamIdToString(generateStreamId(crypto)); expect(s).not.toMatch(/[+/=]/); } }); test('rejects wrong-length streamId on encode', () => { expect(() => streamIdToString(new Uint8Array(15))).toThrow(ValidationError); expect(() => streamIdToString(new Uint8Array(17))).toThrow(ValidationError); }); test('rejects strings that decode to wrong length', () => { expect(() => streamIdFromString('AAAA')).toThrow(ValidationError); }); });