Skip to content

Commit c3277a2

Browse files
Eran MachielsEranNL
Eran Machiels
andauthored
Feature/min max rule (#2)
* Changed messages to use area name * Fixed area test messages * Added min rule * Changed min value argument name * Added max rule Co-authored-by: Eran Machiels <[email protected]>
1 parent ddeb5d5 commit c3277a2

File tree

10 files changed

+205
-13
lines changed

10 files changed

+205
-13
lines changed

__tests__/Area.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ describe('test Provider', () => {
7070
);
7171

7272
area.find('input').at(0).simulate('blur');
73-
expect(area.state().errors[0]).toBe('This field is required');
73+
expect(area.state().errors[0]).toBe('Test is required');
7474
});
7575

7676
it('should render error when area dirty', async () => {
@@ -86,7 +86,7 @@ describe('test Provider', () => {
8686
);
8787

8888
area.find('input').simulate('blur');
89-
expect(area.find('div').text()).toBe('This field is required');
89+
expect(area.find('div').text()).toBe('Test is required');
9090
})
9191

9292
it('should validate element with rule string', () => {

__tests__/rules/max.test.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React from 'react';
2+
import { mount } from 'enzyme';
3+
import { ValidatorArea } from '../../src';
4+
import { ValidatorAreaProps } from '../../src/ValidatorArea';
5+
import max from '../../src/rules/max';
6+
7+
describe('test max rule', () => {
8+
it('should falsely validate input', () => {
9+
const area = mount<ValidatorArea, ValidatorAreaProps>(
10+
<ValidatorArea rules={[max(5)]}>
11+
<input name="test" value="6" />
12+
</ValidatorArea>
13+
);
14+
15+
area.find('input').simulate('blur');
16+
expect(area.state().errors.length).toBe(1);
17+
expect(area.state().errors[0]).toBe('Test should be not greater than 5');
18+
});
19+
20+
it('should falsely validate textarea', () => {
21+
const area = mount<ValidatorArea, ValidatorAreaProps>(
22+
<ValidatorArea rules={[max(5)]}>
23+
<textarea name="test" value="6" />
24+
</ValidatorArea>
25+
);
26+
27+
area.find('textarea').simulate('blur');
28+
expect(area.state().errors.length).toBe(1);
29+
expect(area.state().errors[0]).toBe('Test should be not greater than 5');
30+
});
31+
32+
it('should falsely validate select', () => {
33+
const area = mount<ValidatorArea, ValidatorAreaProps>(
34+
<ValidatorArea rules={[max(5)]}>
35+
<select name="test">
36+
<option value="">Choose...</option>
37+
</select>
38+
</ValidatorArea>
39+
);
40+
41+
area.find('select').simulate('blur');
42+
expect(area.state().errors.length).toBe(1);
43+
expect(area.state().errors[0]).toBe('Test should be not greater than 5');
44+
});
45+
46+
it('should truly validate select', () => {
47+
const area = mount<ValidatorArea, ValidatorAreaProps>(
48+
<ValidatorArea rules={[max(5)]}>
49+
<select name="test">
50+
<option value={5}>Choose...</option>
51+
</select>
52+
</ValidatorArea>
53+
);
54+
55+
area.find('select').simulate('blur');
56+
expect(area.state().errors.length).toBe(0);
57+
});
58+
});

__tests__/rules/min.test.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React from 'react';
2+
import { mount } from 'enzyme';
3+
import { ValidatorArea } from '../../src';
4+
import { ValidatorAreaProps } from '../../src/ValidatorArea';
5+
import min from '../../src/rules/min';
6+
7+
describe('test min rule', () => {
8+
it('should falsely validate input', () => {
9+
const area = mount<ValidatorArea, ValidatorAreaProps>(
10+
<ValidatorArea rules={[min(5)]}>
11+
<input name="test" />
12+
</ValidatorArea>
13+
);
14+
15+
area.find('input').simulate('blur');
16+
expect(area.state().errors.length).toBe(1);
17+
expect(area.state().errors[0]).toBe('Test should be at least 5');
18+
});
19+
20+
it('should falsely validate textarea', () => {
21+
const area = mount<ValidatorArea, ValidatorAreaProps>(
22+
<ValidatorArea rules={[min(5)]}>
23+
<textarea name="test" />
24+
</ValidatorArea>
25+
);
26+
27+
area.find('textarea').simulate('blur');
28+
expect(area.state().errors.length).toBe(1);
29+
expect(area.state().errors[0]).toBe('Test should be at least 5');
30+
});
31+
32+
it('should falsely validate select', () => {
33+
const area = mount<ValidatorArea, ValidatorAreaProps>(
34+
<ValidatorArea rules={[min(5)]}>
35+
<select name="test">
36+
<option value="">Choose...</option>
37+
</select>
38+
</ValidatorArea>
39+
);
40+
41+
area.find('select').simulate('blur');
42+
expect(area.state().errors.length).toBe(1);
43+
expect(area.state().errors[0]).toBe('Test should be at least 5');
44+
});
45+
46+
it('should truly validate select', () => {
47+
const area = mount<ValidatorArea, ValidatorAreaProps>(
48+
<ValidatorArea rules={[min(5)]}>
49+
<select name="test">
50+
<option value={5}>Choose...</option>
51+
</select>
52+
</ValidatorArea>
53+
);
54+
55+
area.find('select').simulate('blur');
56+
expect(area.state().errors.length).toBe(0);
57+
});
58+
});

__tests__/rules/required.test.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { ValidatorAreaProps } from '../../src/ValidatorArea';
55
import required from '../../src/rules/required';
66

77
describe('test required rule', () => {
8-
it('should validate input', () => {
8+
it('should falsely validate input', () => {
99
const area = mount<ValidatorArea, ValidatorAreaProps>(
1010
<ValidatorArea rules={[required]}>
1111
<input name="test" />
@@ -14,10 +14,10 @@ describe('test required rule', () => {
1414

1515
area.find('input').simulate('blur');
1616
expect(area.state().errors.length).toBe(1);
17-
expect(area.state().errors[0]).toBe('This field is required');
17+
expect(area.state().errors[0]).toBe('Test is required');
1818
});
1919

20-
it('should validate textarea', () => {
20+
it('should falsely validate textarea', () => {
2121
const area = mount<ValidatorArea, ValidatorAreaProps>(
2222
<ValidatorArea rules={[required]}>
2323
<textarea name="test" />
@@ -26,10 +26,10 @@ describe('test required rule', () => {
2626

2727
area.find('textarea').simulate('blur');
2828
expect(area.state().errors.length).toBe(1);
29-
expect(area.state().errors[0]).toBe('This field is required');
29+
expect(area.state().errors[0]).toBe('Test is required');
3030
});
3131

32-
it('should validate select', () => {
32+
it('should falsely validate select', () => {
3333
const area = mount<ValidatorArea, ValidatorAreaProps>(
3434
<ValidatorArea rules={[required]}>
3535
<select name="test">
@@ -40,6 +40,19 @@ describe('test required rule', () => {
4040

4141
area.find('select').simulate('blur');
4242
expect(area.state().errors.length).toBe(1);
43-
expect(area.state().errors[0]).toBe('This field is required');
43+
expect(area.state().errors[0]).toBe('Test is required');
44+
});
45+
46+
it('should validate select', () => {
47+
const area = mount<ValidatorArea, ValidatorAreaProps>(
48+
<ValidatorArea rules={[required]}>
49+
<select name="test">
50+
<option value="foo">Choose...</option>
51+
</select>
52+
</ValidatorArea>
53+
);
54+
55+
area.find('select').simulate('blur');
56+
expect(area.state().errors.length).toBe(0);
4457
});
4558
});

src/Rule.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ValidationElement } from './ValidationElement';
22

33
export type Rule = {
4-
passed(element: ValidationElement[]): boolean;
5-
message(element: ValidationElement[]): string;
4+
passed(elements: ValidationElement[]): boolean;
5+
message(name: string): string;
66
}

src/ValidatorArea.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class ValidatorArea extends React.Component<ValidatorAreaProps, ValidatorAreaSta
5959
}
6060

6161
if (typeof rule !== 'string' && !rule.passed(refs)) {
62-
messages.push(rule.message(refs));
62+
messages.push(rule.message(this.getName()));
6363
this.dirty = true;
6464
}
6565
}

src/rules/max.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Rule } from '../Rule';
2+
import { ValidationElement } from '../ValidationElement';
3+
import { capitalize } from '../utils/utils';
4+
5+
export default (value: number): Rule => {
6+
return {
7+
passed(elements: ValidationElement[]): boolean {
8+
let passed = true;
9+
10+
elements.forEach((element) => {
11+
if (element instanceof HTMLInputElement
12+
|| element instanceof HTMLTextAreaElement
13+
) {
14+
passed = parseFloat(element.value.trim()) <= value;
15+
}
16+
17+
if (element instanceof HTMLSelectElement) {
18+
passed = parseFloat(element.options[element.selectedIndex].value) <= value;
19+
}
20+
});
21+
22+
return passed;
23+
},
24+
message(name: string): string {
25+
return `${capitalize(name)} should be not greater than ${value}`
26+
}
27+
}
28+
}

src/rules/min.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Rule } from '../Rule';
2+
import { ValidationElement } from '../ValidationElement';
3+
import { capitalize } from '../utils/utils';
4+
5+
export default (value: number): Rule => {
6+
return {
7+
passed(elements: ValidationElement[]): boolean {
8+
let passed = true;
9+
10+
elements.forEach((element) => {
11+
if (element instanceof HTMLInputElement
12+
|| element instanceof HTMLTextAreaElement
13+
) {
14+
passed = parseFloat(element.value.trim()) >= value;
15+
}
16+
17+
if (element instanceof HTMLSelectElement) {
18+
passed = parseFloat(element.options[element.selectedIndex].value) >= value;
19+
}
20+
});
21+
22+
return passed;
23+
},
24+
message(name: string): string {
25+
return `${capitalize(name)} should be at least ${value}`
26+
}
27+
}
28+
}

src/rules/required.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ValidationElement } from '../ValidationElement';
2+
import { capitalize } from '../utils/utils';
23

34
export default {
45
passed(elements: ValidationElement[]): boolean {
@@ -19,7 +20,7 @@ export default {
1920
return passed;
2021
},
2122

22-
message(): string {
23-
return 'This field is required';
23+
message(name: string): string {
24+
return `${capitalize(name)} is required`;
2425
}
2526
};

src/utils/utils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* Return the given string with an uppercase first letter
3+
*/
4+
export const capitalize = (value: string): string => {
5+
return value.substr(0, 1).toUpperCase() + value.substr(1, value.length - 1);
6+
}

0 commit comments

Comments
 (0)