import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils' import { installPkceS256, type PkceCryptoTarget } from '../src/lib/pkce-s256' describe('PKCE S256 WebCrypto boundary', () => { test('installs a SHA-256 digest backed by the native CSPRNG target', async () => { const target: PkceCryptoTarget = { getRandomValues: (array: T): T => array, } installPkceS256(target) const digest = await target.subtle?.digest?.('SHA-256', utf8ToBytes('abc')) expect(digest).toBeInstanceOf(ArrayBuffer) expect(bytesToHex(new Uint8Array(digest!))).toBe( 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', ) }) test('rejects digest algorithms outside the PKCE contract', async () => { const target: PkceCryptoTarget = { getRandomValues: (array: T): T => array, } installPkceS256(target) await expect(target.subtle?.digest?.('SHA-1', new Uint8Array([1]))).rejects.toThrow( 'pkce_digest_algorithm_unsupported', ) }) test('preserves a complete platform WebCrypto implementation', () => { const digest = jest.fn(async () => new ArrayBuffer(32)) const target: PkceCryptoTarget = { getRandomValues: (array: T): T => array, subtle: { digest }, } installPkceS256(target) expect(target.subtle?.digest).toBe(digest) }) test('fails closed when native random values are unavailable', () => { expect(() => installPkceS256({})).toThrow('pkce_native_csprng_unavailable') }) })