Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Password validator jan 10 1 #62

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a2c342d
[RED]: should know that "abc" is not valid due to length policy
josegarrera Jan 10, 2025
e7e7c48
[GREEN]: should know that "abc" is not valid due to length policy
josegarrera Jan 10, 2025
0a8f50d
[REFACTOR]: types
josegarrera Jan 10, 2025
02bfc53
[RED]: should know that "abcde" is valid regarding to length policy
josegarrera Jan 10, 2025
5326022
[GREEN]: should know that "abcde" is valid regarding to length policy
josegarrera Jan 10, 2025
c74c617
[GREEN]: should know that "abcdefghi12345678" is not valid due to len…
josegarrera Jan 10, 2025
63222b4
[REFACTOR]: extract constant
josegarrera Jan 10, 2025
71907ab
[REFACTOR]: improved test examples
josegarrera Jan 10, 2025
4b214f4
[RED]: should know that "abcde" is not valid due to number policy
josegarrera Jan 10, 2025
9252816
[GREEN]: should know that "abcde" is not valid due to number policy
josegarrera Jan 10, 2025
12dfb44
[GREEN]: should know that "abc1E" is valid regarding to number policy
josegarrera Jan 10, 2025
9f3794d
[RED]: should know that "1bcde" is not valid due to uppercase policy
josegarrera Jan 10, 2025
c3ce390
[GREEN]: should know that "1bcde" is not valid due to uppercase policy
josegarrera Jan 10, 2025
6338173
[GREEN]: should know that "1bcdE" is valid regarding to uppercase policy
josegarrera Jan 10, 2025
1b89bfd
[REFACTOR]: remove duplication
josegarrera Jan 10, 2025
b12e0f5
[REFACTOR]: extract method
josegarrera Jan 10, 2025
7e903f8
[REFACTOR]: extract method
josegarrera Jan 10, 2025
137baa5
[GREEN]: added green tests
josegarrera Jan 10, 2025
4284754
[REFACTOR]: use .each
josegarrera Jan 10, 2025
1ba2d33
[REFACTOR]: improved readability
josegarrera Jan 10, 2025
3ec7d64
[GREEN]: added test for multiple errors
josegarrera Jan 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,55 @@
import {
Checked,
lengthRestrictionError,
numberRestrictionError,
PasswordValidator, PasswordValidatorError,
uppercaseRestrictionError
} from "./index";


const length = 'length';
const number = 'number';
const uppercase = 'uppercase';

describe('password validator', () => {

test('hello', () => {
expect("between 5 and 15").toContain('5 and 15')
const falsyCases: [string, string, PasswordValidatorError][] = [
['aA1', length, lengthRestrictionError],
['abcdefFGhi12345678', length, lengthRestrictionError],
['abCde', number, numberRestrictionError],
['1bcde', uppercase, uppercaseRestrictionError],
['maxwell1_c', uppercase, uppercaseRestrictionError],
['maxwellTheBe', number, numberRestrictionError],
['thePhysical1234567', length, lengthRestrictionError],
]

test.each(falsyCases)('should know that \"%s\" is not valid regarding to %s policy', (input, policy, error) => {
const result = PasswordValidator.check(input);
expect(result).toHaveProperty('result')
expect(result).toHaveProperty('errors')
expect(result.errors).toContainEqual(error)
expect(result.result).toBeFalsy()
})

const truthyCases: [string, string][] = [
['abc1E', length ],
['abc1E', number ],
['1bcdE', uppercase]
]

test.each(truthyCases)('should know that \"%s\" is valid regarding to %s policy', (password, policy) => {
const result = PasswordValidator.check(password);
expect(result).toHaveProperty('result')
expect(result.errors).toBe(undefined)
expect(result.result).toBeTruthy()
})

it('should show three errors for \"abc\" password', () => {
const result = PasswordValidator.check('abc');
expect(result).toHaveProperty('result')
expect(result).toHaveProperty('errors')
expect(result.errors).toHaveLength(3)
expect(result.result).toBeFalsy()
})
})

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
export type Checked = {
result: boolean,
errors?: PasswordValidatorError[]
};

export const PasswordErrors = {
numberOfCharacters: {
type: 'numberOfCharacters',
message: 'Should be in between 5 and 15 characters long',
},
missingNumber: {
type: 'missingNumber',
message: 'Should contain at least one numeric character',
},
missingUppercase: {
type: 'missingUppercase',
message: 'Should contain at least one uppercase letter',
},
} as const;

export type PasswordErrorType = keyof typeof PasswordErrors;
export type PasswordErrorMessage = typeof PasswordErrors[PasswordErrorType]['message'];

export const lengthRestrictionError = PasswordErrors.numberOfCharacters;
export const numberRestrictionError = PasswordErrors.missingNumber;
export const uppercaseRestrictionError = PasswordErrors.missingUppercase;

export type PasswordValidatorError = {
type: PasswordErrorType;
message: PasswordErrorMessage;
};

export class PasswordValidator {
static check(password: string): Checked {
const checked: Checked = {
result: true
}
let errors: PasswordValidatorError[] = [];
if(this.isNotBetween5And15(password)) {
errors.push(lengthRestrictionError)
}
if(this.hasNoDigits(password)) {
errors.push(numberRestrictionError)
}
if(this.hasNoUppercase(password)) {
errors.push(uppercaseRestrictionError)
}
if (errors.length) {
checked.result = false
checked.errors = errors
}
return checked;
}

private static isNotBetween5And15(password: string) {
return password.length < 5 || password.length > 15;
}

private static hasNoDigits(password: string) {
return !/\d/.test(password);
}

private static hasNoUppercase(password: string) {
return !/[A-Z]/.test(password);
}
}