import { describe, expect, it } from 'vitest'; import { hashPin, newLock, newSalt, verifyPin } from './pin'; describe('hashPin', () => { it('is deterministic for the same pin and salt', async () => { const salt = 'fixedsalt'; expect(await hashPin('1234', salt)).toBe(await hashPin('1234', salt)); }); it('differs when the salt differs', async () => { expect(await hashPin('1234', 'saltA')).not.toBe(await hashPin('1234', 'saltB')); }); it('differs when the pin differs', async () => { const salt = 'fixedsalt'; expect(await hashPin('1234', salt)).not.toBe(await hashPin('4321', salt)); }); }); describe('newSalt', () => { it('returns a non-empty value', () => { expect(newSalt().length).toBeGreaterThan(0); }); it('returns a fresh value each call', () => { expect(newSalt()).not.toBe(newSalt()); }); }); describe('newLock / verifyPin', () => { it('produces a lock that verifies its own pin', async () => { const lock = await newLock('1234'); expect(lock.hash.length).toBeGreaterThan(0); expect(lock.salt.length).toBeGreaterThan(0); expect(await verifyPin('1234', lock)).toBe(true); }); it('rejects a wrong pin', async () => { const lock = await newLock('1234'); expect(await verifyPin('0000', lock)).toBe(false); }); it('salts each lock independently (same pin, different hashes)', async () => { const a = await newLock('1234'); const b = await newLock('1234'); expect(a.salt).not.toBe(b.salt); expect(a.hash).not.toBe(b.hash); }); });