All files / src/utils passwordStrength.ts

94.44% Statements 34/36
93.1% Branches 27/29
100% Functions 3/3
93.33% Lines 28/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101                                                      143x 43x     100x 100x 100x 100x     100x     100x 100x 100x 100x 100x 100x 100x       100x 79x 21x 19x   2x     100x                   222x   170x   49x   3x                             444x   340x   98x   6x          
/**
 * Password Strength Utility
 * Story 1.2.2a: Reset Password Confirmation
 *
 * Reusable utility for calculating password strength
 * Used in registration and password reset flows
 */
 
export type PasswordStrength = 'weak' | 'medium' | 'strong';
 
export interface PasswordStrengthResult {
  strength: PasswordStrength | null;
  score: number;
}
 
/**
 * Calculate password strength based on character types and length
 *
 * Algorithm:
 * - Weak: 1-2 character types (e.g., only lowercase + numbers)
 * - Medium: 3 character types (e.g., lower + upper + number)
 * - Strong: 4 character types or 3 types with special char and length >= 12
 *
 * @param password - The password to evaluate
 * @returns PasswordStrengthResult with strength level and numeric score
 */
export function calculatePasswordStrength(password: string): PasswordStrengthResult {
  if (!password) {
    return { strength: null, score: 0 };
  }
 
  const hasLower = /[a-z]/.test(password);
  const hasUpper = /[A-Z]/.test(password);
  const hasNumber = /[0-9]/.test(password);
  const hasSpecial = /[^A-Za-z0-9]/.test(password);
 
  // Count character type diversity
  const charTypeCount = [hasLower, hasUpper, hasNumber, hasSpecial].filter(Boolean).length;
 
  // Calculate strength score (0-6 scale)
  let score = 0;
  if (password.length >= 8) score++;
  if (password.length >= 12) score++;
  if (hasLower) score++;
  if (hasUpper) score++;
  if (hasNumber) score++;
  if (hasSpecial) score++;
 
  // Categorize strength
  let strength: PasswordStrength;
  if (charTypeCount <= 2) {
    strength = 'weak';
  } else if (charTypeCount === 3 || (charTypeCount === 4 && password.length < 12)) {
    strength = 'medium';
  } else {
    strength = 'strong';
  }
 
  return { strength, score };
}
 
/**
 * Get visual representation of password strength for progress bars
 *
 * @param strength - The password strength level
 * @returns Percentage value (0-100) for visual indicators
 */
export function getPasswordStrengthValue(strength: PasswordStrength | null): number {
  switch (strength) {
    case 'weak':
      return 33;
    case 'medium':
      return 66;
    case 'strong':
      return 100;
    default:
      return 0;
  }
}
 
/**
 * Get Material-UI color for password strength indicator
 *
 * @param strength - The password strength level
 * @returns MUI color name ('error' | 'warning' | 'success' | 'inherit')
 */
export function getPasswordStrengthColor(
  strength: PasswordStrength | null
): 'error' | 'warning' | 'success' | 'inherit' {
  switch (strength) {
    case 'weak':
      return 'error';
    case 'medium':
      return 'warning';
    case 'strong':
      return 'success';
    default:
      return 'inherit';
  }
}