Skip to content

Commit fb5fa5d

Browse files
authored
Merge pull request #60 from 53js/fix/helpers-paths-wildcard
fix(helpers): convert every array index in error paths; escape wildcard prefix
2 parents 23f6d9d + 6f25159 commit fb5fa5d

2 files changed

Lines changed: 34 additions & 2 deletions

File tree

‎src/lib/Form/helpers.js‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ export const formatErrors = (errors) => (errors || []).map((error) => {
159159

160160
formatted.field = formatted.field
161161
.replace(/^\./, '')
162-
.replace(/\[([0-9]+)\]/, '.$1');
162+
.replace(/\[([0-9]+)\]/g, '.$1');
163163

164164
return formatted;
165165
});
@@ -178,7 +178,10 @@ export const filterByFieldNameWithWildcard = (fields, fieldName) => {
178178
/** @type {RegExp | undefined} */
179179
let regex;
180180
if (/\*$/.test(fieldName)) {
181-
regex = new RegExp(`^${fieldName.replace(/\*$/, '')}`);
181+
// Escape regex metacharacters so a prefix like `user.` matches the
182+
// literal dot instead of any character (`user.*` must not match `userX`).
183+
const prefix = fieldName.replace(/\*$/, '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
184+
regex = new RegExp(`^${prefix}`);
182185
}
183186

184187
return fields.filter((e) => {

‎src/lib/Form/helpers.test.js‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ describe('.formatErrors(errors)', () => {
8181
const errors = [{ dataPath: 'arr[0].input' }];
8282
expect(helpers.formatErrors(errors)[0].field).toStrictEqual('arr.0.input');
8383
});
84+
85+
it('should convert every array index when the path contains several', () => {
86+
const errors = [{ dataPath: 'items[0].tags[1]' }];
87+
expect(helpers.formatErrors(errors)[0].field).toStrictEqual('items.0.tags.1');
88+
});
8489
});
8590

8691
describe('.filterByFieldNameWithWildcard(fields, fieldName)', () => {
@@ -109,6 +114,30 @@ describe('.filterByFieldNameWithWildcard(fields, fieldName)', () => {
109114
expect(helpers.filterByFieldNameWithWildcard(fields, 'name*'))
110115
.toEqual([{ field: 'name' }, { field: 'name1' }]);
111116
});
117+
118+
it('should treat the dot in a wildcard prefix as a literal character', () => {
119+
const fields = [
120+
{ field: 'user.email' },
121+
{ field: 'userX' },
122+
{ field: 'user' },
123+
];
124+
125+
expect(helpers.filterByFieldNameWithWildcard(fields, 'user.*'))
126+
.toEqual([{ field: 'user.email' }]);
127+
});
128+
129+
it('should not crash when the wildcard prefix contains an unclosed bracket', () => {
130+
const fields = [
131+
{ field: 'items[0].label' },
132+
{ field: 'items[1].label' },
133+
{ field: 'other' },
134+
];
135+
136+
// The unescaped prefix `items[0` used to throw a SyntaxError
137+
// (unterminated character class) when compiled to a RegExp.
138+
expect(helpers.filterByFieldNameWithWildcard(fields, 'items[0*'))
139+
.toEqual([{ field: 'items[0].label' }]);
140+
});
112141
});
113142

114143
describe('.getInputCheckboxValue(target)', () => {

0 commit comments

Comments
 (0)