Skip to content

Commit 882ffba

Browse files
committed
WIP
1 parent cf20da8 commit 882ffba

File tree

10 files changed

+147
-14
lines changed

10 files changed

+147
-14
lines changed

__tests__/suits/Area.test.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,4 +452,30 @@ describe('test ValidatorProvider', () => {
452452
area.setProps({ errors: ['test error'] });
453453
expect(area.state().errors.length).toBe(1);
454454
});
455+
456+
it('should get other area', async () => {
457+
Validator.extend('test_other_area', (validator: Validator) => ({
458+
passed(): boolean {
459+
return !!validator.area('other');
460+
},
461+
message(): string {
462+
return 'test';
463+
}
464+
}))
465+
466+
const provider = mount<ValidatorProvider, ValidatorProviderProps>(
467+
<ValidatorProvider rules="test_other_area">
468+
<ValidatorArea>
469+
<input name="test" />
470+
</ValidatorArea>
471+
<ValidatorArea>
472+
<input name="other" />
473+
</ValidatorArea>
474+
</ValidatorProvider>
475+
);
476+
477+
await provider.instance().validate();
478+
await tick();
479+
expect(provider.state().valid).toBeTruthy();
480+
})
455481
})

__tests__/suits/rules/same.test.tsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Validator, ValidatorProviderProps, ValidatorProviderState } from '../../../src';
2+
import React from 'react';
3+
import same from '../../../src/rules/same';
4+
import { mount } from 'enzyme';
5+
import { ValidatorArea, ValidatorProvider } from '../../../src';
6+
import tick from '../../common/tick';
7+
8+
describe('test same rule', () => {
9+
beforeEach(() => {
10+
Validator.extend('same', same);
11+
});
12+
13+
it('should validate true', async () => {
14+
const area = mount<ValidatorProvider, ValidatorProviderProps, ValidatorProviderState>(
15+
<ValidatorProvider>
16+
<ValidatorArea rules="same:bar">
17+
<input value="foo" name="foo" />
18+
</ValidatorArea>
19+
20+
<ValidatorArea validationName="test">
21+
<input value="foo" name="bar" />
22+
</ValidatorArea>
23+
</ValidatorProvider>
24+
);
25+
26+
await area.instance().validate();
27+
await tick();
28+
expect(area.state().valid).toBeTruthy();
29+
});
30+
31+
it('should validate false', async () => {
32+
const area = mount<ValidatorProvider, ValidatorProviderProps, ValidatorProviderState>(
33+
<ValidatorProvider>
34+
<ValidatorArea rules="same:bar">
35+
<input value="foo" name="foo" />
36+
</ValidatorArea>
37+
38+
<ValidatorArea>
39+
<input value="baz" name="bar" />
40+
</ValidatorArea>
41+
</ValidatorProvider>
42+
);
43+
44+
await area.instance().validate();
45+
await tick();
46+
console.log(area.find(ValidatorArea).first().state());
47+
expect(area.state().valid).toBeFalsy();
48+
});
49+
})

__tests__/suits/utils/utils.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { arraysEqual } from '../../../src/common/utils';
2+
3+
describe('utils test', () => {
4+
it('should check if arrays are equal', () => {
5+
expect(arraysEqual(['foo'], ['foo'])).toBeTruthy();
6+
});
7+
8+
it('should check if arrays are not equal', () => {
9+
expect(arraysEqual(['foo'], ['bar'])).toBeFalsy();
10+
});
11+
12+
it('should check if arrays are not equal', () => {
13+
expect(arraysEqual(['foo'], ['foo', 'bar'])).toBeFalsy();
14+
});
15+
});

src/Rule.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ export type RuleObject = {
1717
* Message shown when the rule doesn't pass
1818
*/
1919
message(): string;
20+
/**
21+
* Array of strings to replace the rule args
22+
*/
23+
messageArgs?(): string[];
2024
}
2125

2226
export type Rule = RuleObject | RuleFunction;

src/Validator.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class Validator {
5858
/**
5959
* Validator area used to access other areas and the provider
6060
*/
61-
private area?: ValidatorArea;
61+
private _area?: ValidatorArea;
6262

6363
/**
6464
* Name used to overwrite name attribute, to allow messages to be more specific
@@ -151,6 +151,17 @@ export class Validator {
151151
return [name, parameters.split(',')];
152152
}
153153

154+
private static parseArgs(rule: RuleObject, args: string[]): string[] {
155+
if (rule.messageArgs) {
156+
return [
157+
...rule.messageArgs(),
158+
...args.slice(rule.messageArgs().length, args.length - 1)
159+
];
160+
}
161+
162+
return args;
163+
}
164+
154165
/**
155166
* Validate a specific rule
156167
*/
@@ -165,7 +176,10 @@ export class Validator {
165176
const passed = await ruleObj.passed(this.elements, ...ruleParameters);
166177

167178
if(!passed) {
168-
this.errors.push(this.localize(ruleObj.message(), ...ruleParameters));
179+
this.errors.push(this.localize(
180+
ruleObj.message(),
181+
Validator.parseArgs(ruleObj, ruleParameters)
182+
));
169183
return false;
170184
}
171185

@@ -192,7 +206,7 @@ export class Validator {
192206
/*
193207
* Get the capitalized, localized message
194208
*/
195-
public localize(message: string, ...ruleArgs: string[]): string {
209+
public localize(message: string, ruleArgs: string[]): string {
196210
return capitalize(this.intl.formatMessage({
197211
id: message,
198212
defaultMessage: message
@@ -213,7 +227,7 @@ export class Validator {
213227
* Sets the current area
214228
*/
215229
public setArea(area: ValidatorArea): Validator {
216-
this.area = area;
230+
this._area = area;
217231

218232
return this;
219233
}
@@ -222,8 +236,8 @@ export class Validator {
222236
* Gets the area where this validator instance is used
223237
*/
224238
public getArea(): ValidatorArea {
225-
if (this.area) {
226-
return this.area;
239+
if (this._area) {
240+
return this._area;
227241
}
228242

229243
throw new Error('Areas are only available when validating React components.');
@@ -236,6 +250,10 @@ export class Validator {
236250
return this.getArea().context.getRefs(name, type);
237251
}
238252

253+
public area(name: string): ValidatorArea | undefined {
254+
return this.getArea().context.getArea(name);
255+
}
256+
239257
/**
240258
* Merges rules from different sources into one array
241259
*/

src/ValidatorContext.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ export interface ValidatorContextProps {
66
rules: RuleOptions;
77
addArea: (name: string, ref: ValidatorArea) => void;
88
getRefs: (name?: string, type?: typeof HTMLElement) => HTMLElement[];
9+
getArea: (name: string) => ValidatorArea | undefined;
910
}
1011

1112
export const ValidatorContext = React.createContext<ValidatorContextProps>({
1213
rules: [],
1314
addArea: () => undefined,
14-
getRefs: () => []
15+
getRefs: () => [],
16+
getArea: () => undefined
1517
});

src/components/ValidatorProvider.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ export class ValidatorProvider extends React.Component<ValidatorProviderProps, V
5555
return !!Object.prototype.hasOwnProperty.call(this.state.areas, name);
5656
}
5757

58+
protected getArea(name: string): ValidatorArea | undefined {
59+
if (!this.hasArea(name)) {
60+
return undefined;
61+
}
62+
63+
return this.state.areas[name];
64+
}
65+
5866
/**
5967
* Sets the errors given via props in the indicated area
6068
*/
@@ -95,7 +103,7 @@ export class ValidatorProvider extends React.Component<ValidatorProviderProps, V
95103
/**
96104
* Validate all areas within this provider
97105
*/
98-
private async validate(onValidated?: () => void): Promise<void> {
106+
public async validate(onValidated?: () => void): Promise<void> {
99107
const { areas } = this.state;
100108

101109
this.setState({
@@ -105,8 +113,10 @@ export class ValidatorProvider extends React.Component<ValidatorProviderProps, V
105113
.map((area) => area.validate())
106114
)).filter((valid: boolean) => !valid);
107115

108-
if (!invalidAreas.length && onValidated) {
109-
onValidated();
116+
if (!invalidAreas.length) {
117+
if (onValidated) {
118+
onValidated();
119+
}
110120
} else {
111121
this.setState({
112122
valid: false
@@ -173,7 +183,8 @@ export class ValidatorProvider extends React.Component<ValidatorProviderProps, V
173183
value={{
174184
rules: rules || [],
175185
addArea: (name: string, ref: ValidatorArea): void => this.addArea(name, ref),
176-
getRefs: (name?: string, type?: typeof HTMLElement) => this.getRefs(name, type)
186+
getRefs: (name?: string, type?: typeof HTMLElement) => this.getRefs(name, type),
187+
getArea: (name: string) => this.getArea(name)
177188
}}
178189
>
179190
{children}

src/locale/en.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ const en: LocaleMessagesMap = {
1010
required: '{name} is required',
1111
length: '{name} should be {0} characters',
1212
minLength: '{name} should have at least {0} characters',
13-
maxLength: '{name} shouldn\'t be more than {0} characters'
13+
maxLength: '{name} shouldn\'t be more than {0} characters',
14+
same: '{name} should be the same as {0}'
1415
}
1516
}
1617

src/locale/nl.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const nl: LocaleMessagesMap = {
1111
length: '{name} moet {0} karakters lang zijn',
1212
minLength: '{name} moet minstens {0} karakters lang zijn',
1313
maxLength: '{name} mag maximaal {0} karakters lang zijn',
14+
same: '{name} moet hetzelfde zijn als {0}'
1415
}
1516
}
1617

src/rules/same.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import {
33
} from '../common/dom';
44
import { Validator } from '../Validator';
55
import { arraysEqual } from '../common/utils';
6+
import { RuleObject } from '../Rule';
67

7-
export default(validator: Validator) => ({
8+
export default(validator: Validator): RuleObject => ({
89
passed(elements: HTMLElement[], name: string): boolean {
910
const values = elements.reduce((prev: string[], element: HTMLElement) => ([
1011
...prev,
@@ -18,7 +19,12 @@ export default(validator: Validator) => ({
1819

1920
return arraysEqual(values, otherValues);
2021
},
22+
messageArgs(): string[] {
23+
return [
24+
'fooo'
25+
];
26+
},
2127
message(): string {
22-
return 'minLength';
28+
return 'same';
2329
}
2430
});

0 commit comments

Comments
 (0)