test(19-01): add failing tests for hashPassword/verifyPassword scrypt primitives
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* localCredentials.ts — unit tests for hashPassword / verifyPassword.
|
||||
*
|
||||
* Uses node:crypto scrypt under the hood; no external dependencies.
|
||||
* All tests run without MariaDB or any external service.
|
||||
*
|
||||
* Test suite (TDD RED → GREEN — Plan 19-01 Task 1):
|
||||
* Test 1: correct password verifies true
|
||||
* Test 2: wrong password verifies false
|
||||
* Test 3: two hashes of the same input produce different encoded strings (unique salt)
|
||||
* Test 4: verifyPassword never throws on a malformed hash (returns false)
|
||||
* Test 5: encoded string has the PHC shape: scrypt$N$r$p$<salt_b64url>$<hash_b64url> (6 segments)
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { hashPassword, verifyPassword } from '../../src/auth/localCredentials.js';
|
||||
|
||||
describe('hashPassword / verifyPassword', () => {
|
||||
it('Test 1: verifyPassword(hashPassword(pw), pw) === true (round-trip)', () => {
|
||||
const encoded = hashPassword('hunter2');
|
||||
const result = verifyPassword(encoded, 'hunter2');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('Test 2: verifyPassword(hashPassword(pw), wrong) === false', () => {
|
||||
const encoded = hashPassword('hunter2');
|
||||
const result = verifyPassword(encoded, 'wrong-password');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('Test 3: two hashPassword calls on same input produce different encoded strings (unique salt)', () => {
|
||||
const encoded1 = hashPassword('x');
|
||||
const encoded2 = hashPassword('x');
|
||||
expect(encoded1).not.toBe(encoded2);
|
||||
});
|
||||
|
||||
it('Test 4: verifyPassword returns false (never throws) on a malformed stored hash', () => {
|
||||
expect(() => verifyPassword('not-a-valid-hash', 'x')).not.toThrow();
|
||||
expect(verifyPassword('not-a-valid-hash', 'x')).toBe(false);
|
||||
expect(verifyPassword('', 'x')).toBe(false);
|
||||
expect(verifyPassword('scrypt$bad$data', 'x')).toBe(false);
|
||||
});
|
||||
|
||||
it('Test 5: encoded string has scrypt$N$r$p$salt$hash shape (6 $-delimited segments)', () => {
|
||||
const encoded = hashPassword('testpassword');
|
||||
const segments = encoded.split('$');
|
||||
expect(segments).toHaveLength(6);
|
||||
expect(segments[0]).toBe('scrypt');
|
||||
// N, r, p are numeric
|
||||
expect(Number(segments[1])).toBeGreaterThan(0); // N
|
||||
expect(Number(segments[2])).toBeGreaterThan(0); // r
|
||||
expect(Number(segments[3])).toBeGreaterThan(0); // p
|
||||
// salt and hash are non-empty base64url strings
|
||||
expect(segments[4].length).toBeGreaterThan(0);
|
||||
expect(segments[5].length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user