Skip to content

Commit

Permalink
Merge pull request #41 from AndreyWV/issue-40/type-validator
Browse files Browse the repository at this point in the history
Issue 40 Added property type validator
  • Loading branch information
AndreyWV committed May 3, 2024
2 parents 3022a7b + 4943ade commit 8d650bb
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.2.0 (2024-05-03)

- Feature: Issue 40 - Added property type validator

## 1.1.0 (2024-04-25)

- Feature: Issue 38 - Serializable validation errors
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# typescript-object-serializer
Typescript library to convert javascript object to typescript class and vice versa

[CHANGELOG](CHANGELOG.md)
[CHANGELOG](CHANGELOG.md)<br>
[Useful snippets](https://github.com/AndreyWV/typescript-object-serializer/wiki)

## Installation and configuration
```sh
Expand Down
12 changes: 10 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typescript-object-serializer",
"version": "1.1.0",
"version": "1.2.0",
"description": "Powerful Scalable Typescript object serializer",
"scripts": {
"build": "TS_NODE_PROJECT=\"webpack.tsconfig.json\" webpack",
Expand Down Expand Up @@ -44,5 +44,13 @@
"webpack-cli": "~5.1.4",
"webpack-dev-server": "~4.15.1"
},
"peerDependencies": {
"reflect-metadata": ">0.1.12 && <1.0.0"
},
"peerDependenciesMeta": {
"reflect-metadata": {
"optional": true
}
},
"source": "src/index.ts"
}
1 change: 1 addition & 0 deletions src/validators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './validators/number-value';
export * from './validators/regexp';
export * from './validators/required';
export * from './validators/string-length';
export * from './validators/type';
88 changes: 88 additions & 0 deletions src/validators/validators/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Constructor } from '../../base-types/constructor';
import { ValidationError } from '../types/validation-error';
import { Validator } from '../types/validator';

/**
* @class TypeValidator Validates that the value is of the specified type.
* @example
* class SomeClass extends SerializableObject {
*
* @property()
* @propertyValidators([TypeValidator.Number()])
* public numberProperty: number;
*
* @property()
* @propertyValidators([TypeValidator.String()])
* public stringProperty: string;
*
* @property()
* @propertyValidators([TypeValidator.Boolean()])
* public booleanProperty: boolean;
*
* @property()
* @propertyValidators([TypeValidator.Object()])
* public someObjectProperty: any;
*
* }
*
* This Validator doesn't return validation error if value is empty or null.
*/
export abstract class TypeValidator extends Validator {

protected isEmpty(value: unknown): boolean {
return value === undefined || value === null;
}

public static String(): Constructor<Validator> {
return class extends TypeValidator {
public validate(value: any, path: string): ValidationError | undefined {
if (this.isEmpty(value)) {
return;
}
if (typeof value !== 'string') {
return new ValidationError('Value must be of type String', path);
}
}
}
}

public static Number(): Constructor<Validator> {
return class extends TypeValidator {
public validate(value: any, path: string): ValidationError | undefined {
if (this.isEmpty(value)) {
return;
}
if (typeof value !== 'number') {
return new ValidationError('Value must be of type Number', path);
}
}
}
}

public static Boolean(): Constructor<Validator> {
return class extends TypeValidator {
public validate(value: any, path: string): ValidationError | undefined {
if (this.isEmpty(value)) {
return;
}
if (typeof value !== 'boolean') {
return new ValidationError('Value must be of type Boolean', path);
}
}
}
}

public static Object(): Constructor<Validator> {
return class extends TypeValidator {
public validate(value: any, path: string): ValidationError | undefined {
if (this.isEmpty(value)) {
return;
}
if (typeof value !== 'object') {
return new ValidationError('Value must be of type Object', path);
}
}
}
}

}
134 changes: 134 additions & 0 deletions tests/validators/validators.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { NumberValueValidator } from '../../src/validators/validators/number-val
import { StringRegexpValidator } from '../../src/validators/validators/regexp';
import { RequiredValidator } from '../../src/validators/validators/required';
import { StringLengthValidator } from '../../src/validators/validators/string-length';
import { TypeValidator } from '../../src/validators/validators/type';

describe('RequiredValidator', () => {

Expand Down Expand Up @@ -114,3 +115,136 @@ describe('NumberValueValidator', () => {
});

});

describe('TypeValidator', () => {

describe('String type', () => {

it('should return validation error if value is not string', () => {
const result = (new (TypeValidator.String())).validate(123, 'test');
expect(result).toEqual({
message: 'Value must be of type String',
path: 'test',
});
});

it('should not return validation error if value is string', () => {
const result = (new (TypeValidator.String())).validate('string value', 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is null', () => {
const result = (new (TypeValidator.String())).validate(null, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is undefined', () => {
const result = (new (TypeValidator.String())).validate(undefined, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is empty string', () => {
const result = (new (TypeValidator.String())).validate('', 'test');
expect(result).toBeUndefined();
});

});

describe('Number type', () => {

it('should return validation error if value is not number', () => {
const result = (new (TypeValidator.Number())).validate('123', 'test');
expect(result).toEqual({
message: 'Value must be of type Number',
path: 'test',
});
});

it('should not return validation error if value is number', () => {
const result = (new (TypeValidator.Number())).validate(123, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is null', () => {
const result = (new (TypeValidator.Number())).validate(null, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is undefined', () => {
const result = (new (TypeValidator.Number())).validate(undefined, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is 0', () => {
const result = (new (TypeValidator.Number())).validate(0, 'test');
expect(result).toBeUndefined();
});

});

describe('Boolean type', () => {

it('should return validation error if value is not boolean', () => {
const result = (new (TypeValidator.Boolean())).validate('123', 'test');
expect(result).toEqual({
message: 'Value must be of type Boolean',
path: 'test',
});
});

it('should not return validation error if value is boolean', () => {
const result = (new (TypeValidator.Boolean())).validate(true, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is null', () => {
const result = (new (TypeValidator.Boolean())).validate(null, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is undefined', () => {
const result = (new (TypeValidator.Boolean())).validate(undefined, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is false', () => {
const result = (new (TypeValidator.Boolean())).validate(false, 'test');
expect(result).toBeUndefined();
});

});

describe('Object type', () => {

it('should return validation error if value is not object', () => {
const result = (new (TypeValidator.Object())).validate('123', 'test');
expect(result).toEqual({
message: 'Value must be of type Object',
path: 'test',
});
});

it('should not return validation error if value is object', () => {
const result = (new (TypeValidator.Object())).validate({ test: true }, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is null', () => {
const result = (new (TypeValidator.Object())).validate(null, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is undefined', () => {
const result = (new (TypeValidator.Object())).validate(undefined, 'test');
expect(result).toBeUndefined();
});

it('should not return validation error if value is empty object', () => {
const result = (new (TypeValidator.Object())).validate({}, 'test');
expect(result).toBeUndefined();
});

});


});

0 comments on commit 8d650bb

Please sign in to comment.