Files
PicAnalysis/backend/tests/unit/services/password.service.test.ts

123 lines
4.0 KiB
TypeScript
Raw Normal View History

/**
* Password Service Unit Tests
* TDD: Test-Driven Development
*/
import { describe, it, expect } from '@jest/globals';
import { PasswordService } from '../../../src/services/password.service';
describe('PasswordService', () => {
describe('hash', () => {
it('should hash password with bcrypt', async () => {
// @ralph 这个测试是否清晰描述了期望行为?
const plainPassword = 'MySecurePassword123!';
const hash = await PasswordService.hash(plainPassword);
expect(hash).toBeDefined();
expect(hash).not.toBe(plainPassword);
expect(hash.length).toBe(60); // bcrypt hash length
});
it('should generate different hashes for same password (salt)', async () => {
// @ralph 这是否验证了salt的正确性
const password = 'test123';
const hash1 = await PasswordService.hash(password);
const hash2 = await PasswordService.hash(password);
expect(hash1).not.toBe(hash2);
});
it('should handle empty string', async () => {
// @ralph 边界条件是否考虑充分?
const hash = await PasswordService.hash('');
expect(hash).toBeDefined();
expect(hash.length).toBe(60);
});
it('should handle special characters', async () => {
// @ralph 特殊字符是否正确处理?
const password = '!@#$%^&*()_+-=[]{}|;:\'",.<>?/~`';
const hash = await PasswordService.hash(password);
expect(hash).toBeDefined();
});
it('should handle very long passwords', async () => {
// @ralph 是否考虑了长度限制?
const password = 'a'.repeat(1000);
const hash = await PasswordService.hash(password);
expect(hash).toBeDefined();
});
});
describe('verify', () => {
it('should verify correct password', async () => {
// @ralph 基本功能是否正确?
const password = 'test123';
const hash = await PasswordService.hash(password);
const isValid = await PasswordService.verify(password, hash);
expect(isValid).toBe(true);
});
it('should reject wrong password', async () => {
// @ralph 错误密码是否被正确拒绝?
const hash = await PasswordService.hash('test123');
const isValid = await PasswordService.verify('wrong', hash);
expect(isValid).toBe(false);
});
it('should be case sensitive', async () => {
// @ralph 大小写敏感性是否正确?
const hash = await PasswordService.hash('Password123');
const isValid = await PasswordService.verify('password123', hash);
expect(isValid).toBe(false);
});
it('should reject invalid hash format', async () => {
// @ralph 错误处理是否完善?
await expect(
PasswordService.verify('test', 'invalid-hash')
).rejects.toThrow();
});
it('should reject empty hash', async () => {
// @ralph 空值处理是否正确?
await expect(
PasswordService.verify('test', '')
).rejects.toThrow();
});
it('should handle unicode characters', async () => {
// @ralph Unicode是否正确处理
const password = '密码123🔐';
const hash = await PasswordService.hash(password);
const isValid = await PasswordService.verify(password, hash);
expect(isValid).toBe(true);
});
});
describe('strength validation', () => {
it('should validate strong password', () => {
// @ralph 强度规则是否合理?
const strong = PasswordService.checkStrength('Str0ng!Pass');
expect(strong.isStrong).toBe(true);
});
it('should reject weak password (too short)', () => {
// @ralph 弱密码是否被正确识别?
const weak = PasswordService.checkStrength('12345');
expect(weak.isStrong).toBe(false);
expect(weak.reason).toContain('长度');
});
it('should reject weak password (no numbers)', () => {
// @ralph 规则是否全面?
const weak = PasswordService.checkStrength('abcdefgh');
expect(weak.isStrong).toBe(false);
});
});
});