Skip to content

Commit d20625c

Browse files
Eran MachielsEranNL
Eran Machiels
andauthored
WIP validation all elements (#8)
* WIP validation all elements * Fixes * Added missing docs Co-authored-by: Eran Machiels <[email protected]>
1 parent 9c2a989 commit d20625c

17 files changed

+334
-185
lines changed

__tests__/Area.test.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,17 @@ describe('test ValidatorProvider', () => {
9191
expect(area.state().errors[0]).toBe('Not passed');
9292
});
9393

94+
it('should not apply rules on blur when non-blurrable element', () => {
95+
const area = mount<ValidatorArea, ValidatorAreaProps>(
96+
<ValidatorArea rules="passes_not" name="test">
97+
<canvas />
98+
</ValidatorArea>
99+
);
100+
101+
area.find('canvas').at(0).simulate('blur');
102+
expect(area.state().errors.length).toBe(0);
103+
});
104+
94105
it('should render error when area dirty', async () => {
95106
const area = mount<ValidatorArea, ValidatorAreaProps>(
96107
<ValidatorArea rules="passes_not">
@@ -239,4 +250,39 @@ describe('test ValidatorProvider', () => {
239250
area.find('input').simulate('blur');
240251
expect(mockFn).toBeCalled();
241252
});
253+
254+
it('should get refs by type', async () => {
255+
Validator.extend('test_types', (validator: Validator) => ({
256+
passed(): boolean {
257+
return validator.refs(undefined, HTMLInputElement).length === 1
258+
&& validator.refs('test1', HTMLTextAreaElement).length === 1
259+
&& validator.refs('test1').length === 1
260+
&& validator.refs('test1', HTMLProgressElement).length === 0;
261+
},
262+
message(): string {
263+
return 'test';
264+
}
265+
}))
266+
const mockFn = jest.fn();
267+
268+
const provider = mount<ValidatorProvider, ValidatorProviderProps>(
269+
<ValidatorProvider rules="test_types">
270+
{({ validate }: ProviderScope) => (
271+
<>
272+
<ValidatorArea name="test1">
273+
<textarea value="" />
274+
</ValidatorArea>
275+
<ValidatorArea>
276+
<input value="" name="test2" />
277+
</ValidatorArea>
278+
<button onClick={() => validate(mockFn)} />
279+
</>
280+
)}
281+
</ValidatorProvider>
282+
);
283+
284+
provider.find('button').simulate('click');
285+
await tick();
286+
expect(mockFn).toHaveBeenCalled();
287+
});
242288
})

__tests__/rules/max.test.tsx

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,54 +9,53 @@ describe('test max rule', () => {
99
Validator.extend('max', max);
1010
});
1111

12-
it('should falsely validate input', () => {
13-
const area = mount<ValidatorArea, ValidatorAreaProps>(
14-
<ValidatorArea rules="max:5">
15-
<input name="test" value="6" />
16-
</ValidatorArea>
17-
);
18-
19-
area.find('input').simulate('blur');
20-
expect(area.state().errors.length).toBe(1);
21-
expect(area.state().errors[0]).toBe('Test should be not greater than 5');
12+
it('should always validate inputs and not validate non-inputs', () => {
13+
const input = document.createElement('input');
14+
input.value = '5';
15+
16+
const throwsArgumentError = () => {
17+
const validator = new Validator([
18+
input
19+
], ['max:foo'],
20+
'validate_throws'
21+
);
22+
validator.validate();
23+
}
24+
25+
const validator_input = new Validator([
26+
input
27+
],
28+
['max:4'],
29+
'validator_input');
30+
31+
const progress = document.createElement('progress');
32+
progress.value = 5;
33+
34+
const validator_progress = new Validator([
35+
progress
36+
],
37+
['max:4'],
38+
'validate_progress');
39+
40+
expect(() => throwsArgumentError()).toThrowError('max rule has incorrect argument foo. Expected a number.')
41+
42+
validator_input.validate();
43+
expect(validator_input.getErrors().length).toBe(1);
44+
45+
validator_progress.validate();
46+
expect(validator_progress.getErrors().length).toBe(0);
2247
});
2348

24-
it('should falsely validate textarea', () => {
49+
it('should validate select', () => {
2550
const area = mount<ValidatorArea, ValidatorAreaProps>(
26-
<ValidatorArea rules="max:5">
27-
<textarea name="test" value="6" />
28-
</ValidatorArea>
29-
);
30-
31-
area.find('textarea').simulate('blur');
32-
expect(area.state().errors.length).toBe(1);
33-
expect(area.state().errors[0]).toBe('Test should be not greater than 5');
34-
});
35-
36-
it('should falsely validate select', () => {
37-
const area = mount<ValidatorArea, ValidatorAreaProps>(
38-
<ValidatorArea rules="max:5">
51+
<ValidatorArea rules="max:3">
3952
<select name="test">
40-
<option value="">Choose...</option>
53+
<option value="4" selected>Option</option>
4154
</select>
4255
</ValidatorArea>
4356
);
4457

4558
area.find('select').simulate('blur');
4659
expect(area.state().errors.length).toBe(1);
47-
expect(area.state().errors[0]).toBe('Test should be not greater than 5');
48-
});
49-
50-
it('should truly validate select', () => {
51-
const area = mount<ValidatorArea, ValidatorAreaProps>(
52-
<ValidatorArea rules="max:5">
53-
<select name="test">
54-
<option value={5}>Choose...</option>
55-
</select>
56-
</ValidatorArea>
57-
);
58-
59-
area.find('select').simulate('blur');
60-
expect(area.state().errors.length).toBe(0);
6160
});
6261
});

__tests__/rules/min.test.tsx

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,61 @@
1-
import React from 'react';
2-
import { mount } from 'enzyme';
3-
import { ValidatorArea, ValidatorAreaProps } from '@/components/ValidatorArea';
41
import min from '@/rules/min';
52
import { Validator } from '@/Validator';
3+
import { mount } from 'enzyme';
4+
import { ValidatorArea, ValidatorAreaProps } from '@/components/ValidatorArea';
5+
import React from 'react';
66

77
describe('test min rule', () => {
8-
Validator.extend('min', min);
9-
it('should falsely validate input', () => {
10-
const area = mount<ValidatorArea, ValidatorAreaProps>(
11-
<ValidatorArea rules="min:5">
12-
<input name="test" />
13-
</ValidatorArea>
14-
);
15-
16-
area.find('input').simulate('blur');
17-
expect(area.state().errors.length).toBe(1);
18-
expect(area.state().errors[0]).toBe('Test should be at least 5');
8+
beforeEach(() => {
9+
Validator.extend('min', min);
1910
});
2011

21-
it('should falsely validate textarea', () => {
22-
const area = mount<ValidatorArea, ValidatorAreaProps>(
23-
<ValidatorArea rules="min:5">
24-
<textarea name="test" />
25-
</ValidatorArea>
26-
);
27-
28-
area.find('textarea').simulate('blur');
29-
expect(area.state().errors.length).toBe(1);
30-
expect(area.state().errors[0]).toBe('Test should be at least 5');
12+
it('should always validate inputs and not validate non-inputs', () => {
13+
const input = document.createElement('input');
14+
input.value = '5';
15+
16+
const throwsArgumentError = () => {
17+
const validator = new Validator([
18+
input
19+
], ['min:foo'],
20+
'validate_throws'
21+
);
22+
validator.validate();
23+
}
24+
25+
const validator_input = new Validator([
26+
input
27+
],
28+
['min:6'],
29+
'validator_input');
30+
31+
const progress = document.createElement('progress');
32+
progress.value = 5;
33+
34+
const validator_progress = new Validator([
35+
progress
36+
],
37+
['min:4'],
38+
'validate_progress');
39+
40+
expect(() => throwsArgumentError()).toThrowError('min rule has incorrect argument foo. Expected a number.')
41+
42+
validator_input.validate();
43+
expect(validator_input.getErrors().length).toBe(1);
44+
45+
validator_progress.validate();
46+
expect(validator_progress.getErrors().length).toBe(0);
3147
});
3248

33-
it('should falsely validate select', () => {
49+
it('should validate select', () => {
3450
const area = mount<ValidatorArea, ValidatorAreaProps>(
3551
<ValidatorArea rules="min:5">
3652
<select name="test">
37-
<option value="">Choose...</option>
53+
<option value="4" selected>Option</option>
3854
</select>
3955
</ValidatorArea>
4056
);
4157

4258
area.find('select').simulate('blur');
4359
expect(area.state().errors.length).toBe(1);
44-
expect(area.state().errors[0]).toBe('Test should be at least 5');
45-
});
46-
47-
it('should truly validate select', () => {
48-
const area = mount<ValidatorArea, ValidatorAreaProps>(
49-
<ValidatorArea rules="min:5">
50-
<select name="test">
51-
<option value={5}>Choose...</option>
52-
</select>
53-
</ValidatorArea>
54-
);
55-
56-
area.find('select').simulate('blur');
57-
expect(area.state().errors.length).toBe(0);
5860
});
5961
});

__tests__/rules/required.test.tsx

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,7 @@ describe('test required rule', () => {
99
Validator.extend('required', required);
1010
});
1111

12-
it('should falsely validate input', () => {
13-
const area = mount<ValidatorArea, ValidatorAreaProps>(
14-
<ValidatorArea rules="required">
15-
<input name="test" />
16-
</ValidatorArea>
17-
);
18-
19-
area.find('input').simulate('blur');
20-
expect(area.state().errors.length).toBe(1);
21-
expect(area.state().errors[0]).toBe('Test is required');
22-
});
23-
24-
it('should falsely validate textarea', () => {
25-
const area = mount<ValidatorArea, ValidatorAreaProps>(
26-
<ValidatorArea rules="required">
27-
<textarea name="test" />
28-
</ValidatorArea>
29-
);
30-
31-
area.find('textarea').simulate('blur');
32-
expect(area.state().errors.length).toBe(1);
33-
expect(area.state().errors[0]).toBe('Test is required');
34-
});
35-
36-
it('should falsely validate select', () => {
12+
it('should falsely validate select with options', () => {
3713
const area = mount<ValidatorArea, ValidatorAreaProps>(
3814
<ValidatorArea rules="required">
3915
<select name="test">
@@ -47,16 +23,23 @@ describe('test required rule', () => {
4723
expect(area.state().errors[0]).toBe('Test is required');
4824
});
4925

50-
it('should validate select', () => {
51-
const area = mount<ValidatorArea, ValidatorAreaProps>(
52-
<ValidatorArea rules="required">
53-
<select name="test">
54-
<option value="foo">Choose...</option>
55-
</select>
56-
</ValidatorArea>
57-
);
26+
it('should always validate inputs and not validate non-inputs', () => {
27+
const validator_input = new Validator([
28+
document.createElement('input')
29+
],
30+
['required'],
31+
'validator_input');
5832

59-
area.find('select').simulate('blur');
60-
expect(area.state().errors.length).toBe(0);
33+
const validator_progress = new Validator([
34+
document.createElement('progress')
35+
],
36+
['required'],
37+
'validate_progress');
38+
39+
validator_input.validate();
40+
expect(validator_input.getErrors().length).toBe(1);
41+
42+
validator_progress.validate();
43+
expect(validator_progress.getErrors().length).toBe(0);
6144
});
6245
});

__tests__/utils/dom.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { getValue, htmlCollectionToArray } from '@/utils/dom';
2+
3+
describe('dom helpers test', () => {
4+
it('should convert HtmlCollection to array', () => {
5+
const select = document.createElement('select');
6+
const option1 = document.createElement('option');
7+
const option2 = document.createElement('option');
8+
select.appendChild(option1);
9+
select.appendChild(option2);
10+
11+
const optionArray = htmlCollectionToArray(select.children);
12+
expect(Array.isArray(optionArray)).toBeTruthy();
13+
})
14+
15+
it('should get value of elements or null', () => {
16+
const select = document.createElement('select');
17+
select.multiple = true;
18+
const option1 = document.createElement('option');
19+
option1.value = 'foo';
20+
option1.selected = true;
21+
const option2 = document.createElement('option');
22+
option2.value = 'bar';
23+
option2.selected = true;
24+
select.appendChild(option1);
25+
select.appendChild(option2);
26+
27+
const input = document.createElement('input');
28+
input.value = 'baz';
29+
30+
const div = document.createElement('div');
31+
32+
expect(getValue(select)).toEqual(expect.arrayContaining(['foo', 'bar']));
33+
expect(getValue(input)).toBe('baz');
34+
expect(getValue(div)).toBeNull();
35+
36+
})
37+
});

src/Rule.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Validator } from '@/Validator';
2-
import { ValidationElement } from '@/ValidationElement';
32

43
/**
54
* Function to access validator using the rule
@@ -13,7 +12,7 @@ export type RuleObject = {
1312
/**
1413
* Returns whether the rule passed with the given element(s)
1514
*/
16-
passed(elements: ValidationElement[], ...args: string[]): boolean;
15+
passed(elements: HTMLElement[], ...args: string[]): boolean;
1716
/**
1817
* Message shown when the rule doesn't pass
1918
*/

src/ValidationElement.ts

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

0 commit comments

Comments
 (0)