Skip to content

Feature/rewrite rules #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 19 additions & 34 deletions __tests__/Area.test.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import React from 'react';
import { mount } from 'enzyme';
import { ValidatorArea, Validator } from '../src';
import { ValidatorAreaProps } from '../src/ValidatorArea';
import required from '../src/rules/required';
import { Validator } from '@/Validator';
import { ValidatorArea, ValidatorAreaProps } from '@/components/ValidatorArea';

describe('test ValidatorProvider', () => {
beforeEach(() => {
Validator.extend('passes_not', {
passed(): boolean {
return false;
},
message(): string {
return 'not passed';
}
});
});

describe('test Provider', () => {
it('should render input', () => {
const area = mount<ValidatorArea, ValidatorAreaProps>(
<ValidatorArea>
Expand Down Expand Up @@ -64,43 +74,18 @@ describe('test Provider', () => {

it('should apply rules on blur', () => {
const area = mount<ValidatorArea, ValidatorAreaProps>(
<ValidatorArea rules={[required]}>
<ValidatorArea rules="passes_not">
<input name="test" />
</ValidatorArea>
);

area.find('input').at(0).simulate('blur');
expect(area.state().errors[0]).toBe('Test is required');
expect(area.state().errors[0]).toBe('Not passed');
});

it('should render error when area dirty', async () => {
const area = mount<ValidatorArea, ValidatorAreaProps>(
<ValidatorArea rules={[required]}>
{({ errors }) => (
<>
<input name="test" />
{errors.length && <div>{errors[0]}</div>}
</>
)}
</ValidatorArea>
);

area.find('input').simulate('blur');
expect(area.find('div').text()).toBe('Test is required');
})

it('should validate element with rule string', () => {
Validator.extend('testrule', {
passed(): boolean {
return false;
},
message(): string {
return 'string rule passed';
}
});

const area = mount<ValidatorArea, ValidatorAreaProps>(
<ValidatorArea rules={['testrule']}>
<ValidatorArea rules="passes_not">
{({ errors }) => (
<>
<input name="test" />
Expand All @@ -111,14 +96,14 @@ describe('test Provider', () => {
);

area.find('input').simulate('blur');
expect(area.find('div').text()).toBe('string rule passed');
expect(area.find('div').text()).toBe('Not passed');
})

it('should call element\'s provided blur along validator blur', () => {
const mockFn = jest.fn();

const area = mount<ValidatorArea, ValidatorAreaProps>(
<ValidatorArea rules={[required]}>
<ValidatorArea rules="passes_not">
<input name="test" onBlur={mockFn} />
</ValidatorArea>
);
Expand Down
74 changes: 47 additions & 27 deletions __tests__/Provider.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import { mount } from 'enzyme';
import { ValidatorArea, ValidatorProvider } from '../src';
import required from '../src/rules/required';
import { ValidatorProviderProps } from '../src/Provider';
import { Validator } from '@/Validator';
import ValidatorProvider, { ValidatorProviderProps } from '@/components/ValidatorProvider';
import { ValidatorArea } from '@/components/ValidatorArea';


const tick = () => {
Expand All @@ -11,31 +11,51 @@ const tick = () => {
})
}

describe('test Provider', () => {
it('should render Provider', () => {
describe('test ValidatorProvider', () => {
beforeEach(() => {
Validator.extend('passes_not', {
passed(): boolean {
return false;
},
message(): string {
return 'not passed';
}
});

Validator.extend('passes', {
passed(): boolean {
return true;
},
message(): string {
return 'passed';
}
});
});

it('should render ValidatorProvider', () => {
const provider = mount<ValidatorProvider, ValidatorProviderProps>(
<ValidatorProvider rules={[required]} />
<ValidatorProvider rules="passes_not" />
);

expect(provider.instance().props.rules).toBeDefined();
});

it('should throw error when area with existing name is addeded', () => {
const provider = () => {
mount<ValidatorProvider, ValidatorProviderProps>(
<ValidatorProvider>
<ValidatorArea name="test">
<div />
</ValidatorArea>
<ValidatorArea name="test">
<div />
</ValidatorArea>
</ValidatorProvider>
);
}

expect(() => provider()).toThrow('Validation area names should be unique');
})
it('should throw error when area with existing name is added', () => {
const provider = () => {
mount<ValidatorProvider, ValidatorProviderProps>(
<ValidatorProvider>
<ValidatorArea name="test">
<div />
</ValidatorArea>
<ValidatorArea name="test">
<div />
</ValidatorArea>
</ValidatorProvider>
);
}

expect(() => provider()).toThrow('Validation area names should be unique');
});

it('should render with function as child', () => {
const provider = mount<ValidatorProvider, ValidatorProviderProps>(
Expand All @@ -45,7 +65,7 @@ describe('test Provider', () => {
);

expect(provider.find('div').text()).toBe('test');
})
});

it('should add an area when provided as child', () => {
const provider = mount<ValidatorProvider, ValidatorProviderProps>(
Expand All @@ -69,10 +89,10 @@ describe('test Provider', () => {
<ValidatorProvider>
{({ validate }) => (
<>
<ValidatorArea rules={[required]} name="test1">
<ValidatorArea rules="passes_not" name="test1">
<input value="" />
</ValidatorArea>
<ValidatorArea rules={[required]} name="test2">
<ValidatorArea rules="passes_not" name="test2">
<input value="" />
</ValidatorArea>
<button onClick={() => validate(mockFn)} />
Expand All @@ -93,7 +113,7 @@ describe('test Provider', () => {
<ValidatorProvider>
{({ validate }) => (
<>
<ValidatorArea rules={[required]} name="test1">
<ValidatorArea rules="passes" name="test1">
<input value="foo" />
</ValidatorArea>
<button onClick={() => validate(mockFn)} />
Expand Down Expand Up @@ -127,5 +147,5 @@ describe('test Provider', () => {
provider.find('button').simulate('click');
await tick();
expect(mockFn).toHaveBeenCalled()
})
});
})
19 changes: 0 additions & 19 deletions __tests__/Validator.test.ts

This file was deleted.

107 changes: 107 additions & 0 deletions __tests__/Validator.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { Rule } from '../src/Rule';
import { Validator } from '../src';

describe('test validator', () => {
beforeEach(() => {
Validator.extend('rule_one', {
passed(): boolean {
return false;
},
message(): string {
return 'rule one not passed'
}
});

Validator.extend('rule_two', {
passed(): boolean {
return false;
},
message(): string {
return 'rule two not passed'
}
});

Validator.extend('rule_with_params', {
passed(): boolean {
return false;
},
message(): string {
return 'rule params not passed: {0}, {1}, {2}, {3}'
}
});
});

it('should add custom rules', () => {
const rule: Rule = {
passed(): boolean {
return true;
},
message(): string {
return '';
}
}

Validator.extend('testRule', rule);

expect(Validator.hasRule('testRule')).toBeTruthy();
});

it('should validate rules as string', () => {
const validator = new Validator(
[
document.createElement<'input'>('input')
],
'rule_one|rule_two',
'test'
);

validator.validate();
expect(validator.getErrors().length).toBe(2);
});

it('should validate rules as array', () => {
const validator = new Validator(
[
document.createElement<'input'>('input')
],
['rule_one', 'rule_two'],
'test'
);

validator.validate();
expect(validator.getErrors().length).toBe(2);
});

it('should validate with parameters', () => {
const validator = new Validator(
[
document.createElement<'input'>('input')
],
['rule_with_params:1,2,3,4'],
'test'
);

validator.validate();
expect(validator.getErrors()[0]).toBe('Rule params not passed: 1, 2, 3, 4');
});

it('throws an exception when rule is not found', () => {
const throws = () => {
const validator = new Validator(
[
document.createElement<'input'>('input')
],
['not_existing_rule'],
'test'
);
validator.validate();
}

expect(() => throws()).toThrowError('Validation rule not_existing_rule not found.');
});

it('should merge rules', () => {
const rules = Validator.mergeRules(['rule_one', 'rule_two'], 'rule_tree|rule_four', ['rule_five|rule_six']);
expect(rules.length).toBe(6);
})
});
18 changes: 11 additions & 7 deletions __tests__/rules/max.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import React from 'react';
import { mount } from 'enzyme';
import { ValidatorArea } from '../../src';
import { ValidatorAreaProps } from '../../src/ValidatorArea';
import max from '../../src/rules/max';
import max from '@/rules/max';
import { Validator } from '@/Validator';
import { ValidatorArea, ValidatorAreaProps } from '@/components/ValidatorArea';

describe('test max rule', () => {
beforeEach(() => {
Validator.extend('max', max);
});

it('should falsely validate input', () => {
const area = mount<ValidatorArea, ValidatorAreaProps>(
<ValidatorArea rules={[max(5)]}>
<ValidatorArea rules="max:5">
<input name="test" value="6" />
</ValidatorArea>
);
Expand All @@ -19,7 +23,7 @@ describe('test max rule', () => {

it('should falsely validate textarea', () => {
const area = mount<ValidatorArea, ValidatorAreaProps>(
<ValidatorArea rules={[max(5)]}>
<ValidatorArea rules="max:5">
<textarea name="test" value="6" />
</ValidatorArea>
);
Expand All @@ -31,7 +35,7 @@ describe('test max rule', () => {

it('should falsely validate select', () => {
const area = mount<ValidatorArea, ValidatorAreaProps>(
<ValidatorArea rules={[max(5)]}>
<ValidatorArea rules="max:5">
<select name="test">
<option value="">Choose...</option>
</select>
Expand All @@ -45,7 +49,7 @@ describe('test max rule', () => {

it('should truly validate select', () => {
const area = mount<ValidatorArea, ValidatorAreaProps>(
<ValidatorArea rules={[max(5)]}>
<ValidatorArea rules="max:5">
<select name="test">
<option value={5}>Choose...</option>
</select>
Expand Down
Loading