Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9de29a5
commit a7090ae
Showing
14 changed files
with
534 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import isFinite from "lodash.isfinite"; | ||
import { emailRegex, passwordRegex } from "./inputRegex"; | ||
import InvalidFieldError from "./InvalidFieldError"; | ||
|
||
export const isEmpty = (field: string, value: unknown): InvalidFieldError<any> | undefined => { | ||
if (typeof value !== "string") { | ||
throw new Error("isEmpty must be called on string"); | ||
} | ||
|
||
if (!value) { | ||
return { | ||
field, | ||
error: `${field}_isEmpty`, | ||
}; | ||
} | ||
}; | ||
|
||
export const isEmail = (field: string, value: unknown): InvalidFieldError<any> | undefined => { | ||
if (typeof value !== "string") { | ||
throw new Error("isEmail must be called on string"); | ||
} | ||
|
||
if (value && !(emailRegex.test(value))) { | ||
return { | ||
field, | ||
error: `${field}_isEmail`, | ||
}; | ||
} | ||
}; | ||
|
||
export const isPassword = (field: string, value: unknown): InvalidFieldError<any> | undefined => { | ||
if (typeof value !== "string") { | ||
throw new Error("isPassword must be called on string"); | ||
} | ||
|
||
if (value && !(passwordRegex.test(value))) { | ||
return { | ||
field, | ||
error: `${field}_isPassword`, | ||
}; | ||
} | ||
}; | ||
|
||
export const isSame = (toCompare: unknown) => (field: string, value: unknown): InvalidFieldError<any> | undefined => { | ||
if (value !== toCompare) { | ||
return { | ||
field, | ||
error: `${field}_isSame_${field}`, | ||
}; | ||
} | ||
}; | ||
|
||
export const isNumber = (field: string, value: unknown): InvalidFieldError<any> | undefined => { | ||
if (value && !isFinite(Number(value))) { | ||
return { | ||
field, | ||
error: `${field}_isNumber`, | ||
}; | ||
} | ||
}; | ||
|
||
export const hasLength = (length: number) => | ||
(field: string, value: unknown): InvalidFieldError<any> | undefined => { | ||
if (typeof value !== "string") { | ||
throw new Error("hasLength must be called on string"); | ||
} | ||
|
||
if (value.length !== length) { | ||
return { | ||
field, | ||
error: `${field}_hasLength:${length}`, | ||
}; | ||
} | ||
}; | ||
|
||
export const hasMinLength = (length: number) => | ||
(field: string, value: unknown): InvalidFieldError<any> | undefined => { | ||
if (typeof value !== "string") { | ||
throw new Error("hasMinLength must be called on string"); | ||
} | ||
|
||
if (value.length < length) { | ||
return { | ||
field, | ||
error: `${field}_hasMinLength:${length}`, | ||
}; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import InvalidFieldError from "./InvalidFieldError"; | ||
import ValidatorRules from "./ValidationRules"; | ||
|
||
abstract class FormValidator<Fields> { | ||
protected formData: Fields; | ||
public rules: ValidatorRules; | ||
public errors: InvalidFieldError<keyof Fields>[]; | ||
|
||
constructor(formData: Fields) { | ||
this.formData = formData; | ||
this.errors = []; | ||
this.rules = {}; | ||
} | ||
|
||
public validate = (): void => { | ||
this.errors = []; | ||
Object.entries(this.formData).map(([field, value]) => { | ||
this.rules[field].map((fn) => { | ||
const error = fn(field, value); | ||
if (error) { | ||
this.errors.push(error); | ||
} | ||
}); | ||
}); | ||
}; | ||
|
||
public hasError = (): boolean => this.errors.length > 0; | ||
} | ||
|
||
export default FormValidator; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
interface InvalidFieldError<Fields> { | ||
error: string; | ||
field: Fields; | ||
} | ||
|
||
export default InvalidFieldError; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import InvalidFieldError from "./InvalidFieldError"; | ||
|
||
export default interface ValidatorRules { | ||
[key: string]: ((field: string, value: unknown) => InvalidFieldError<any> | undefined)[]; | ||
} |
164 changes: 164 additions & 0 deletions
164
src/domain/form/validation/__tests__/FormValidations.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import { | ||
isEmpty, isEmail, isNumber, hasLength, hasMinLength, | ||
} from "../FormValidations"; | ||
import "jest"; | ||
|
||
describe("FormValidations", () => { | ||
const FIELD_NAME = "FIELD_NAME"; | ||
describe("isEmpty", () => { | ||
describe("given a non string value", () => { | ||
it("should throw", () => { | ||
const value = {}; | ||
expect(() => isEmpty(FIELD_NAME, value as unknown as string)).toThrow(); | ||
}); | ||
}); | ||
|
||
describe("given an empty value", () => { | ||
it("should return an error", () => { | ||
const value = ""; | ||
expect(isEmpty(FIELD_NAME, value)).toEqual({ field: FIELD_NAME, error: `${FIELD_NAME}_isEmpty` }); | ||
}); | ||
}); | ||
|
||
describe("given a valid value", () => { | ||
it("should not return no error", () => { | ||
const value = "value"; | ||
expect(isEmpty(FIELD_NAME, value)).toBe(undefined); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("isEmail", () => { | ||
describe("given a non string value", () => { | ||
it("should throw", () => { | ||
const value = {}; | ||
expect(() => isEmail(FIELD_NAME, value as unknown as string)).toThrow(); | ||
}); | ||
}); | ||
|
||
describe("given an empty value", () => { | ||
it("should return no error", () => { | ||
const value = ""; | ||
expect(isEmail(FIELD_NAME, value)).toBe(undefined); | ||
}); | ||
}); | ||
|
||
describe("given a valid email", () => { | ||
it("should return no error", () => { | ||
const value = "email@exemple.ca"; | ||
expect(isEmail(FIELD_NAME, value)).toBe(undefined); | ||
}); | ||
}); | ||
|
||
describe("given a custom email doamin", () => { | ||
it("should return no error", () => { | ||
const value = "email+something@nexapp.ca"; | ||
expect(isEmail(FIELD_NAME, value)).toBe(undefined); | ||
}); | ||
}); | ||
|
||
describe("given an invalid email", () => { | ||
it("should return an error", () => { | ||
const value = "notAnEmail"; | ||
expect(isEmail(FIELD_NAME, value)).toEqual({ field: FIELD_NAME, error: `${FIELD_NAME}_isEmail` }); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("isNumber", () => { | ||
describe("given a string containing only numbers", () => { | ||
it("should return no error", () => { | ||
const value = "123"; | ||
expect(isNumber(FIELD_NAME, value)).toBe(undefined); | ||
}); | ||
}); | ||
|
||
describe("given an string containing letters", () => { | ||
it("should return an error", () => { | ||
const value = "notANumber"; | ||
expect(isNumber(FIELD_NAME, value)).toEqual({ field: FIELD_NAME, error: `${FIELD_NAME}_isNumber` }); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("hasLength", () => { | ||
const LENGTH = 10; | ||
describe("given a non string or array value", () => { | ||
it("should throw", () => { | ||
const value = {}; | ||
expect(() => hasLength(LENGTH)(FIELD_NAME, value as unknown as string)).toThrow(); | ||
}); | ||
}); | ||
|
||
describe("given an empty value", () => { | ||
it("should return an error", () => { | ||
const value = ""; | ||
expect(hasLength(LENGTH)(FIELD_NAME, value)) | ||
.toEqual({ field: FIELD_NAME, error: `${FIELD_NAME}_hasLength:${LENGTH}` }); | ||
}); | ||
}); | ||
|
||
describe("given a value equal to given lenght", () => { | ||
it("should return no error", () => { | ||
const value = "1234567890"; | ||
expect(hasLength(LENGTH)(FIELD_NAME, value)).toBe(undefined); | ||
}); | ||
}); | ||
|
||
describe("given a value longer than length", () => { | ||
it("should return an error", () => { | ||
const value = "1234567890123456789"; | ||
expect(hasLength(LENGTH)(FIELD_NAME, value)) | ||
.toEqual({ field: FIELD_NAME, error: `${FIELD_NAME}_hasLength:${LENGTH}` }); | ||
}); | ||
}); | ||
|
||
describe("given a value shorter than length", () => { | ||
it("should return an error", () => { | ||
const value = "123"; | ||
expect(hasLength(LENGTH)(FIELD_NAME, value)) | ||
.toEqual({ field: FIELD_NAME, error: `${FIELD_NAME}_hasLength:${LENGTH}` }); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("hasMinLength", () => { | ||
const LENGTH = 10; | ||
describe("given a non string or array value", () => { | ||
it("should throw", () => { | ||
const value = {}; | ||
expect(() => hasMinLength(LENGTH)(FIELD_NAME, value as unknown as string)).toThrow(); | ||
}); | ||
}); | ||
|
||
describe("given an empty value", () => { | ||
it("should return an error", () => { | ||
const value = ""; | ||
expect(hasMinLength(LENGTH)(FIELD_NAME, value)) | ||
.toEqual({ field: FIELD_NAME, error: `${FIELD_NAME}_hasMinLength:${LENGTH}` }); | ||
}); | ||
}); | ||
|
||
describe("given a value equal to given length", () => { | ||
it("should return no error", () => { | ||
const value = "1234567890"; | ||
expect(hasMinLength(LENGTH)(FIELD_NAME, value)).toBe(undefined); | ||
}); | ||
}); | ||
|
||
describe("given a value longer to given length", () => { | ||
it("should return no error", () => { | ||
const value = "1234567890123456789"; | ||
expect(hasMinLength(LENGTH)(FIELD_NAME, value)).toBe(undefined); | ||
}); | ||
}); | ||
|
||
describe("given a value shorter than minimum length", () => { | ||
it("should return an error", () => { | ||
const value = "123"; | ||
expect(hasMinLength(LENGTH)(FIELD_NAME, value)) | ||
.toEqual({ field: FIELD_NAME, error: `${FIELD_NAME}_hasMinLength:${LENGTH}` }); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.