mirror of https://github.com/Squidex/squidex.git
55 changed files with 897 additions and 308 deletions
@ -0,0 +1,100 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace Squidex.Infrastructure |
|||
{ |
|||
public static class Not |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string Defined(string property) |
|||
{ |
|||
return $"{Upper(property)} is required."; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string Defined2(string property1, string property2) |
|||
{ |
|||
return $"If {Lower(property1)} or {Lower(property2)} is used both must be defined."; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string ValidSlug(string property) |
|||
{ |
|||
return $"{Upper(property)} is not a valid slug."; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string GreaterThan(string property, string other) |
|||
{ |
|||
return $"{Upper(property)} must be greater than {Lower(other)}."; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string GreaterEquals(string property, string other) |
|||
{ |
|||
return $"{Upper(property)} must be greater or equal to {Lower(other)}."; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string LessThan(string property, string other) |
|||
{ |
|||
return $"{Upper(property)} must be less than {Lower(other)}."; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string LessEquals(string property, string other) |
|||
{ |
|||
return $"{Upper(property)} must be less or equal to {Lower(other)}."; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string Between<T>(string property, T min, T max) |
|||
{ |
|||
return $"{Upper(property)} must be between {min} and {max}."; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string Valid(string property) |
|||
{ |
|||
return $"{Upper(property)} is not a valid value."; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string New(string type, string property) |
|||
{ |
|||
return $"{Upper(type)} has already this {Lower(property)}."; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static string DefinedOr(string property1, string property2) |
|||
{ |
|||
return $"Either {Lower(property1)} or {Lower(property2)} must be defined."; |
|||
} |
|||
|
|||
private static string Lower(string property) |
|||
{ |
|||
if (char.IsUpper(property[0])) |
|||
{ |
|||
return char.ToLower(property[0]) + property.Substring(1); |
|||
} |
|||
|
|||
return property; |
|||
} |
|||
|
|||
private static string Upper(string property) |
|||
{ |
|||
if (char.IsLower(property[0])) |
|||
{ |
|||
return char.ToUpper(property[0]) + property.Substring(1); |
|||
} |
|||
|
|||
return property; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,160 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; |
|||
|
|||
import { ValidatorsEx } from './validators'; |
|||
|
|||
import { formatError } from './error-formatting'; |
|||
|
|||
describe('formatErrors', () => { |
|||
it('should format min', () => { |
|||
const error = validate(1, Validators.min(2)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must be greater or equal to \'2\'.'); |
|||
}); |
|||
|
|||
it('should format max', () => { |
|||
const error = validate(3, Validators.max(2)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must be less or equal to \'2\'.'); |
|||
}); |
|||
|
|||
it('should format required', () => { |
|||
const error = validate(undefined, Validators.required); |
|||
|
|||
expect(error).toEqual('MY_FIELD is required.'); |
|||
}); |
|||
|
|||
it('should format requiredTrue', () => { |
|||
const error = validate(undefined, Validators.requiredTrue); |
|||
|
|||
expect(error).toEqual('MY_FIELD is required.'); |
|||
}); |
|||
|
|||
it('should format email', () => { |
|||
const error = validate('invalid', Validators.email); |
|||
|
|||
expect(error).toEqual('MY_FIELD must be an email address.'); |
|||
}); |
|||
|
|||
it('should format minLength string', () => { |
|||
const error = validate('x', Validators.minLength(2)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must have at least 2 character(s).'); |
|||
}); |
|||
|
|||
it('should format maxLength string', () => { |
|||
const error = validate('xxx', Validators.maxLength(2)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must not have more than 2 character(s).'); |
|||
}); |
|||
|
|||
it('should format minLength array', () => { |
|||
const error = validate([1], Validators.minLength(2)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must have at least 2 item(s).'); |
|||
}); |
|||
|
|||
it('should format maxLength array', () => { |
|||
const error = validate([1, 1, 1], Validators.maxLength(2)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must not have more than 2 item(s).'); |
|||
}); |
|||
|
|||
it('should format match', () => { |
|||
const error = validate('123', Validators.pattern('[A-Z]')); |
|||
|
|||
expect(error).toEqual('MY_FIELD does not match to the pattern.'); |
|||
}); |
|||
|
|||
it('should format match with message', () => { |
|||
const error = validate('123', ValidatorsEx.pattern('[A-Z]', 'Custom Message')); |
|||
|
|||
expect(error).toEqual('Custom Message'); |
|||
}); |
|||
|
|||
it('should format between exactly', () => { |
|||
const error = validate(2, ValidatorsEx.between(3, 3)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must be exactly \'3\'.'); |
|||
}); |
|||
|
|||
it('should format between range', () => { |
|||
const error = validate(2, ValidatorsEx.between(3, 5)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must be between \'3\' and \'5\'.'); |
|||
}); |
|||
|
|||
it('should format betweenLength string exactly', () => { |
|||
const error = validate('xx', ValidatorsEx.betweenLength(3, 3)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must have exactly 3 character(s).'); |
|||
}); |
|||
|
|||
it('should format betweenLength string range', () => { |
|||
const error = validate('xx', ValidatorsEx.betweenLength(3, 5)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must have between 3 and 5 character(s).'); |
|||
}); |
|||
|
|||
it('should format betweenLength array exactly', () => { |
|||
const error = validate([1], ValidatorsEx.betweenLength(3, 3)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must have exactly 3 item(s).'); |
|||
}); |
|||
|
|||
it('should format betweenLength array range', () => { |
|||
const error = validate([1, 1], ValidatorsEx.betweenLength(3, 5)); |
|||
|
|||
expect(error).toEqual('MY_FIELD must have between 3 and 5 item(s).'); |
|||
}); |
|||
|
|||
it('should format validDateTime', () => { |
|||
const error = validate('invalid', ValidatorsEx.validDateTime()); |
|||
|
|||
expect(error).toEqual('MY_FIELD is not a valid date time.'); |
|||
}); |
|||
|
|||
it('should format validValues', () => { |
|||
const error = validate(5, ValidatorsEx.validValues([1, 2, 3])); |
|||
|
|||
expect(error).toEqual('MY_FIELD is not a valid value.'); |
|||
}); |
|||
|
|||
it('should format validArrayValues', () => { |
|||
const error = validate([2, 4], ValidatorsEx.validArrayValues([1, 2, 3])); |
|||
|
|||
expect(error).toEqual('MY_FIELD contains an invalid value.'); |
|||
}); |
|||
|
|||
it('should format match', () => { |
|||
const formControl1 = new FormControl(1); |
|||
const formControl2 = new FormControl(2); |
|||
|
|||
const formGroup = new FormGroup({ |
|||
field1: formControl1, |
|||
field2: formControl2 |
|||
}); |
|||
|
|||
const formError = ValidatorsEx.match('field2', 'Passwords must match.')!(formControl1)!; |
|||
const formMessage = formatError('MY_FIELD', Object.keys(formError)[0], Object.values(formError)[0], undefined); |
|||
|
|||
expect(formMessage).toEqual('Passwords must match.'); |
|||
|
|||
formGroup.reset(); |
|||
}); |
|||
|
|||
function validate(value: any, validator: ValidatorFn) { |
|||
const formControl = new FormControl(value); |
|||
|
|||
const formError = validator(formControl)!; |
|||
const formMessage = formatError('MY_FIELD', Object.keys(formError)[0], Object.values(formError)[0], value); |
|||
|
|||
return formMessage; |
|||
} |
|||
}); |
|||
@ -0,0 +1,70 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights r vbeserved |
|||
*/ |
|||
|
|||
import { Types } from './../../utils/types'; |
|||
|
|||
const DEFAULT_ERRORS: { [key: string]: string } = { |
|||
between: '{field} must be between \'{min}\' and \'{max}\'.', |
|||
betweenlength: '{field} must have between {minlength} and {maxlength} item(s).', |
|||
betweenlengthstring: '{field} must have between {minlength} and {maxlength} character(s).', |
|||
email: '{field} must be an email address.', |
|||
exactly: '{field} must be exactly \'{expected}\'.', |
|||
exactlylength: '{field} must have exactly {expected} item(s).', |
|||
exactlylengthstring: '{field} must have exactly {expected} character(s).', |
|||
match: '{message}', |
|||
max: '{field} must be less or equal to \'{max}\'.', |
|||
maxlength: '{field} must not have more than {requiredlength} item(s).', |
|||
maxlengthstring: '{field} must not have more than {requiredlength} character(s).', |
|||
min: '{field} must be greater or equal to \'{min}\'.', |
|||
minlength: '{field} must have at least {requiredlength} item(s).', |
|||
minlengthstring: '{field} must have at least {requiredlength} character(s).', |
|||
pattern: '{field} does not match to the pattern.', |
|||
patternmessage: '{message}', |
|||
required: '{field} is required.', |
|||
requiredTrue: '{field} is required.', |
|||
validdatetime: '{field} is not a valid date time.', |
|||
validvalues: '{field} is not a valid value.', |
|||
validarrayvalues: '{field} contains an invalid value.' |
|||
}; |
|||
|
|||
export function formatError(field: string, type: string, properties: any, value: any, errors?: any) { |
|||
type = type.toLowerCase(); |
|||
|
|||
if (Types.isString(value)) { |
|||
if (type === 'minlength') { |
|||
type = 'minlengthstring'; |
|||
} |
|||
|
|||
if (type === 'maxlength') { |
|||
type = 'maxlengthstring'; |
|||
} |
|||
|
|||
if (type === 'exactlylength') { |
|||
type = 'exactlylengthstring'; |
|||
} |
|||
|
|||
if (type === 'betweenlength') { |
|||
type = 'betweenlengthstring'; |
|||
} |
|||
} |
|||
|
|||
let message = (errors ? errors[type] : null) || DEFAULT_ERRORS[type]; |
|||
|
|||
if (!message) { |
|||
return null; |
|||
} |
|||
|
|||
for (let property in properties) { |
|||
if (properties.hasOwnProperty(property)) { |
|||
message = message.replace(`{${property.toLowerCase()}}`, properties[property]); |
|||
} |
|||
} |
|||
|
|||
message = message.replace('{field}', field); |
|||
|
|||
return message; |
|||
} |
|||
Loading…
Reference in new issue