Skip to content

Commit 4d70859

Browse files
Eran MachielsEranNL
Eran Machiels
andauthored
Feature/rewrite rules (#3)
* Added basic localization and fixed tests * Fixed eslint for tests * Added docs, cleanup * Fixed typo * Fixed typo * Added root imports, reorganized file structure Co-authored-by: Eran Machiels <[email protected]>
1 parent c3277a2 commit 4d70859

25 files changed

+548
-202
lines changed

__tests__/Area.test.tsx

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
import React from 'react';
22
import { mount } from 'enzyme';
3-
import { ValidatorArea, Validator } from '../src';
4-
import { ValidatorAreaProps } from '../src/ValidatorArea';
5-
import required from '../src/rules/required';
3+
import { Validator } from '@/Validator';
4+
import { ValidatorArea, ValidatorAreaProps } from '@/components/ValidatorArea';
5+
6+
describe('test ValidatorProvider', () => {
7+
beforeEach(() => {
8+
Validator.extend('passes_not', {
9+
passed(): boolean {
10+
return false;
11+
},
12+
message(): string {
13+
return 'not passed';
14+
}
15+
});
16+
});
617

7-
describe('test Provider', () => {
818
it('should render input', () => {
919
const area = mount<ValidatorArea, ValidatorAreaProps>(
1020
<ValidatorArea>
@@ -64,43 +74,18 @@ describe('test Provider', () => {
6474

6575
it('should apply rules on blur', () => {
6676
const area = mount<ValidatorArea, ValidatorAreaProps>(
67-
<ValidatorArea rules={[required]}>
77+
<ValidatorArea rules="passes_not">
6878
<input name="test" />
6979
</ValidatorArea>
7080
);
7181

7282
area.find('input').at(0).simulate('blur');
73-
expect(area.state().errors[0]).toBe('Test is required');
83+
expect(area.state().errors[0]).toBe('Not passed');
7484
});
7585

7686
it('should render error when area dirty', async () => {
7787
const area = mount<ValidatorArea, ValidatorAreaProps>(
78-
<ValidatorArea rules={[required]}>
79-
{({ errors }) => (
80-
<>
81-
<input name="test" />
82-
{errors.length && <div>{errors[0]}</div>}
83-
</>
84-
)}
85-
</ValidatorArea>
86-
);
87-
88-
area.find('input').simulate('blur');
89-
expect(area.find('div').text()).toBe('Test is required');
90-
})
91-
92-
it('should validate element with rule string', () => {
93-
Validator.extend('testrule', {
94-
passed(): boolean {
95-
return false;
96-
},
97-
message(): string {
98-
return 'string rule passed';
99-
}
100-
});
101-
102-
const area = mount<ValidatorArea, ValidatorAreaProps>(
103-
<ValidatorArea rules={['testrule']}>
88+
<ValidatorArea rules="passes_not">
10489
{({ errors }) => (
10590
<>
10691
<input name="test" />
@@ -111,14 +96,14 @@ describe('test Provider', () => {
11196
);
11297

11398
area.find('input').simulate('blur');
114-
expect(area.find('div').text()).toBe('string rule passed');
99+
expect(area.find('div').text()).toBe('Not passed');
115100
})
116101

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

120105
const area = mount<ValidatorArea, ValidatorAreaProps>(
121-
<ValidatorArea rules={[required]}>
106+
<ValidatorArea rules="passes_not">
122107
<input name="test" onBlur={mockFn} />
123108
</ValidatorArea>
124109
);

__tests__/Provider.test.tsx

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from 'react';
22
import { mount } from 'enzyme';
3-
import { ValidatorArea, ValidatorProvider } from '../src';
4-
import required from '../src/rules/required';
5-
import { ValidatorProviderProps } from '../src/Provider';
3+
import { Validator } from '@/Validator';
4+
import ValidatorProvider, { ValidatorProviderProps } from '@/components/ValidatorProvider';
5+
import { ValidatorArea } from '@/components/ValidatorArea';
66

77

88
const tick = () => {
@@ -11,31 +11,51 @@ const tick = () => {
1111
})
1212
}
1313

14-
describe('test Provider', () => {
15-
it('should render Provider', () => {
14+
describe('test ValidatorProvider', () => {
15+
beforeEach(() => {
16+
Validator.extend('passes_not', {
17+
passed(): boolean {
18+
return false;
19+
},
20+
message(): string {
21+
return 'not passed';
22+
}
23+
});
24+
25+
Validator.extend('passes', {
26+
passed(): boolean {
27+
return true;
28+
},
29+
message(): string {
30+
return 'passed';
31+
}
32+
});
33+
});
34+
35+
it('should render ValidatorProvider', () => {
1636
const provider = mount<ValidatorProvider, ValidatorProviderProps>(
17-
<ValidatorProvider rules={[required]} />
37+
<ValidatorProvider rules="passes_not" />
1838
);
1939

2040
expect(provider.instance().props.rules).toBeDefined();
2141
});
2242

23-
it('should throw error when area with existing name is addeded', () => {
24-
const provider = () => {
25-
mount<ValidatorProvider, ValidatorProviderProps>(
26-
<ValidatorProvider>
27-
<ValidatorArea name="test">
28-
<div />
29-
</ValidatorArea>
30-
<ValidatorArea name="test">
31-
<div />
32-
</ValidatorArea>
33-
</ValidatorProvider>
34-
);
35-
}
36-
37-
expect(() => provider()).toThrow('Validation area names should be unique');
38-
})
43+
it('should throw error when area with existing name is added', () => {
44+
const provider = () => {
45+
mount<ValidatorProvider, ValidatorProviderProps>(
46+
<ValidatorProvider>
47+
<ValidatorArea name="test">
48+
<div />
49+
</ValidatorArea>
50+
<ValidatorArea name="test">
51+
<div />
52+
</ValidatorArea>
53+
</ValidatorProvider>
54+
);
55+
}
56+
57+
expect(() => provider()).toThrow('Validation area names should be unique');
58+
});
3959

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

4767
expect(provider.find('div').text()).toBe('test');
48-
})
68+
});
4969

5070
it('should add an area when provided as child', () => {
5171
const provider = mount<ValidatorProvider, ValidatorProviderProps>(
@@ -69,10 +89,10 @@ describe('test Provider', () => {
6989
<ValidatorProvider>
7090
{({ validate }) => (
7191
<>
72-
<ValidatorArea rules={[required]} name="test1">
92+
<ValidatorArea rules="passes_not" name="test1">
7393
<input value="" />
7494
</ValidatorArea>
75-
<ValidatorArea rules={[required]} name="test2">
95+
<ValidatorArea rules="passes_not" name="test2">
7696
<input value="" />
7797
</ValidatorArea>
7898
<button onClick={() => validate(mockFn)} />
@@ -93,7 +113,7 @@ describe('test Provider', () => {
93113
<ValidatorProvider>
94114
{({ validate }) => (
95115
<>
96-
<ValidatorArea rules={[required]} name="test1">
116+
<ValidatorArea rules="passes" name="test1">
97117
<input value="foo" />
98118
</ValidatorArea>
99119
<button onClick={() => validate(mockFn)} />
@@ -127,5 +147,5 @@ describe('test Provider', () => {
127147
provider.find('button').simulate('click');
128148
await tick();
129149
expect(mockFn).toHaveBeenCalled()
130-
})
150+
});
131151
})

__tests__/Validator.test.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

__tests__/Validator.test.tsx

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { Rule } from '../src/Rule';
2+
import { Validator } from '../src';
3+
4+
describe('test validator', () => {
5+
beforeEach(() => {
6+
Validator.extend('rule_one', {
7+
passed(): boolean {
8+
return false;
9+
},
10+
message(): string {
11+
return 'rule one not passed'
12+
}
13+
});
14+
15+
Validator.extend('rule_two', {
16+
passed(): boolean {
17+
return false;
18+
},
19+
message(): string {
20+
return 'rule two not passed'
21+
}
22+
});
23+
24+
Validator.extend('rule_with_params', {
25+
passed(): boolean {
26+
return false;
27+
},
28+
message(): string {
29+
return 'rule params not passed: {0}, {1}, {2}, {3}'
30+
}
31+
});
32+
});
33+
34+
it('should add custom rules', () => {
35+
const rule: Rule = {
36+
passed(): boolean {
37+
return true;
38+
},
39+
message(): string {
40+
return '';
41+
}
42+
}
43+
44+
Validator.extend('testRule', rule);
45+
46+
expect(Validator.hasRule('testRule')).toBeTruthy();
47+
});
48+
49+
it('should validate rules as string', () => {
50+
const validator = new Validator(
51+
[
52+
document.createElement<'input'>('input')
53+
],
54+
'rule_one|rule_two',
55+
'test'
56+
);
57+
58+
validator.validate();
59+
expect(validator.getErrors().length).toBe(2);
60+
});
61+
62+
it('should validate rules as array', () => {
63+
const validator = new Validator(
64+
[
65+
document.createElement<'input'>('input')
66+
],
67+
['rule_one', 'rule_two'],
68+
'test'
69+
);
70+
71+
validator.validate();
72+
expect(validator.getErrors().length).toBe(2);
73+
});
74+
75+
it('should validate with parameters', () => {
76+
const validator = new Validator(
77+
[
78+
document.createElement<'input'>('input')
79+
],
80+
['rule_with_params:1,2,3,4'],
81+
'test'
82+
);
83+
84+
validator.validate();
85+
expect(validator.getErrors()[0]).toBe('Rule params not passed: 1, 2, 3, 4');
86+
});
87+
88+
it('throws an exception when rule is not found', () => {
89+
const throws = () => {
90+
const validator = new Validator(
91+
[
92+
document.createElement<'input'>('input')
93+
],
94+
['not_existing_rule'],
95+
'test'
96+
);
97+
validator.validate();
98+
}
99+
100+
expect(() => throws()).toThrowError('Validation rule not_existing_rule not found.');
101+
});
102+
103+
it('should merge rules', () => {
104+
const rules = Validator.mergeRules(['rule_one', 'rule_two'], 'rule_tree|rule_four', ['rule_five|rule_six']);
105+
expect(rules.length).toBe(6);
106+
})
107+
});

__tests__/rules/max.test.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import React from 'react';
22
import { mount } from 'enzyme';
3-
import { ValidatorArea } from '../../src';
4-
import { ValidatorAreaProps } from '../../src/ValidatorArea';
5-
import max from '../../src/rules/max';
3+
import max from '@/rules/max';
4+
import { Validator } from '@/Validator';
5+
import { ValidatorArea, ValidatorAreaProps } from '@/components/ValidatorArea';
66

77
describe('test max rule', () => {
8+
beforeEach(() => {
9+
Validator.extend('max', max);
10+
});
11+
812
it('should falsely validate input', () => {
913
const area = mount<ValidatorArea, ValidatorAreaProps>(
10-
<ValidatorArea rules={[max(5)]}>
14+
<ValidatorArea rules="max:5">
1115
<input name="test" value="6" />
1216
</ValidatorArea>
1317
);
@@ -19,7 +23,7 @@ describe('test max rule', () => {
1923

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

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

4650
it('should truly validate select', () => {
4751
const area = mount<ValidatorArea, ValidatorAreaProps>(
48-
<ValidatorArea rules={[max(5)]}>
52+
<ValidatorArea rules="max:5">
4953
<select name="test">
5054
<option value={5}>Choose...</option>
5155
</select>

0 commit comments

Comments
 (0)