2025-12-03 21:56:50 +00:00
|
|
|
import { describe, it, expect } from 'vitest';
|
|
|
|
|
import {
|
|
|
|
|
validatePasswordStrength,
|
|
|
|
|
calculatePasswordStrength,
|
|
|
|
|
} from './passwordValidator';
|
|
|
|
|
|
|
|
|
|
describe('passwordValidator', () => {
|
|
|
|
|
describe('validatePasswordStrength', () => {
|
|
|
|
|
it('should validate a password with all requirements', () => {
|
|
|
|
|
const result = validatePasswordStrength('SecurePass123!');
|
|
|
|
|
expect(result.isValid).toBe(true);
|
|
|
|
|
expect(result.errors).toHaveLength(0);
|
|
|
|
|
expect(result.strength.length).toBe(true);
|
|
|
|
|
expect(result.strength.upper).toBe(true);
|
|
|
|
|
expect(result.strength.lower).toBe(true);
|
|
|
|
|
expect(result.strength.number).toBe(true);
|
|
|
|
|
expect(result.strength.special).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject password shorter than 8 characters', () => {
|
|
|
|
|
const result = validatePasswordStrength('Test123');
|
|
|
|
|
expect(result.isValid).toBe(false);
|
|
|
|
|
expect(result.errors).toContain('password must be at least 8 characters');
|
|
|
|
|
expect(result.strength.length).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject password longer than 128 characters', () => {
|
2025-12-13 02:34:34 +00:00
|
|
|
const longPassword = `${'A'.repeat(129)}a1!`;
|
2025-12-03 21:56:50 +00:00
|
|
|
const result = validatePasswordStrength(longPassword);
|
|
|
|
|
expect(result.isValid).toBe(false);
|
|
|
|
|
expect(result.errors).toContain(
|
2025-12-13 02:34:34 +00:00
|
|
|
'password must be less than 128 characters',
|
2025-12-03 21:56:50 +00:00
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject password without uppercase letter', () => {
|
|
|
|
|
const result = validatePasswordStrength('test123!@#');
|
|
|
|
|
expect(result.isValid).toBe(false);
|
|
|
|
|
expect(result.errors).toContain(
|
2025-12-13 02:34:34 +00:00
|
|
|
'password must contain at least one uppercase letter',
|
2025-12-03 21:56:50 +00:00
|
|
|
);
|
|
|
|
|
expect(result.strength.upper).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject password without lowercase letter', () => {
|
|
|
|
|
const result = validatePasswordStrength('TEST123!@#');
|
|
|
|
|
expect(result.isValid).toBe(false);
|
|
|
|
|
expect(result.errors).toContain(
|
2025-12-13 02:34:34 +00:00
|
|
|
'password must contain at least one lowercase letter',
|
2025-12-03 21:56:50 +00:00
|
|
|
);
|
|
|
|
|
expect(result.strength.lower).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject password without number', () => {
|
|
|
|
|
const result = validatePasswordStrength('TestPass!@#');
|
|
|
|
|
expect(result.isValid).toBe(false);
|
|
|
|
|
expect(result.errors).toContain(
|
2025-12-13 02:34:34 +00:00
|
|
|
'password must contain at least one number',
|
2025-12-03 21:56:50 +00:00
|
|
|
);
|
|
|
|
|
expect(result.strength.number).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject password without special character', () => {
|
|
|
|
|
const result = validatePasswordStrength('TestPass123');
|
|
|
|
|
expect(result.isValid).toBe(false);
|
|
|
|
|
expect(result.errors).toContain(
|
2025-12-13 02:34:34 +00:00
|
|
|
'password must contain at least one special character',
|
2025-12-03 21:56:50 +00:00
|
|
|
);
|
|
|
|
|
expect(result.strength.special).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should accept password exactly 8 characters', () => {
|
|
|
|
|
const result = validatePasswordStrength('Test123!');
|
|
|
|
|
expect(result.isValid).toBe(true);
|
|
|
|
|
expect(result.errors).toHaveLength(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return multiple errors for password missing multiple requirements', () => {
|
|
|
|
|
const result = validatePasswordStrength('test');
|
|
|
|
|
expect(result.isValid).toBe(false);
|
|
|
|
|
expect(result.errors.length).toBeGreaterThan(1);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should validate password with various special characters', () => {
|
|
|
|
|
const specialChars = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')'];
|
|
|
|
|
specialChars.forEach((char) => {
|
2025-12-13 02:34:34 +00:00
|
|
|
const password = `Test123${char}`;
|
2025-12-03 21:56:50 +00:00
|
|
|
const result = validatePasswordStrength(password);
|
|
|
|
|
expect(result.isValid).toBe(true);
|
|
|
|
|
expect(result.strength.special).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('calculatePasswordStrength', () => {
|
|
|
|
|
it('should return score 5 for strong password', () => {
|
|
|
|
|
const score = calculatePasswordStrength('SecurePass123!');
|
|
|
|
|
expect(score).toBe(5);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return score 0 for empty password', () => {
|
|
|
|
|
const score = calculatePasswordStrength('');
|
|
|
|
|
expect(score).toBe(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return score 2 for password with length and lowercase', () => {
|
|
|
|
|
const score = calculatePasswordStrength('testpass');
|
|
|
|
|
expect(score).toBe(2); // length + lowercase
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return score 2 for password with length and uppercase', () => {
|
|
|
|
|
const score = calculatePasswordStrength('TESTPASS');
|
|
|
|
|
expect(score).toBe(2);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return score 3 for password with length, uppercase, and lowercase', () => {
|
|
|
|
|
const score = calculatePasswordStrength('TestPass');
|
|
|
|
|
expect(score).toBe(3);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return score 4 for password with length, uppercase, lowercase, and number', () => {
|
|
|
|
|
const score = calculatePasswordStrength('TestPass123');
|
|
|
|
|
expect(score).toBe(4);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|