diff --git a/src/util/reach.js b/src/util/reach.js index 1f8fae725..23a61e781 100644 --- a/src/util/reach.js +++ b/src/util/reach.js @@ -16,7 +16,9 @@ export function getIn(schema, path, value, context) { schema, }; - forEach(path, (_part, isBracket, isArray) => { + // I no longer remember why this is so complicated + forEach(path, (_part, isBracket, isArray, partIdx, parts) => { + let isLast = partIdx === parts.length - 1; let part = isBracket ? trim(_part) : _part; if (isArray || has(schema, '_subType')) { @@ -33,6 +35,11 @@ export function getIn(schema, path, value, context) { ); } + if (isLast) { + parent = value; + lastPart = part; + lastPartDebug = isBracket ? '[' + _part + ']' : '.' + _part; + } value = value[idx]; } } @@ -43,7 +50,7 @@ export function getIn(schema, path, value, context) { if (!has(schema, 'fields') || !has(schema.fields, part)) throw new Error( `The schema does not contain the path: ${path}. ` + - `(failed at: ${lastPartDebug} which is a type: "${schema._type}") `, + `(failed at: ${lastPartDebug} which is a type: "${schema._type}")`, ); schema = schema.fields[part]; diff --git a/test/yup.js b/test/yup.js index e87734585..3f8126bd1 100644 --- a/test/yup.js +++ b/test/yup.js @@ -66,17 +66,18 @@ describe('Yup', function() { }); it('should getIn correctly', async () => { - var num = number(), - inst = object().shape({ - num: number().max(4), - - nested: object().shape({ - arr: array().of(object().shape({ 'num-1': num })), - }), - }); + let num = number(); + let shape = object({ 'num-1': num }); + let inst = object({ + num: number().max(4), + + nested: object({ + arr: array().of(shape), + }), + }); const value = { nested: { arr: [{}, { 'num-1': 2 }] } }; - const { schema, parent, parentPath } = getIn( + let { schema, parent, parentPath } = getIn( inst, 'nested.arr[1].num-1', value, @@ -87,21 +88,50 @@ describe('Yup', function() { expect(parent).to.equal(value.nested.arr[1]); }); + it('should getIn array correctly', async () => { + let num = number(); + let shape = object({ 'num-1': num }); + let inst = object({ + num: number().max(4), + + nested: object({ + arr: array().of(shape), + }), + }); + + const value = { + nested: { + arr: [{}, { 'num-1': 2 }], + }, + }; + + const { schema, parent, parentPath } = getIn(inst, 'nested.arr[1]', value); + + console.log(parentPath); + expect(schema).to.equal(shape); + expect(parentPath).to.equal('1'); + expect(parent).to.equal(value.nested.arr); + }); + it('should REACH correctly', async () => { - var num = number(), - inst = object().shape({ - num: number().max(4), + let num = number(); + let shape = object({ num }); - nested: object().shape({ - arr: array().of(object().shape({ num: num })), - }), - }); + let inst = object({ + num: number().max(4), + + nested: object({ + arr: array().of(shape), + }), + }); reach(inst, '').should.equal(inst); reach(inst, 'nested.arr.num').should.equal(num); reach(inst, 'nested.arr[].num').should.equal(num); reach(inst, 'nested.arr[1].num').should.equal(num); + reach(inst, 'nested.arr[1]').should.equal(shape); + reach(inst, 'nested["arr"][1].num').should.not.equal(number()); let valid = await reach(inst, 'nested.arr[].num').isValid(5); @@ -185,7 +215,10 @@ describe('Yup', function() { }) .strict() .validate({ - x: [{ type: 1, foo: '4' }, { type: 2, foo: '5' }], + x: [ + { type: 1, foo: '4' }, + { type: 2, foo: '5' }, + ], }) .should.be.rejected(); err.message.should.match(/must be a `number` type/);