feat(validate): use static validatorName instead of instance name (#600)

This commit is contained in:
George Serbanescu 2020-02-26 16:24:01 +02:00 committed by Joren Broekema
parent 62978a559a
commit 7c45dd6839
28 changed files with 233 additions and 248 deletions

View file

@ -237,13 +237,12 @@ Below is a more advanced validator on the group that evaluates the children chec
{() => {
loadDefaultFeedbackMessages();
class HasMinTwoChecked extends Validator {
constructor(...args) {
super(...args);
this.name = 'HasMinTwoChecked';
}
execute(value) {
return value.length < 2;
}
static get validatorName() {
return 'HasMinTwoChecked';
}
static async getMessage() {
return 'You need to select at least 2 values.';
}
@ -284,15 +283,15 @@ import { Required, Validator, loadDefaultFeedbackMessages } from '@lion/validate
loadDefaultFeedbackMessages();
class HasMinTwoChecked extends Validator {
constructor(...args) {
super(...args);
this.name = 'HasMinTwoChecked';
}
execute(value) {
return value.length < 2;
}
static get validatorName() {
return 'HasMinTwoChecked';
}
static async getMessage() {
return 'You need to select at least 2 values.';
}

View file

@ -338,9 +338,8 @@ export function runFormatMixinSuite(customConfig) {
// that set hasError back to false when the user input is mimicked.
const AlwaysInvalid = class extends Validator {
constructor(...args) {
super(...args);
this.name = 'AlwaysInvalid';
static get validatorName() {
return 'AlwaysInvalid';
}
execute() {

View file

@ -298,9 +298,8 @@ describe('<lion-field>', () => {
it('should conditionally show error', async () => {
const HasX = class extends Validator {
constructor() {
super();
this.name = 'HasX';
static get validatorName() {
return 'HasX';
}
execute(value) {
@ -412,9 +411,8 @@ describe('<lion-field>', () => {
it('will only update formattedValue when valid on `user-input-changed`', async () => {
const formatterSpy = sinon.spy(value => `foo: ${value}`);
const Bar = class extends Validator {
constructor(...args) {
super(...args);
this.name = 'Bar';
static get validatorName() {
return 'Bar';
}
execute(value) {

View file

@ -1,9 +1,8 @@
import { Validator } from '@lion/validate';
export class FormElementsHaveNoError extends Validator {
constructor() {
super();
this.name = 'FormElementsHaveNoError';
static get validatorName() {
return 'FormElementsHaveNoError';
}
// eslint-disable-next-line class-methods-use-this

View file

@ -343,9 +343,8 @@ describe('<lion-fieldset>', () => {
describe('Validation', () => {
it('validates on init', async () => {
class IsCat extends Validator {
constructor() {
super();
this.name = 'IsCat';
static get validatorName() {
return 'IsCat';
}
execute(value) {
@ -376,9 +375,8 @@ describe('<lion-fieldset>', () => {
it('has a special validator for all children - can be checked via this.error.FormElementsHaveNoError', async () => {
class IsCat extends Validator {
constructor() {
super();
this.name = 'IsCat';
static get validatorName() {
return 'IsCat';
}
execute(value) {
@ -405,9 +403,8 @@ describe('<lion-fieldset>', () => {
it('validates on children (de)registration', async () => {
class HasEvenNumberOfChildren extends Validator {
constructor() {
super();
this.name = 'HasEvenNumberOfChildren';
static get validatorName() {
return 'HasEvenNumberOfChildren';
}
execute(value) {
@ -561,9 +558,8 @@ describe('<lion-fieldset>', () => {
it('potentially shows fieldset error message on interaction change', async () => {
class Input1IsTen extends Validator {
constructor() {
super();
this.name = 'Input1IsTen';
static get validatorName() {
return 'Input1IsTen';
}
execute(value) {
@ -593,9 +589,8 @@ describe('<lion-fieldset>', () => {
it('show error if tabbing "out" of last ', async () => {
class Input1IsTen extends Validator {
constructor() {
super();
this.name = 'Input1IsTen';
static get validatorName() {
return 'Input1IsTen';
}
execute(value) {
@ -916,9 +911,8 @@ describe('<lion-fieldset>', () => {
it('has correct validation afterwards', async () => {
class IsCat extends Validator {
constructor() {
super();
this.name = 'IsCat';
static get validatorName() {
return 'IsCat';
}
execute(value) {
@ -927,9 +921,8 @@ describe('<lion-fieldset>', () => {
}
}
class ColorContainsA extends Validator {
constructor() {
super();
this.name = 'ColorContainsA';
static get validatorName() {
return 'ColorContainsA';
}
execute(value) {

View file

@ -363,9 +363,8 @@ You can even hard code localization in there if needed or you can use a localiza
<Story name="Custom Validators">
{() => {
class MyValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'myValidator';
static get validatorName() {
return 'myValidator';
}
execute(modelValue, param) {
return modelValue !== param;
@ -394,7 +393,10 @@ You can even hard code localization in there if needed or you can use a localiza
class MyValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'myValidator';
}
static get validatorName() {
return 'myValidator';
}
execute(modelValue, param) {
@ -511,8 +513,12 @@ Oftern
class AsyncValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'asyncValidator';
this.async = true;
}
static get validatorName() {
return 'asyncValidator';
}
static get async() {
return true;
}
async execute() {
console.log('async pending...');
@ -549,8 +555,12 @@ function pause(ms = 0) {
class AsyncValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'asyncValidator';
this.async = true;
}
static get validatorName() {
return 'asyncValidator';
}
static get async() {
return true;
}
async execute() {
console.log('async pending...');

View file

@ -105,9 +105,8 @@ In the following example we will demonstrate this with interaction states, the m
// Define a demo validator that should only be visible on an odd amount of characters
// const OddValidator = [modelValue => ({ odd: modelValue.length % 2 !== 0 })];
class OddValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'OddValidator';
static get validatorName() {
return 'OddValidator';
}
// eslint-disable-next-line class-methods-use-this
execute(value) {

View file

@ -175,9 +175,8 @@ Try it by typing something in the input, then removing it.
<Story name="Validation">
{() => {
const DemoValidator = class extends Validator {
constructor() {
super();
this.name = 'DemoValidator';
static get validatorName() {
return 'DemoValidator';
}
execute(value) {
if (value && value.input1) {
@ -199,9 +198,8 @@ Try it by typing something in the input, then removing it.
```js
const DemoValidator = class extends Validator {
constructor() {
super();
this.name = 'DemoValidator';
static get validatorName() {
return 'DemoValidator';
}
execute(value) {
@ -230,9 +228,8 @@ You can have your fieldset validator take into consideration multiple fields.
<Story name="Validating 2 fields">
{() => {
const IsCatsAndDogs = class extends Validator {
constructor() {
super();
this.name = 'IsCatsAndDogs';
static get validatorName() {
return 'IsCatsAndDogs';
}
execute(value) {
return !(value.input1 === 'cats' && value.input2 === 'dogs');
@ -262,9 +259,8 @@ You can have your fieldset validator take into consideration multiple fields.
```js
const IsCatsAndDogs = class extends Validator {
constructor() {
super();
this.name = 'IsCatsAndDogs';
static get validatorName() {
return 'IsCatsAndDogs';
}
execute(value) {
@ -308,9 +304,8 @@ You can have your fieldset validator take into accounts multiple nested fieldset
<Story name="Validating 2 fieldsets">
{() => {
const IsCatsDogs = class extends Validator {
constructor() {
super();
this.name = 'IsCatsDogs';
static get validatorName() {
return 'IsCatsAndDogs';
}
execute(value) {
if ((value.inner1 && value.inner1.input1 === 'cats') &&
@ -350,9 +345,8 @@ You can have your fieldset validator take into accounts multiple nested fieldset
```js
const IsCatsDogs = class extends Validator {
constructor() {
super();
this.name = 'IsCatsDogs';
static get validatorName() {
return 'IsCatsDogs';
}
execute(value) {

View file

@ -322,14 +322,14 @@ export class LionInputDatepicker extends OverlayMixin(LionInputDate) {
// On every validator change, synchronize disabled dates: this means
// we need to extract minDate, maxDate, minMaxDate and disabledDates validators
validators.forEach(v => {
if (v.name === 'MinDate') {
if (v.constructor.name === 'MinDate') {
this.__calendarMinDate = v.param;
} else if (v.name === 'MaxDate') {
} else if (v.constructor.name === 'MaxDate') {
this.__calendarMaxDate = v.param;
} else if (v.name === 'MinMaxDate') {
} else if (v.constructor.name === 'MinMaxDate') {
this.__calendarMinDate = v.param.min;
this.__calendarMaxDate = v.param.max;
} else if (v.name === 'IsDateDisabled') {
} else if (v.constructor.name === 'IsDateDisabled') {
this.__calendarDisableDates = v.param;
}
});

View file

@ -69,9 +69,8 @@ loadDefaultFeedbackMessages();
<Story name="Custom Validator">
{() => {
class GmailOnly extends Validator {
constructor(...args) {
super(...args);
this.name = 'GmailOnly';
static get validatorName() {
return 'GmailOnly';
}
execute(value) {
let hasError = false;
@ -98,9 +97,8 @@ loadDefaultFeedbackMessages();
import { Validator } from '@lion/validate';
class GmailOnly extends Validator {
constructor(...args) {
super(...args);
this.name = 'GmailOnly';
static get validatorName() {
return 'GmailOnly';
}
execute(value) {

View file

@ -1,8 +1,8 @@
/* eslint-disable max-classes-per-file */
import { isValidIBAN } from 'ibantools';
import { Validator } from '@lion/validate';
import { localize } from '@lion/localize';
import { Validator } from '@lion/validate';
import { isValidIBAN } from 'ibantools';
let loaded = false;
const loadTranslations = async () => {
@ -19,9 +19,8 @@ const loadTranslations = async () => {
};
export class IsIBAN extends Validator {
constructor(...args) {
super(...args);
this.name = 'IsIBAN';
static get validatorName() {
return 'IsIBAN';
}
// eslint-disable-next-line class-methods-use-this
@ -36,9 +35,8 @@ export class IsIBAN extends Validator {
}
export class IsCountryIBAN extends IsIBAN {
constructor(...args) {
super(...args);
this.name = 'IsCountryIBAN';
static get validatorName() {
return 'IsCountryIBAN';
}
execute(value) {

View file

@ -192,9 +192,8 @@ You can also create a validator that validates whether a certain option is check
<Story name="Validate item">
{() => {
class IsBrontosaurus extends Validator {
constructor() {
super();
this.name = 'IsBrontosaurus';
static get validatorName() {
return 'IsBrontosaurus';
}
execute(value) {
return value === 'brontosaurus';
@ -227,9 +226,8 @@ You can also create a validator that validates whether a certain option is check
import { loadDefaultFeedbackMessages, Required, Validator } from 'lion/validate';
class IsBrontosaurus extends Validator {
constructor() {
super();
this.name = 'IsBrontosaurus';
static get validatorName() {
return 'IsBrontosaurus';
}
execute(value) {
return value === 'brontosaurus';

View file

@ -65,9 +65,8 @@ Simple example that illustrates where validation feedback will be displayed.
<Story name="Validation">
{() => {
const IsTrue = class extends Validator {
constructor(...args) {
super(...args);
this.name = 'IsTrue';
static get validatorName() {
return 'IsTrue';
}
execute(value) {
return !value.checked;
@ -98,9 +97,8 @@ import { Validator } from '@lion/validate';
import { LionSwitch } from '@lion/switch/src/LionSwitch';
const IsTrue = class extends Validator {
constructor(...args) {
super(...args);
this.name = 'IsTrue';
static get validatorName() {
return 'IsTrue';
}
execute(value) {
return !value.checked;

View file

@ -42,9 +42,8 @@ import { Required, IsString, MaxLength, DefaultSuccess, Validator } from '@lion/
const isInitialsRegex = /^([A-Z]\.)+$/;
class IsInitialsExample extends Validator {
constructor(...args) {
super(...args);
this.name = 'IsExampleInitials';
static get validatorName() {
return 'IsExampleInitials';
}
execute(value) {

View file

@ -323,8 +323,12 @@ export const ValidateMixin = dedupeMixin(
const /** @type {Validator[]} */ filteredValidators = this._allValidators.filter(
v => !(v instanceof ResultValidator) && !(v instanceof Required),
);
const /** @type {Validator[]} */ syncValidators = filteredValidators.filter(v => !v.async);
const /** @type {Validator[]} */ asyncValidators = filteredValidators.filter(v => v.async);
const /** @type {Validator[]} */ syncValidators = filteredValidators.filter(
v => !v.constructor.async,
);
const /** @type {Validator[]} */ asyncValidators = filteredValidators.filter(
v => v.constructor.async,
);
/**
* 2. Synchronous validators
@ -378,7 +382,7 @@ export const ValidateMixin = dedupeMixin(
__executeResultValidators(regularValidationResult) {
/** @type {ResultValidator[]} */
const resultValidators = this._allValidators.filter(
v => !v.async && v instanceof ResultValidator,
v => !v.constructor.async && v instanceof ResultValidator,
);
return resultValidators.filter(v =>
@ -415,7 +419,7 @@ export const ValidateMixin = dedupeMixin(
if (!validationStates[v.type]) {
validationStates[v.type] = {};
}
validationStates[v.type][v.name] = true;
validationStates[v.type][v.constructor.name] = true;
});
this.validationStates = validationStates;
this.hasFeedbackFor = [...new Set(this.__validationResult.map(v => v.type))];
@ -457,7 +461,7 @@ export const ValidateMixin = dedupeMixin(
}
if (this.constructor.validationTypes.indexOf(v.type) === -1) {
// throws in constructor are not visible to end user so we do both
const errorMessage = `This component does not support the validator type "${v.type}" used in "${v.name}". You may change your validators type or add it to the components "static get validationTypes() {}".`;
const errorMessage = `This component does not support the validator type "${v.type}" used in "${v.constructor.validatorName}". You may change your validators type or add it to the components "static get validationTypes() {}".`;
// eslint-disable-next-line no-console
console.error(errorMessage, this);
throw new Error(errorMessage);

View file

@ -4,13 +4,19 @@ export class Validator {
constructor(param, config) {
fakeExtendsEventTarget(this);
this.name = '';
this.async = false;
this.__param = param;
this.__config = config || {};
this.type = (config && config.type) || 'error'; // Default type supported by ValidateMixin
}
static get validatorName() {
return '';
}
static get async() {
return false;
}
/**
* @desc The function that returns a Boolean
* @param {string|Date|Number|object} modelValue
@ -18,8 +24,10 @@ export class Validator {
* @returns {Boolean|Promise<Boolean>}
*/
execute(/* modelValue, param */) {
if (!this.name) {
throw new Error('You must provide a name like "this.name = \'IsCat\'" for your Validator');
if (!this.validatorName) {
throw new Error(
'A validator needs to have a name! Please set it via "static get validatorName() { return \'IsCat\'; }"',
);
}
}
@ -52,7 +60,7 @@ export class Validator {
*/
async _getMessage(data) {
const composedData = {
name: this.name,
name: this.constructor.validatorName,
type: this.type,
params: this.param,
config: this.config,

View file

@ -9,9 +9,8 @@ function isDate(value) {
}
export class IsDate extends Validator {
constructor(...args) {
super(...args);
this.name = 'IsDate';
static get validatorName() {
return 'IsDate';
}
// eslint-disable-next-line class-methods-use-this
@ -25,9 +24,8 @@ export class IsDate extends Validator {
}
export class MinDate extends Validator {
constructor(...args) {
super(...args);
this.name = 'MinDate';
static get validatorName() {
return 'MinDate';
}
execute(value, min = this.param) {
@ -40,9 +38,8 @@ export class MinDate extends Validator {
}
export class MaxDate extends Validator {
constructor(...args) {
super(...args);
this.name = 'MaxDate';
static get validatorName() {
return 'MaxDate';
}
execute(value, max = this.param) {
@ -55,9 +52,8 @@ export class MaxDate extends Validator {
}
export class MinMaxDate extends Validator {
constructor(...args) {
super(...args);
this.name = 'MinMaxDate';
static get validatorName() {
return 'MinMaxDate';
}
execute(value, { min = 0, max = 0 } = this.param) {
@ -70,9 +66,8 @@ export class MinMaxDate extends Validator {
}
export class IsDateDisabled extends Validator {
constructor(...args) {
super(...args);
this.name = 'IsDateDisabled';
static get validatorName() {
return 'IsDateDisabled';
}
execute(value, isDisabledFn = this.param) {

View file

@ -11,9 +11,8 @@ const isNumber = value =>
value === value && typeof value === 'number';
export class IsNumber extends Validator {
constructor(...args) {
super(...args);
this.name = 'IsNumber';
static get validatorName() {
return 'IsNumber';
}
// eslint-disable-next-line class-methods-use-this
@ -27,9 +26,8 @@ export class IsNumber extends Validator {
}
export class MinNumber extends Validator {
constructor(...args) {
super(...args);
this.name = 'MinNumber';
static get validatorName() {
return 'MinNumber';
}
execute(value, min = this.param) {
@ -42,9 +40,8 @@ export class MinNumber extends Validator {
}
export class MaxNumber extends Validator {
constructor(...args) {
super(...args);
this.name = 'MaxNumber';
static get validatorName() {
return 'MaxNumber';
}
execute(value, max = this.param) {
@ -57,9 +54,8 @@ export class MaxNumber extends Validator {
}
export class MinMaxNumber extends Validator {
constructor(...args) {
super(...args);
this.name = 'MinMaxNumber';
static get validatorName() {
return 'MinMaxNumber';
}
execute(value, { min = 0, max = 0 } = this.param) {

View file

@ -1,9 +1,8 @@
import { Validator } from '../Validator.js';
export class Required extends Validator {
constructor(...args) {
super(...args);
this.name = 'Required';
static get validatorName() {
return 'Required';
}
/**

View file

@ -4,9 +4,8 @@ import { Validator } from '../Validator.js';
const isString = value => typeof value === 'string';
export class IsString extends Validator {
constructor(...args) {
super(...args);
this.name = 'IsString';
static get validatorName() {
return 'IsString';
}
// eslint-disable-next-line class-methods-use-this
@ -20,9 +19,8 @@ export class IsString extends Validator {
}
export class EqualsLength extends Validator {
constructor(...args) {
super(...args);
this.name = 'EqualsLength';
static get validatorName() {
return 'EqualsLength';
}
execute(value, length = this.param) {
@ -35,9 +33,8 @@ export class EqualsLength extends Validator {
}
export class MinLength extends Validator {
constructor(...args) {
super(...args);
this.name = 'MinLength';
static get validatorName() {
return 'MinLength';
}
execute(value, min = this.param) {
@ -50,9 +47,8 @@ export class MinLength extends Validator {
}
export class MaxLength extends Validator {
constructor(...args) {
super(...args);
this.name = 'MaxLength';
static get validatorName() {
return 'MaxLength';
}
execute(value, max = this.param) {
@ -65,9 +61,8 @@ export class MaxLength extends Validator {
}
export class MinMaxLength extends Validator {
constructor(...args) {
super(...args);
this.name = 'MinMaxLength';
static get validatorName() {
return 'MinMaxLength';
}
execute(value, { min = 0, max = 0 } = this.param) {
@ -81,9 +76,8 @@ export class MinMaxLength extends Validator {
const isEmailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
export class IsEmail extends Validator {
constructor(...args) {
super(...args);
this.name = 'IsEmail';
static get validatorName() {
return 'IsEmail';
}
// eslint-disable-next-line class-methods-use-this

View file

@ -46,11 +46,6 @@ All validators extend from the default `Validator` class. Below example is an ex
```js
class MyValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'MyValidator';
}
execute(modelValue, param) {
const hasFeedback = false;
if (modelValue === param) {
@ -59,6 +54,10 @@ class MyValidator extends Validator {
return hasFeedback;
}
static get validatorName() {
return 'Required';
}
static getMessage({ fieldName }) {
return `Please fill in ${fieldName}`;
}
@ -87,7 +86,7 @@ You can implement your own custom message for a default validator. Pass a getMes
```js
function getCustomMessage(data) {
return `${data.name} is a required field`;
return `${data.validatorName} is a required field`;
}
```
@ -113,12 +112,6 @@ You can make your async validators as follows:
```js
class AsyncValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'AsyncValidator';
this.async = true;
}
async execute() {
console.log('async pending...');
await pause(2000);
@ -126,6 +119,12 @@ class AsyncValidator extends Validator {
return true;
}
static get validatorName() {
return 'AsyncValidator';
}
static get async() { return true; }
static getMessage({ modelValue }) {
return `Validated for modelValue: ${modelValue}`;
}

View file

@ -2,9 +2,8 @@
import { Validator } from '../src/Validator.js';
export class AlwaysInvalid extends Validator {
constructor(...args) {
super(...args);
this.name = 'AlwaysInvalid';
static get validatorName() {
return 'AlwaysInvalid';
}
execute() {
@ -14,9 +13,8 @@ export class AlwaysInvalid extends Validator {
}
export class AlwaysValid extends Validator {
constructor(...args) {
super(...args);
this.name = 'AlwaysValid';
static get validatorName() {
return 'AlwaysValid';
}
execute() {
@ -26,9 +24,8 @@ export class AlwaysValid extends Validator {
}
export class AsyncAlwaysValid extends AlwaysValid {
constructor(...args) {
super(...args);
this.async = true;
static get async() {
return true;
}
execute() {
@ -37,9 +34,8 @@ export class AsyncAlwaysValid extends AlwaysValid {
}
export class AsyncAlwaysInvalid extends AlwaysValid {
constructor(...args) {
super(...args);
this.async = true;
static get async() {
return true;
}
async execute() {

View file

@ -1,22 +1,21 @@
import { expect, fixture, html, unsafeStatic, defineCE, aTimeout } from '@open-wc/testing';
import sinon from 'sinon';
import { LitElement } from '@lion/core';
import { aTimeout, defineCE, expect, fixture, html, unsafeStatic } from '@open-wc/testing';
import sinon from 'sinon';
import {
AlwaysValid,
AlwaysInvalid,
AsyncAlwaysValid,
AsyncAlwaysInvalid,
} from '../test-helpers.js';
import {
ValidateMixin,
Unparseable,
Validator,
ResultValidator,
Required,
MinLength,
MaxLength,
MinLength,
Required,
ResultValidator,
Unparseable,
ValidateMixin,
Validator,
} from '../index.js';
import {
AlwaysInvalid,
AlwaysValid,
AsyncAlwaysInvalid,
AsyncAlwaysValid,
} from '../test-helpers.js';
export function runValidateMixinSuite(customConfig) {
const cfg = {
@ -104,9 +103,12 @@ export function runValidateMixinSuite(customConfig) {
class MajorValidator extends Validator {
constructor() {
super();
this.name = 'MajorValidator';
this.type = 'major error';
}
static get validatorName() {
return 'MajorValidator';
}
}
const el = await fixture(html`<${tag}></${tag}>`);
expect(() => {
@ -218,9 +220,8 @@ export function runValidateMixinSuite(customConfig) {
it('finally checks for ResultValidators: creates TotalValidationResult', async () => {
class MyResult extends ResultValidator {
constructor(...args) {
super(...args);
this.name = 'ResultValidator';
static get validatorName() {
return 'ResultValidator';
}
}
@ -285,21 +286,27 @@ export function runValidateMixinSuite(customConfig) {
class IsCat extends Validator {
constructor(...args) {
super(...args);
this.name = 'isCat';
this.execute = (modelValue, param) => {
const validateString = param && param.number ? `cat${param.number}` : 'cat';
const showError = modelValue !== validateString;
return showError;
};
}
static get validatorName() {
return 'isCat';
}
}
class OtherValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'otherValidator';
this.execute = () => true;
}
static get validatorName() {
return 'otherValidator';
}
}
it('Validators will be called with ".modelValue" as first argument', async () => {
@ -357,11 +364,11 @@ export function runValidateMixinSuite(customConfig) {
`);
el.modelValue = 'cat';
expect(el.validationStates.error.isCat).to.be.undefined;
expect(el.validationStates.error.IsCat).to.be.undefined;
el.modelValue = 'dog';
expect(el.validationStates.error.isCat).to.be.true;
expect(el.validationStates.error.IsCat).to.be.true;
el.modelValue = '';
expect(el.validationStates.error.isCat).to.be.undefined;
expect(el.validationStates.error.IsCat).to.be.undefined;
});
it('Validators get retriggered on parameter change', async () => {
@ -391,10 +398,12 @@ export function runValidateMixinSuite(customConfig) {
});
class IsAsyncCat extends Validator {
constructor(param, config) {
super(param, config);
this.name = 'delayed-cat';
this.async = true;
static get validatorName() {
return 'delayed-cat';
}
static get async() {
return true;
}
/**
@ -769,20 +778,26 @@ export function runValidateMixinSuite(customConfig) {
class ContainsLowercaseA extends Validator {
constructor(...args) {
super(...args);
this.name = 'ContainsLowercaseA';
this.execute = modelValue => !modelValue.includes('a');
}
static get validatorName() {
return 'ContainsLowercaseA';
}
}
class ContainsLowercaseB extends Validator {
constructor(...args) {
super(...args);
this.name = 'containsLowercaseB';
this.execute = modelValue => !modelValue.includes('b');
}
static get validatorName() {
return 'containsLowercaseB';
}
}
it('stores validity of individual Validators in ".validationStates.error[validator.name]"', async () => {
it('stores validity of individual Validators in ".validationStates.error[validator.validatorName]"', async () => {
const el = await fixture(html`
<${tag}
.modelValue=${'a'}

View file

@ -41,9 +41,8 @@ export function runValidateMixinFeedbackPart() {
tag = unsafeStatic(tagString);
ContainsLowercaseA = class extends Validator {
constructor(...args) {
super(...args);
this.name = 'ContainsLowercaseA';
static get validatorName() {
return 'ContainsLowercaseA';
}
execute(modelValue) {
@ -53,9 +52,8 @@ export function runValidateMixinFeedbackPart() {
};
class ContainsCat extends Validator {
constructor(...args) {
super(...args);
this.name = 'ContainsCat';
static get validatorName() {
return 'ContainsCat';
}
execute(modelValue) {
@ -244,7 +242,7 @@ export function runValidateMixinFeedbackPart() {
render() {
return html`
Custom for ${this.feedbackData[0].validator.name}
Custom for ${this.feedbackData[0].validator.constructor.name}
`;
}
},

View file

@ -13,7 +13,7 @@ describe('Date Validation', () => {
it('provides new isDate() to allow only dates', () => {
let isEnabled;
const validator = new IsDate();
expect(validator.name).to.equal('IsDate');
expect(validator.constructor.name).to.equal('IsDate');
isEnabled = validator.execute(new Date());
expect(isEnabled).to.be.false;
@ -28,7 +28,7 @@ describe('Date Validation', () => {
it('provides new minDate(x) to allow only dates after min', () => {
let isEnabled;
const validator = new MinDate(new Date('2018/02/02'));
expect(validator.name).to.equal('MinDate');
expect(validator.constructor.name).to.equal('MinDate');
isEnabled = validator.execute(new Date('2018-02-03'));
expect(isEnabled).to.be.false;
@ -46,7 +46,7 @@ describe('Date Validation', () => {
it('provides maxDate() to allow only dates before max', () => {
let isEnabled;
const validator = new MaxDate(new Date('2018/02/02'));
expect(validator.name).to.equal('MaxDate');
expect(validator.constructor.name).to.equal('MaxDate');
isEnabled = validator.execute(new Date('2018-02-01'));
expect(isEnabled).to.be.false;
@ -67,7 +67,7 @@ describe('Date Validation', () => {
min: new Date('2018/02/02'),
max: new Date('2018/02/04'),
});
expect(validator.name).to.equal('MinMaxDate');
expect(validator.constructor.name).to.equal('MinMaxDate');
isEnabled = validator.execute(new Date('2018/02/03'));
expect(isEnabled).to.be.false;
@ -88,7 +88,7 @@ describe('Date Validation', () => {
it('provides new IsDateDisabled() to disable dates matching specified condition', () => {
let isDisabled;
const validator = new IsDateDisabled(d => d.getDate() === 3);
expect(validator.name).to.equal('IsDateDisabled');
expect(validator.constructor.name).to.equal('IsDateDisabled');
isDisabled = validator.execute(new Date('2018/02/04'));
expect(isDisabled).to.be.false;

View file

@ -11,7 +11,7 @@ describe('Number Validation', () => {
it('provides new IsNumber() to allow only numbers', () => {
let isEnabled;
const validator = new IsNumber();
expect(validator.name).to.equal('IsNumber');
expect(validator.constructor.name).to.equal('IsNumber');
isEnabled = validator.execute(4);
expect(isEnabled).to.be.false;
@ -26,7 +26,7 @@ describe('Number Validation', () => {
it('provides new MinNumber(x) to allow only numbers longer then min', () => {
let isEnabled;
const validator = new MinNumber(3);
expect(validator.name).to.equal('MinNumber');
expect(validator.constructor.name).to.equal('MinNumber');
isEnabled = validator.execute(3);
expect(isEnabled).to.be.false;
@ -38,7 +38,7 @@ describe('Number Validation', () => {
it('provides new MaxNumber(x) to allow only number shorter then max', () => {
let isEnabled;
const validator = new MaxNumber(3);
expect(validator.name).to.equal('MaxNumber');
expect(validator.constructor.name).to.equal('MaxNumber');
isEnabled = validator.execute(3);
expect(isEnabled).to.be.false;
@ -50,7 +50,7 @@ describe('Number Validation', () => {
it('provides new MinMaxNumber({ min: x, max: y}) to allow only numbers between min and max', () => {
let isEnabled;
const validator = new MinMaxNumber({ min: 2, max: 4 });
expect(validator.name).to.equal('MinMaxNumber');
expect(validator.constructor.name).to.equal('MinMaxNumber');
isEnabled = validator.execute(2);
expect(isEnabled).to.be.false;

View file

@ -13,7 +13,7 @@ describe('String Validation', () => {
it('provides new IsString() to allow only strings', () => {
let isEnabled;
const validator = new IsString();
expect(validator.name).to.equal('IsString');
expect(validator.constructor.name).to.equal('IsString');
isEnabled = validator.execute('foo');
expect(isEnabled).to.be.false;
@ -28,7 +28,7 @@ describe('String Validation', () => {
it('provides new EqualsLength(x) to allow only a specific string length', () => {
let isEnabled;
const validator = new EqualsLength(3);
expect(validator.name).to.equal('EqualsLength');
expect(validator.constructor.name).to.equal('EqualsLength');
isEnabled = validator.execute('foo');
expect(isEnabled).to.be.false;
@ -43,7 +43,7 @@ describe('String Validation', () => {
it('provides new MinLength(x) to allow only strings longer then min', () => {
let isEnabled;
const validator = new MinLength(3);
expect(validator.name).to.equal('MinLength');
expect(validator.constructor.name).to.equal('MinLength');
isEnabled = validator.execute('foo');
expect(isEnabled).to.be.false;
@ -55,7 +55,7 @@ describe('String Validation', () => {
it('provides new MaxLength(x) to allow only strings shorter then max', () => {
let isEnabled;
const validator = new MaxLength(3);
expect(validator.name).to.equal('MaxLength');
expect(validator.constructor.name).to.equal('MaxLength');
isEnabled = validator.execute('foo');
expect(isEnabled).to.be.false;
@ -67,7 +67,7 @@ describe('String Validation', () => {
it('provides new MinMaxValidator({ min: x, max: y}) to allow only strings between min and max', () => {
let isEnabled;
const validator = new MinMaxLength({ min: 2, max: 4 });
expect(validator.name).to.equal('MinMaxLength');
expect(validator.constructor.name).to.equal('MinMaxLength');
isEnabled = validator.execute('foo');
expect(isEnabled).to.be.false;
@ -82,7 +82,7 @@ describe('String Validation', () => {
it('provides new IsEmail() to allow only valid email formats', () => {
let isEnabled;
const validator = new IsEmail();
expect(validator.name).to.equal('IsEmail');
expect(validator.constructor.name).to.equal('IsEmail');
isEnabled = validator.execute('foo@bar.com');
expect(isEnabled).to.be.false;

View file

@ -32,14 +32,15 @@ describe('Validator', () => {
class MyValidator extends Validator {}
expect(() => {
new MyValidator().execute();
}).to.throw('You must provide a name like "this.name = \'IsCat\'" for your Validator');
}).to.throw(
'A validator needs to have a name! Please set it via "static get validatorName() { return \'IsCat\'; }"',
);
});
it('throws when executing a Validator that has a getMessage config property with a value not of type function', async () => {
class MyValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'MyValidator';
static get validatorName() {
return 'MyValidator';
}
}
@ -62,9 +63,8 @@ describe('Validator', () => {
it('has access to name, type, params, config in getMessage provided by config', () => {
const configSpy = sinon.spy();
class MyValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'MyValidator';
static get validatorName() {
return 'MyValidator';
}
}
const vali = new MyValidator('myParam', { my: 'config', getMessage: configSpy });
@ -81,9 +81,8 @@ describe('Validator', () => {
it('has access to name, type, params, config in static get getMessage', () => {
let staticArgs;
class MyValidator extends Validator {
constructor(...args) {
super(...args);
this.name = 'MyValidator';
static get validatorName() {
return 'MyValidator';
}
static getMessage(...args) {