Skip to content

Commit 2ae7a57

Browse files
authored
Merge pull request #880 from rvsia/resetErrors
fix(manager): reset errors when revalidated
2 parents 35dbce2 + 37ef083 commit 2ae7a57

File tree

2 files changed

+173
-9
lines changed

2 files changed

+173
-9
lines changed

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

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,47 @@ describe('managerApi', () => {
12191219
});
12201220
});
12211221
});
1222+
1223+
it('should reset error state when revalidated', () => {
1224+
jest.useFakeTimers();
1225+
const render = jest.fn();
1226+
const managerApi = createManagerApi({ validate: asyncValidate });
1227+
const { registerField, change } = managerApi();
1228+
1229+
registerField({ name: 'foo', render });
1230+
1231+
change('foo', 'foo');
1232+
1233+
jest.advanceTimersByTime(10);
1234+
setImmediate(() => {
1235+
expect(managerApi().getState().errors).toEqual({
1236+
foo: 'error'
1237+
});
1238+
expect(managerApi().getState().valid).toEqual(false);
1239+
expect(managerApi().getState().invalid).toEqual(true);
1240+
expect(managerApi().getState().validating).toEqual(false);
1241+
expect(managerApi().hasValidationErrors).toEqual(true);
1242+
1243+
change('foo', 'foo');
1244+
1245+
expect(managerApi().getState().errors).toEqual({});
1246+
expect(managerApi().getState().valid).toEqual(true);
1247+
expect(managerApi().getState().invalid).toEqual(false);
1248+
expect(managerApi().getState().validating).toEqual(true);
1249+
expect(managerApi().hasValidationErrors).toEqual(false);
1250+
1251+
jest.advanceTimersByTime(10);
1252+
setImmediate(() => {
1253+
expect(managerApi().getState().errors).toEqual({
1254+
foo: 'error'
1255+
});
1256+
expect(managerApi().getState().valid).toEqual(false);
1257+
expect(managerApi().getState().invalid).toEqual(true);
1258+
expect(managerApi().getState().validating).toEqual(false);
1259+
expect(managerApi().hasValidationErrors).toEqual(true);
1260+
});
1261+
});
1262+
});
12221263
});
12231264

12241265
describe('Combine form and field level validation', () => {
@@ -1532,6 +1573,37 @@ describe('managerApi', () => {
15321573
});
15331574
});
15341575
});
1576+
1577+
it('should reset field.error when validating', async (done) => {
1578+
expect.assertions(8);
1579+
jest.useFakeTimers();
1580+
const render = jest.fn();
1581+
1582+
const managerApi = createManagerApi({});
1583+
managerApi().registerField({ name: 'field', initialValue: 'one', validate: asyncValidate1, render, internalId: 1 });
1584+
1585+
jest.runAllTimers();
1586+
1587+
setImmediate(() => {
1588+
expect(managerApi().getFieldState('field').error).toEqual('error-one');
1589+
expect(managerApi().getFieldState('field').valid).toEqual(false);
1590+
expect(managerApi().getFieldState('field').invalid).toEqual(true);
1591+
1592+
managerApi().change('field', 'ok');
1593+
1594+
expect(managerApi().getFieldState('field').error).toEqual(undefined);
1595+
expect(managerApi().getFieldState('field').valid).toEqual(true);
1596+
expect(managerApi().getFieldState('field').invalid).toEqual(false);
1597+
1598+
jest.runAllTimers();
1599+
1600+
setImmediate(() => {
1601+
expect(managerApi().getFieldState('field').validating).toEqual(false);
1602+
expect(managerApi().getState().validating).toEqual(false);
1603+
done();
1604+
});
1605+
});
1606+
});
15351607
});
15361608

15371609
describe('initialize', () => {
@@ -2019,6 +2091,36 @@ describe('managerApi', () => {
20192091
expect(managerApi().getFieldState('field').meta.error).toEqual(undefined);
20202092
});
20212093

2094+
it('warning should rewrite error - sync', () => {
2095+
const managerApi = createManagerApi({});
2096+
managerApi().registerField({
2097+
name: 'field',
2098+
initialValue: 'warning',
2099+
validate: (value) => (value === 'warning' ? { type: 'warning', error: someError } : 'error'),
2100+
render,
2101+
internalId: 1
2102+
});
2103+
2104+
expect(managerApi().getFieldState('field').meta.warning).toEqual(someError);
2105+
expect(managerApi().getFieldState('field').meta.error).toEqual(undefined);
2106+
expect(managerApi().getFieldState('field').meta.valid).toEqual(true);
2107+
expect(managerApi().getFieldState('field').meta.invalid).toEqual(false);
2108+
2109+
managerApi().change('field', 'error');
2110+
2111+
expect(managerApi().getFieldState('field').meta.warning).toEqual(undefined);
2112+
expect(managerApi().getFieldState('field').meta.error).toEqual('error');
2113+
expect(managerApi().getFieldState('field').meta.valid).toEqual(false);
2114+
expect(managerApi().getFieldState('field').meta.invalid).toEqual(true);
2115+
2116+
managerApi().change('field', 'warning');
2117+
2118+
expect(managerApi().getFieldState('field').meta.warning).toEqual(someError);
2119+
expect(managerApi().getFieldState('field').meta.error).toEqual(undefined);
2120+
expect(managerApi().getFieldState('field').meta.valid).toEqual(true);
2121+
expect(managerApi().getFieldState('field').meta.invalid).toEqual(false);
2122+
});
2123+
20222124
it('should save type: warning as warning - async', (done) => {
20232125
expect.assertions(2);
20242126

@@ -2033,6 +2135,52 @@ describe('managerApi', () => {
20332135
done();
20342136
});
20352137
});
2138+
2139+
it('warning should rewrite error - async', (done) => {
2140+
expect.assertions(18);
2141+
2142+
const asyncValidate = jest
2143+
.fn()
2144+
.mockImplementation((value) => Promise.reject(value === 'warning' ? { type: 'warning', error: someError } : 'error'));
2145+
2146+
const managerApi = createManagerApi({});
2147+
managerApi().registerField({ name: 'field', initialValue: 'warning', validate: asyncValidate, render, internalId: 1 });
2148+
2149+
expect(managerApi().getFieldState('field').meta.validating).toEqual(true);
2150+
2151+
setImmediate(() => {
2152+
expect(managerApi().getFieldState('field').meta.warning).toEqual(someError);
2153+
expect(managerApi().getFieldState('field').meta.error).toEqual(undefined);
2154+
expect(managerApi().getFieldState('field').meta.valid).toEqual(true);
2155+
expect(managerApi().getFieldState('field').meta.invalid).toEqual(false);
2156+
expect(managerApi().getFieldState('field').meta.validating).toEqual(false);
2157+
2158+
managerApi().change('field', 'error');
2159+
2160+
expect(managerApi().getFieldState('field').meta.validating).toEqual(true);
2161+
2162+
setImmediate(() => {
2163+
expect(managerApi().getFieldState('field').meta.warning).toEqual(undefined);
2164+
expect(managerApi().getFieldState('field').meta.error).toEqual('error');
2165+
expect(managerApi().getFieldState('field').meta.valid).toEqual(false);
2166+
expect(managerApi().getFieldState('field').meta.invalid).toEqual(true);
2167+
expect(managerApi().getFieldState('field').meta.validating).toEqual(false);
2168+
2169+
managerApi().change('field', 'warning');
2170+
2171+
expect(managerApi().getFieldState('field').meta.validating).toEqual(true);
2172+
2173+
setImmediate(() => {
2174+
expect(managerApi().getFieldState('field').meta.warning).toEqual(someError);
2175+
expect(managerApi().getFieldState('field').meta.error).toEqual(undefined);
2176+
expect(managerApi().getFieldState('field').meta.valid).toEqual(true);
2177+
expect(managerApi().getFieldState('field').meta.invalid).toEqual(false);
2178+
expect(managerApi().getFieldState('field').meta.validating).toEqual(false);
2179+
done();
2180+
});
2181+
});
2182+
});
2183+
});
20362184
});
20372185

20382186
describe('invalid submit', () => {

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

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -291,15 +291,16 @@ const createManagerApi: CreateManagerApi = ({
291291
runFormValidation = false;
292292
}
293293

294-
function handleFieldError(name: string, isValid: boolean, error: string | undefined = undefined) {
294+
function handleFieldError(name: string, isValid: boolean, error: string | undefined = undefined, validating = false) {
295295
setFieldState(name, (prev: FieldState) => ({
296296
...prev,
297297
meta: {
298298
...prev.meta,
299299
error,
300300
valid: isValid,
301301
invalid: !isValid,
302-
validating: false
302+
validating,
303+
warning: undefined
303304
}
304305
}));
305306

@@ -322,6 +323,7 @@ const createManagerApi: CreateManagerApi = ({
322323
if (validators.length > 0) {
323324
const result = composeValidators(validators as Validator[])(value, state.values);
324325
if (isPromise(result)) {
326+
handleFieldError(name, true, undefined, true);
325327
(result as Promise<string | undefined>)
326328
.then(() => handleFieldError(name, true))
327329
.catch((response) => {
@@ -330,7 +332,11 @@ const createManagerApi: CreateManagerApi = ({
330332
...prev,
331333
meta: {
332334
...prev.meta,
333-
warning: response.error
335+
warning: response.error,
336+
error: undefined,
337+
valid: true,
338+
invalid: false,
339+
validating: false
334340
}
335341
}));
336342
} else {
@@ -344,7 +350,11 @@ const createManagerApi: CreateManagerApi = ({
344350
...prev,
345351
meta: {
346352
...prev.meta,
347-
warning: (result as WarningObject)?.error
353+
warning: (result as WarningObject)?.error,
354+
error: undefined,
355+
valid: true,
356+
invalid: false,
357+
validating: false
348358
}
349359
}));
350360
} else {
@@ -443,22 +453,28 @@ const createManagerApi: CreateManagerApi = ({
443453
const currentInvalidFields = Object.keys(state.errors);
444454
if (isPromise(result)) {
445455
const asyncResult = result as Promise<FormLevelError>;
456+
457+
state.errors = {};
458+
state.hasValidationErrors = false;
459+
state.valid = true;
460+
state.invalid = false;
461+
state.error = undefined;
462+
446463
return asyncResult
447464
.then(() => {
448465
if (!state.validating) {
449-
state.errors = {};
450-
state.hasValidationErrors = false;
451-
state.valid = true;
452-
state.invalid = false;
453-
state.error = undefined;
454466
revalidateFields(currentInvalidFields);
455467
}
456468
})
457469
.catch((errors) => {
470+
const render = prepareRerender();
471+
458472
state.errors = errors;
459473
state.hasValidationErrors = true;
460474
state.valid = false;
461475
state.invalid = true;
476+
477+
render();
462478
});
463479
}
464480

0 commit comments

Comments
 (0)