Skip to content

Commit

Permalink
Add matchRegExp validator
Browse files Browse the repository at this point in the history
  • Loading branch information
tobias-walle committed Jul 29, 2017
1 parent a568296 commit 692f769
Show file tree
Hide file tree
Showing 14 changed files with 119 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Isomorphic makes no restrictions which technology you use for that.

*It is recommended to use this library with [typescript](https://www.typescriptlang.org/). But the usage with javascript is also possible.*

You can find all possible validations in [validators.ts](src/validators.ts).
You can find all possible validations in [validators.ts](src/configuration/validators.ts).
The structure of the definitions is the following:

|Property|Description|
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { defaultValueValidatorConfig } from './default-value-validator-config';
import { resolveErrorMessage } from './create-value-validator';
import { ErrorMessage, ValidationTarget } from './error-mapping';
import { resolveErrorMessage } from '../create-value-validator';
import { ErrorMessage, ValidationTarget } from '../model/error-mapping.model';
import { Validators } from './validators';

describe('defaultValueValidatorConfig', () => {
Expand Down Expand Up @@ -38,6 +38,11 @@ describe('defaultValueValidatorConfig', () => {
.toBe('Use a maximum of 3 characters');
});

it('should have valid matchRegExp error messages', async () => {
const matchRegExp = errorMapping.matchRegExp;
expect(await getMessage(matchRegExp.notValid, {target: {name: 'name'}}))
.toBe('Enter a valid name');
});
});

// Helper method for testing the messages
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ValueValidatorConfig } from './create-value-validator';
import { capitalizeFirstLetter, pluralize } from './format.utils';
import { ValueValidatorConfig } from '../create-value-validator';
import { capitalizeFirstLetter, pluralize } from '../utils/format.utils';

export const defaultValueValidatorConfig: ValueValidatorConfig<{}> = {
errorMapping: {
Expand All @@ -19,6 +19,9 @@ export const defaultValueValidatorConfig: ValueValidatorConfig<{}> = {
hasLength: {
shorter: ({params: {min}}) => `Use at least ${min} ${pluralize(min, 'character')}`,
longer: ({params: {max}}) => `Use a maximum of ${max} ${pluralize(max, 'character')}`
},
matchRegExp: {
notValid: ({target: {name}}) => `Enter a valid ${name}`
}
},
context: {}
Expand Down
21 changes: 20 additions & 1 deletion src/resolvers.spec.ts → src/configuration/resolvers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { VALIDATION_RESOLVERS } from './resolvers';
import { ErrorMessages } from './error-mapping';
import { ErrorMessages } from '../model/error-mapping.model';
import { Validators } from './validators';

describe('Resolvers', () => {
Expand Down Expand Up @@ -137,4 +137,23 @@ describe('Resolvers', () => {
expect(hasLength('12345689101')).toBe('longer');
});
});

describe('matchRegExp', () => {
const errorMessages: ErrorMessages<'matchRegExp', {}> = {
notValid: 'notValid'
};
const matchRegex = VALIDATION_RESOLVERS.matchRegExp({errorMessages})({
//language=RegExp
pattern: '/^[ABC]{2}\\d+$/i'
});
it('should detect valid inputs', () => {
expect(matchRegex('ab123')).toBeNull();
expect(matchRegex('Cb3')).toBeNull();
});
it('should detect invalid inputs', () => {
expect(matchRegex('a123')).toBe('notValid');
expect(matchRegex('ac')).toBe('notValid');
expect(matchRegex('Ae1344')).toBe('notValid');
});
});
});
13 changes: 11 additions & 2 deletions src/resolvers.ts → src/configuration/resolvers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ValidationResolvers } from './model';
import { ValidationResolvers } from '../model/validation-resolver.model';
import * as email from 'email-validation';
import { convertStringToRegExp } from '../utils/regex.utils';

export const VALIDATION_RESOLVERS: ValidationResolvers<any> = {
required: ({errorMessages}) => () => (value) => {
Expand Down Expand Up @@ -40,5 +41,13 @@ export const VALIDATION_RESOLVERS: ValidationResolvers<any> = {
return errorMessages.longer;
}
return null;
}
},
matchRegExp: ({errorMessages}) => ({pattern}) => (value) => {
if (value == null) return null;
const regExp: RegExp = convertStringToRegExp(pattern);
if (!regExp.test(value)) {
return errorMessages.notValid;
}
return null;
},
};
20 changes: 20 additions & 0 deletions src/validators.ts → src/configuration/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ export interface Validators {
params: {},
cases: 'notDefined'
};
matchRegExp: {
inputType: string,
params: {
pattern: string
},
cases: 'notValid'
};
isNumber: {
inputType: number
params: {},
Expand All @@ -14,6 +21,11 @@ export interface Validators {
params: {},
cases: 'notValid'
};
//isUrl: {
// inputType: string,
// params: {},
// cases: 'notValid'
//};
inRange: {
inputType: number
params: {
Expand All @@ -30,4 +42,12 @@ export interface Validators {
},
cases: 'shorter' | 'longer'
};
//isInList: {
// inputType: any,
// params: {
// list: any[],
// listName: string
// },
// cases: 'notInList'
//};
}
12 changes: 6 additions & 6 deletions src/create-value-validator.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ValidationResolverConfig, ValidationResolverCreator } from './model';
import { ErrorMapping, ErrorMessageFunction, ValidationTarget } from './error-mapping';
import { ValidationSchema } from './validation-schema';
import { Validators } from './validators';
import { VALIDATION_RESOLVERS } from './resolvers';
import { defaultValueValidatorConfig } from './default-value-validator-config';
import { ValidationResolverConfig, ValidationResolverCreator } from './model/validation-resolver.model';
import { ErrorMapping, ErrorMessageFunction, ValidationTarget } from './model/error-mapping.model';
import { ValidationSchema } from './model/validation-schema.model';
import { Validators } from './configuration/validators';
import { VALIDATION_RESOLVERS } from './configuration/resolvers';
import { defaultValueValidatorConfig } from './configuration/default-value-validator-config';
import deepmerge = require('deepmerge');

export type ValueValidatorConfig<Context> = {
Expand Down
2 changes: 1 addition & 1 deletion src/error-mapping.ts → src/model/error-mapping.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Validators } from './validators';
import { Validators } from '../configuration/validators';

export type Cases<K extends keyof Validators> = Validators[K]['cases'];

Expand Down
4 changes: 2 additions & 2 deletions src/model.ts → src/model/validation-resolver.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Validators } from './validators';
import { ErrorMessage, ErrorMessages } from './error-mapping';
import { Validators } from '../configuration/validators';
import { ErrorMessage, ErrorMessages } from './error-mapping.model';

export type ValidationResolverConfig<K extends keyof Validators, Context> = {
errorMessages: ErrorMessages<K, Context>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Validators } from './validators';
import { Validators } from '../configuration/validators';

export type ValidationSchema = {
[key in keyof Validators]?: Validators[key]['params']
Expand Down
File renamed without changes.
File renamed without changes.
29 changes: 29 additions & 0 deletions src/utils/regex.utils.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { convertStringToRegExp } from './regex.utils';
describe('RegExpUtils', () => {
describe('convertStringToRegExp', () => {

it('should convert a string into a regular expression', () => {
expect(convertStringToRegExp('/abc/').toString()).toBe('/abc/');
expect(convertStringToRegExp('/abc/g').toString()).toBe('/abc/g');
expect(convertStringToRegExp('/abc/gimuy').toString()).toBe('/abc/gimuy');
expect(convertStringToRegExp('/[abc]+\\w*/gimuy').toString()).toBe('/[abc]+\\w*/gimuy');
});

it('should throw an error on invalid strings', () => {
expect.assertions(4);
const test = (pattern: string) => {
try {
convertStringToRegExp(pattern);
} catch (err) {
expect(err).toBeDefined();
}
};

test('');
test('//');
test('/');
test('/abc/xyvvx');
});

});
});
16 changes: 16 additions & 0 deletions src/utils/regex.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Convert a string to a regular expression. The string should be formed like a RegExp
* literal.
* @param pattern
* @returns {RegExp}
*/
export function convertStringToRegExp(pattern: string): RegExp {
const regExpPattern = /^\/(.+)\/([gimuy]*)$/;
const args: string[] | null = regExpPattern.exec(pattern);
if (args === null) {
throw Error(`Invalid regExp string "${pattern}"`);
}
const body = args[1] || '';
const flags = args[2];
return new RegExp(body, flags);
}

0 comments on commit 692f769

Please sign in to comment.