Skip to content

Commit d12cac6

Browse files
authored
Merge pull request #845 from rvsia/managerWarnings
feat(manager): introduce warnings feature
2 parents 24cd6fa + a98bd49 commit d12cac6

File tree

5 files changed

+68
-8
lines changed

5 files changed

+68
-8
lines changed

packages/form-state-manager/src/files/compose-validators.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ import ComposeValidators from '../types/compose-validators';
1010
* @returns {Function} New validation function
1111
*/
1212
const composeValidators: ComposeValidators = (validators = []) => (value, allValues) => {
13-
const promises: Promise<string | undefined>[] = [];
13+
const promises: Promise<any>[] = [];
1414
let index = 0;
15-
let error: string | undefined;
15+
let error: any;
1616
while (validators.length > 0 && !error && index < validators.length) {
1717
const result = validators[index](value, allValues);
1818
if (isPromise(result)) {
19-
promises.push(result as Promise<string | undefined>);
19+
promises.push(result as Promise<any>);
2020
} else {
21-
error = result as string | undefined;
21+
error = result as any;
2222
}
2323

2424
index = index + 1;

packages/form-state-manager/src/tests/utils/manager-api.test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,4 +1876,32 @@ describe('managerApi', () => {
18761876
expect(managerApi().hasSubmitErrors).toEqual(true);
18771877
});
18781878
});
1879+
1880+
describe('warning validation', () => {
1881+
const someError = 'some error message';
1882+
const render = jest.fn();
1883+
1884+
it('should save type: warning as warning - sync', () => {
1885+
const managerApi = createManagerApi({});
1886+
managerApi().registerField({ name: 'field', validate: () => ({ type: 'warning', error: someError }), render, internalId: 1 });
1887+
1888+
expect(managerApi().getFieldState('field').meta.warning).toEqual(someError);
1889+
expect(managerApi().getFieldState('field').meta.error).toEqual(undefined);
1890+
});
1891+
1892+
it('should save type: warning as warning - async', (done) => {
1893+
expect.assertions(2);
1894+
1895+
const asyncValidate = jest.fn().mockImplementation(() => Promise.reject({ type: 'warning', error: someError }));
1896+
1897+
const managerApi = createManagerApi({});
1898+
managerApi().registerField({ name: 'field', validate: asyncValidate, render, internalId: 1 });
1899+
1900+
setImmediate(() => {
1901+
expect(managerApi().getFieldState('field').meta.warning).toEqual(someError);
1902+
expect(managerApi().getFieldState('field').meta.error).toEqual(undefined);
1903+
done();
1904+
});
1905+
});
1906+
});
18791907
});
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { Validator } from './validate';
22
import AnyObject from './any-object';
33

4-
export type ComposeValidators = (validators: Validator[]) => (value: any, allValues: AnyObject) => Promise<string | undefined> | string | undefined;
4+
export interface WarningObject<T = string | undefined> {
5+
type: 'warning';
6+
error: T;
7+
}
8+
9+
export type ComposeValidators<T = WarningObject | string | undefined> = (
10+
validators: Validator[]
11+
) => (value: any, allValues: AnyObject) => Promise<T> | T;
512

613
export default ComposeValidators;

packages/form-state-manager/src/types/use-field.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export interface Meta {
3838
valid: boolean;
3939
validating: boolean;
4040
visited: boolean;
41+
warning: any;
4142
}
4243

4344
export type OnChange = (value: any) => void;

packages/form-state-manager/src/utils/manager-api.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import CreateManagerApi, {
2424
import AnyObject from '../types/any-object';
2525
import FieldConfig, { IsEqual } from '../types/field-config';
2626
import { Meta } from '../types/use-field';
27+
import { WarningObject } from '../types/compose-validators';
2728
import { formLevelValidator, isPromise } from './validate';
2829
import { FormValidator, FormLevelError, Validator } from '../types/validate';
2930
import findDifference from './find-difference';
@@ -142,7 +143,8 @@ export const initialMeta = (initial: any): Meta => ({
142143
touched: false,
143144
valid: true,
144145
validating: false,
145-
visited: false
146+
visited: false,
147+
warning: undefined
146148
});
147149

148150
export const createField = (name: string, value: any): FieldState => ({
@@ -307,10 +309,32 @@ const createManagerApi: CreateManagerApi = ({
307309
if (isPromise(result)) {
308310
(result as Promise<string | undefined>)
309311
.then(() => handleFieldError(name, true))
310-
.catch((response) => handleFieldError(name, false, response as string | undefined));
312+
.catch((response) => {
313+
if (response?.type === 'warning') {
314+
setFieldState(name, (prev: FieldState) => ({
315+
...prev,
316+
meta: {
317+
...prev.meta,
318+
warning: response.error
319+
}
320+
}));
321+
} else {
322+
handleFieldError(name, false, response as string | undefined);
323+
}
324+
});
311325
listener.registerValidator(result as Promise<string | undefined>);
312326
} else {
313-
handleFieldError(name, !result, result as string | undefined);
327+
if ((result as WarningObject)?.type === 'warning') {
328+
setFieldState(name, (prev: FieldState) => ({
329+
...prev,
330+
meta: {
331+
...prev.meta,
332+
warning: (result as WarningObject)?.error
333+
}
334+
}));
335+
} else {
336+
handleFieldError(name, !result, result as string | undefined);
337+
}
314338
}
315339
}
316340
}

0 commit comments

Comments
 (0)