Skip to content

Commit

Permalink
feat: add test
Browse files Browse the repository at this point in the history
  • Loading branch information
tiavina-mika committed Jun 18, 2024
1 parent 9b73052 commit 5cb072b
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 51 deletions.
2 changes: 2 additions & 0 deletions src/PasswordStrengthInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Options = {
export type PasswordsComplexityPass = {
pass: boolean;
message: string;
key?: string;
};

export type ErrorMessages = {
Expand Down Expand Up @@ -66,6 +67,7 @@ const PasswordStrengthInput = forwardRef<HTMLDivElement, PasswordStrengthInputP
const { value } = event.target;

const result = getPasswordScoreAndCriteria(value, errorMessages);
console.log(value, result);
const newErrors = result.errorMessages || [];
setErrors(newErrors);

Expand Down
48 changes: 17 additions & 31 deletions src/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,26 @@
// import {describe, expect, test} from '@jest/globals';
import { getPasswordStrengthResult } from '../PasswordStrengthInput';

// ------------ default options ------------ //
describe('check default labels', () => {
test('tooWeak label', () => {
expect(getPasswordStrengthResult('tooWeak').label).toBe('Too weak');
});

test('weak label', () => {
expect(getPasswordStrengthResult('weak').label).toBe('Weak');
});

test('medium label', () => {
expect(getPasswordStrengthResult('medium').label).toBe('Okay');
});
import { getPasswordScoreAndCriteria } from "../utils";

test('strong label', () => {
expect(getPasswordStrengthResult('strong').label).toBe('Strong');
});
});

// ------------ custom options ------------ //
describe('check override labels', () => {
test('custom label', () => {
const option = getPasswordStrengthResult('tooWeak', { tooWeak: { label: 'Too weak 2' } });
expect(option.label).toBe('Too weak 2');
// ------------ default options ------------ //
describe('check password', () => {
test('check min length', () => {
const { allChecksPassed, errorMessages } = getPasswordScoreAndCriteria('abcde')
expect(allChecksPassed).toBe(false);
const currentPassed = errorMessages.find((error) => error.key === 'lowerCase');
expect(currentPassed?.pass).toBe(true);
});

test('custom color', () => {
const option = getPasswordStrengthResult('medium', { medium: { color: 'red' } });
expect(option.color).toBe('red');
test('check two passed check', () => {
const { allChecksPassed, errorMessages } = getPasswordScoreAndCriteria('abcde8')
expect(allChecksPassed).toBe(false);
const passedChecks = errorMessages.filter((error) => error.key && ['lowerCase', 'number'].includes(error.key));
expect(passedChecks?.length).toBe(2);
});

test('custom color and label', () => {
const option = getPasswordStrengthResult('strong', { strong: { color: 'red', label: 'Strong 2' } });
expect(option.label).toBe('Strong 2');
expect(option.color).toBe('red');
test('check all checks passed', () => {
const { allChecksPassed, errorMessages } = getPasswordScoreAndCriteria('abcde8=F')
expect(allChecksPassed).toBe(true);
expect(errorMessages?.length).toBe(5);
});
});
58 changes: 38 additions & 20 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { ErrorMessages, PasswordsComplexityPass } from "./PasswordStrengthInput";

type ComplexPasswordErrors = {
[key: number]: PasswordsComplexityPass;
}
type ComplexPasswordErrors = Record<'minLength' | 'lowerCase' | 'upperCase' | 'number' | 'specialChar', PasswordsComplexityPass>

type Checks = {
pass: boolean;
key: keyof ComplexPasswordErrors;
}
type PasswordScoreAndCriteria = {
errorMessages?: PasswordsComplexityPass[];
errorMessages: PasswordsComplexityPass[];
allChecksPassed: boolean;
}
export const getPasswordScoreAndCriteria = (password: string, message?: ErrorMessages): PasswordScoreAndCriteria => {
Expand All @@ -17,40 +19,56 @@ export const getPasswordScoreAndCriteria = (password: string, message?: ErrorMes
specialChar = "Must contain at least one special character"
} = message || {};

if (!password) return { allChecksPassed: false};
if (!password) return { allChecksPassed: false, errorMessages: [] };

/**
* all criteria checks
*/
const checks: boolean[] = [
const checks: Checks[] = [
// password length
password.length > 8,
{
pass: password.length >= 8,
key: 'minLength'
},
// password has lowercase
/[a-z]/.test(password),
{
pass: /[a-z]/.test(password),
key: 'lowerCase'
},
// password has uppercase
/[A-Z]/.test(password),
{
pass: /[A-Z]/.test(password),
key: 'upperCase'
},
// password has number
/\d/.test(password),
{
pass: /\d/.test(password),
key: 'number'
},
// password has special character
/[`!@#$%^&*()_\-+=[\]{};':"\\|,.<>/?~ ]/.test(password),
{
pass: /[`!@#$%^&*()_\-+=[\]{};':"\\|,.<>/?~ ]/.test(password),
key: 'specialChar'
}
];

const errorMessages: ComplexPasswordErrors = {
1: { pass: false, message: minLength },
2: { pass: false, message: lowerCase },
3: { pass: false, message: upperCase },
4: { pass: false, message: number },
5: { pass: false, message: specialChar },
minLength: { pass: false, message: minLength },
lowerCase: { pass: false, message: lowerCase },
upperCase: { pass: false, message: upperCase },
number: { pass: false, message: number },
specialChar: { pass: false, message: specialChar },
};

let allChecksPassed: boolean = false;

checks.forEach((check: boolean, index: number) => {
if (errorMessages[index + 1]) {
if (check) {
errorMessages[index + 1] = { ...errorMessages[index + 1], pass: true };
checks.forEach((check: Checks) => {
if (errorMessages[check.key]) {
if (check.pass) {
errorMessages[check.key] = { ...errorMessages[check.key], pass: true, key: check.key };
allChecksPassed = true;
} else {
errorMessages[check.key] = { ...errorMessages[check.key], key: check.key };
allChecksPassed = false;
}
}
Expand Down

0 comments on commit 5cb072b

Please sign in to comment.