Skip to content

Commit 21a98d0

Browse files
committed
fix(manager): do not focus on empty errors
1 parent f7c832f commit 21a98d0

File tree

5 files changed

+167
-54
lines changed

5 files changed

+167
-54
lines changed

packages/form-state-manager/src/tests/files/use-field.test.js

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const SubscribedComponent = ({ fakeComponent, ...props }) => {
2727
};
2828

2929
const DummyComponent = ({ subscriberProps, managerApi }) => (
30-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
30+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
3131
<SubscribedComponent {...subscriberProps} />
3232
</FormManagerContext.Provider>
3333
);
@@ -265,7 +265,7 @@ describe('useField', () => {
265265
const managerApi = createManagerApi({});
266266

267267
const wrapper = mount(
268-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
268+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
269269
<RenderWatch name="field" />
270270
</FormManagerContext.Provider>
271271
);
@@ -284,7 +284,7 @@ describe('useField', () => {
284284
const managerApi = createManagerApi({});
285285

286286
const wrapper = mount(
287-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
287+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
288288
<RenderWatch name="field" subscription={{ valid: true }} />
289289
</FormManagerContext.Provider>
290290
);
@@ -310,7 +310,7 @@ describe('useField', () => {
310310
const managerApi = createManagerApi({ subscription: { valid: true } });
311311

312312
const wrapper = mount(
313-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
313+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
314314
<RenderWatch name="field" subscription={{ valid: true }} />
315315
</FormManagerContext.Provider>
316316
);
@@ -499,7 +499,7 @@ describe('useField', () => {
499499
const managerApi = createManagerApi({});
500500

501501
const wrapper = mount(
502-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
502+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
503503
<CleanButton name="field" value="some value" clearedValue={null} />
504504
</FormManagerContext.Provider>
505505
);
@@ -516,7 +516,7 @@ describe('useField', () => {
516516
const managerApi = createManagerApi({});
517517

518518
const wrapper = mount(
519-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi, clearedValue: null }}>
519+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi(), clearedValue: null }}>
520520
<CleanButton name="field" value="some value" />
521521
</FormManagerContext.Provider>
522522
);
@@ -533,7 +533,7 @@ describe('useField', () => {
533533
const managerApi = createManagerApi({});
534534

535535
const wrapper = mount(
536-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi, clearedValue: null }}>
536+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi(), clearedValue: null }}>
537537
<CleanButton name="field" value="some value" clearedValue="cleared" />
538538
</FormManagerContext.Provider>
539539
);
@@ -576,7 +576,7 @@ describe('useField', () => {
576576

577577
it('should parse string', async () => {
578578
wrapper = mount(
579-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
579+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
580580
<Setter name="field" dataType="string" />
581581
</FormManagerContext.Provider>
582582
);
@@ -593,7 +593,7 @@ describe('useField', () => {
593593

594594
it('should parse float', async () => {
595595
wrapper = mount(
596-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
596+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
597597
<Setter name="field" dataType="float" />
598598
</FormManagerContext.Provider>
599599
);
@@ -610,7 +610,7 @@ describe('useField', () => {
610610

611611
it('should parse number', async () => {
612612
wrapper = mount(
613-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
613+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
614614
<Setter name="field" dataType="number" />
615615
</FormManagerContext.Provider>
616616
);
@@ -627,7 +627,7 @@ describe('useField', () => {
627627

628628
it('should parse boolean', async () => {
629629
wrapper = mount(
630-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
630+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
631631
<Setter name="field" dataType="boolean" />
632632
</FormManagerContext.Provider>
633633
);
@@ -644,7 +644,7 @@ describe('useField', () => {
644644

645645
it('should parse integer', async () => {
646646
wrapper = mount(
647-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
647+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
648648
<Setter name="field" dataType="integer" />
649649
</FormManagerContext.Provider>
650650
);
@@ -661,7 +661,7 @@ describe('useField', () => {
661661

662662
it('should parse array of numbers', async () => {
663663
wrapper = mount(
664-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
664+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
665665
<Setter name="field" dataType="number" value={['1', '2', '45']} />
666666
</FormManagerContext.Provider>
667667
);
@@ -676,7 +676,7 @@ describe('useField', () => {
676676

677677
it('should parse initialValue - float', async () => {
678678
wrapper = mount(
679-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
679+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
680680
<Setter name="field" dataType="float" initialValue="12.34" />
681681
</FormManagerContext.Provider>
682682
);
@@ -686,7 +686,7 @@ describe('useField', () => {
686686

687687
it('should parse defaultValue - float', async () => {
688688
wrapper = mount(
689-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
689+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
690690
<Setter name="field" dataType="float" defaultValue="12.34" />
691691
</FormManagerContext.Provider>
692692
);
@@ -696,7 +696,7 @@ describe('useField', () => {
696696

697697
it('should parse defaultValue - objects', async () => {
698698
wrapper = mount(
699-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
699+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
700700
<Setter name="field" dataType="float" defaultValue={[{ value: '23.67' }, { value: '123.34' }]} />
701701
</FormManagerContext.Provider>
702702
);
@@ -725,7 +725,7 @@ describe('useField', () => {
725725

726726
it('checkbox with no value', async () => {
727727
wrapper = mount(
728-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
728+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
729729
<Typper name="field" type="checkbox" spy={spy} />
730730
</FormManagerContext.Provider>
731731
);
@@ -787,7 +787,7 @@ describe('useField', () => {
787787
const spyHamster = jest.fn();
788788

789789
wrapper = mount(
790-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
790+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
791791
<Typper name="field" value="dog" type="checkbox" spy={spyDog} />
792792
<Typper name="field" value="cat" type="checkbox" spy={spyCat} />
793793
<Typper name="field" value="hamster" type="checkbox" spy={spyHamster} />
@@ -968,7 +968,7 @@ describe('useField', () => {
968968
const spyHamster = jest.fn();
969969

970970
wrapper = mount(
971-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
971+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
972972
<Typper name="field" value="dog" type="radio" spy={spyDog} />
973973
<Typper name="field" value="cat" type="radio" spy={spyCat} />
974974
<Typper name="field" value="hamster" type="radio" spy={spyHamster} />
@@ -1160,7 +1160,7 @@ describe('useField', () => {
11601160
it('parse value on change', async () => {
11611161
const parse = jest.fn().mockImplementation((value, name) => value * 2);
11621162
wrapper = mount(
1163-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1163+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
11641164
<Dummy name="field" parse={parse} />
11651165
</FormManagerContext.Provider>
11661166
);
@@ -1177,7 +1177,7 @@ describe('useField', () => {
11771177
it('format value', async () => {
11781178
const format = jest.fn().mockImplementation((value, name) => value * 2);
11791179
wrapper = mount(
1180-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1180+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
11811181
<Dummy name="field" format={format} />
11821182
</FormManagerContext.Provider>
11831183
);
@@ -1195,7 +1195,7 @@ describe('useField', () => {
11951195
it('format value on blur', async () => {
11961196
const format = jest.fn().mockImplementation((value, name) => value * 2);
11971197
wrapper = mount(
1198-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1198+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
11991199
<Dummy name="field" format={format} formatOnBlur />
12001200
</FormManagerContext.Provider>
12011201
);
@@ -1227,7 +1227,7 @@ describe('useField', () => {
12271227

12281228
it('default parse and format handles undefined/empty string', async () => {
12291229
wrapper = mount(
1230-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1230+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
12311231
<Dummy name="field" />
12321232
</FormManagerContext.Provider>
12331233
);
@@ -1267,7 +1267,7 @@ describe('useField', () => {
12671267

12681268
it('by default converts null to empty string', async () => {
12691269
wrapper = mount(
1270-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1270+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
12711271
<Dummy name="field" />
12721272
</FormManagerContext.Provider>
12731273
);
@@ -1292,7 +1292,7 @@ describe('useField', () => {
12921292
console.error = jest.fn();
12931293

12941294
wrapper = mount(
1295-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1295+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
12961296
<Dummy name="field" allowNull />
12971297
</FormManagerContext.Provider>
12981298
);
@@ -1328,7 +1328,7 @@ describe('useField', () => {
13281328

13291329
it('select and deselect multiple', async () => {
13301330
wrapper = mount(
1331-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1331+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
13321332
<Select name="field" multiple />
13331333
</FormManagerContext.Provider>
13341334
);
@@ -1390,7 +1390,7 @@ describe('useField', () => {
13901390
it('register inputFile name and uregister', async () => {
13911391
expect(managerApi().fileInputs).toEqual([]);
13921392
wrapper = mount(
1393-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1393+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
13941394
<Dummy name="field" type="file" />
13951395
</FormManagerContext.Provider>
13961396
);
@@ -1406,7 +1406,7 @@ describe('useField', () => {
14061406

14071407
it('sanitize value', async () => {
14081408
wrapper = mount(
1409-
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1409+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi() }}>
14101410
<Dummy name="field" type="file" />
14111411
</FormManagerContext.Provider>
14121412
);

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,22 @@ describe('focusError', () => {
4545
expect(listenerNotError).not.toHaveBeenCalled();
4646
expect(listenerError).toHaveBeenCalled();
4747
});
48+
49+
it('not focus first error element when error is empty', async () => {
50+
document.body.innerHTML = `<form name="foo">
51+
<input name="field-1" />
52+
<input name="field-2" />
53+
<input name="field-3" />
54+
</form>`;
55+
56+
const listener = jest.fn();
57+
58+
document.querySelector('[name="field-2"]').addEventListener('focus', listener);
59+
60+
expect(listener).not.toHaveBeenCalled();
61+
62+
focusError({ 'field-2': '' });
63+
64+
expect(listener).not.toHaveBeenCalled();
65+
});
4866
});

packages/form-state-manager/src/utils/focus-error.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const focusError = (errors: AnyObject, name?: string): void => {
1414

1515
const errorKeys = Object.keys(errors);
1616

17-
const firstError = allInputs.find((inp) => errorKeys.includes(inp.name));
17+
const firstError = allInputs.find((inp) => errorKeys.includes(inp.name) && errors[inp.name]);
1818

1919
firstError && firstError.focus();
2020
}

packages/react-form-renderer/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
"webpack-merge": "^4.1.4"
6565
},
6666
"dependencies": {
67-
"@data-driven-forms/form-state-manager": "*",
6867
"lodash": "^4.17.15",
6968
"prop-types": "^15.7.2",
7069
"react-final-form": "^6.5.0",

0 commit comments

Comments
 (0)