65 lines
1.9 KiB
TypeScript
65 lines
1.9 KiB
TypeScript
|
|
import { describe, test, expect } from 'bun:test';
|
||
|
|
import * as fc from 'fast-check';
|
||
|
|
import {
|
||
|
|
generateRequestId,
|
||
|
|
generateIdempotencyKey,
|
||
|
|
base64UrlEncode,
|
||
|
|
base64UrlDecode,
|
||
|
|
RequestIdSchema,
|
||
|
|
} from '../../src/index.js';
|
||
|
|
|
||
|
|
describe('generateRequestId', () => {
|
||
|
|
test('produces 22-char base64url string', () => {
|
||
|
|
const id = generateRequestId();
|
||
|
|
expect(id.length).toBe(22);
|
||
|
|
expect(RequestIdSchema.safeParse(id).success).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('1e5 generated IDs are all unique', () => {
|
||
|
|
const seen = new Set<string>();
|
||
|
|
for (let i = 0; i < 100_000; i++) {
|
||
|
|
const id = generateRequestId();
|
||
|
|
expect(seen.has(id)).toBe(false);
|
||
|
|
seen.add(id);
|
||
|
|
}
|
||
|
|
expect(seen.size).toBe(100_000);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('generateIdempotencyKey returns the same shape', () => {
|
||
|
|
expect(generateIdempotencyKey().length).toBe(22);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('base64url encode/decode', () => {
|
||
|
|
test('roundtrip arbitrary bytes (property-based)', () => {
|
||
|
|
fc.assert(
|
||
|
|
fc.property(fc.uint8Array({ minLength: 0, maxLength: 64 }), (bytes) => {
|
||
|
|
const decoded = base64UrlDecode(base64UrlEncode(bytes));
|
||
|
|
expect(decoded).toEqual(bytes);
|
||
|
|
}),
|
||
|
|
{ numRuns: 500 },
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('produces URL-safe alphabet only', () => {
|
||
|
|
fc.assert(
|
||
|
|
fc.property(fc.uint8Array({ minLength: 1, maxLength: 64 }), (bytes) => {
|
||
|
|
const enc = base64UrlEncode(bytes);
|
||
|
|
expect(enc).not.toMatch(/[+/=]/);
|
||
|
|
}),
|
||
|
|
{ numRuns: 200 },
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('handles empty input', () => {
|
||
|
|
expect(base64UrlEncode(new Uint8Array(0))).toBe('');
|
||
|
|
expect(base64UrlDecode('')).toEqual(new Uint8Array(0));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('decodes inputs without padding correctly', () => {
|
||
|
|
expect(base64UrlDecode('YQ')).toEqual(new Uint8Array([0x61]));
|
||
|
|
expect(base64UrlDecode('YWI')).toEqual(new Uint8Array([0x61, 0x62]));
|
||
|
|
expect(base64UrlDecode('YWJj')).toEqual(new Uint8Array([0x61, 0x62, 0x63]));
|
||
|
|
});
|
||
|
|
});
|