Skip to content

Commit

Permalink
[fixed] array().concat() incorrectly cleared the sub-schema
Browse files Browse the repository at this point in the history
  • Loading branch information
jquense committed Jul 18, 2016
1 parent b2bcbf7 commit 69c0ad4
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 7 deletions.
29 changes: 26 additions & 3 deletions src/array.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import typeOf from 'type-name';

import inherits from './util/inherits';
import isAbsent from './util/isAbsent';
import isSchema from './util/isSchema';
import MixedSchema from './mixed';
import { mixed, array as locale } from './locale.js';
import runValidations, { propagateErrors } from './util/runValidations';
Expand All @@ -15,7 +18,9 @@ function ArraySchema(type) {

MixedSchema.call(this, { type: 'array'})

this._subType = null;
// `undefined` specifically means uninitialized, as opposed to
// "no subtype"
this._subType = undefined;

this.withMutation(() => {
this.transform(function(values) {
Expand Down Expand Up @@ -91,9 +96,27 @@ inherits(ArraySchema, MixedSchema, {
})
},

of(schema){
// concat(schema) {
// var next = MixedSchema.prototype.concat.call(this, schema)
//
// next._subType = schema._subType === undefined
// ? this._subType
// : schema._subType;
//
// return next
// },

of(schema) {
var next = this.clone()
next._subType = schema

if (schema !== false && !isSchema(schema))
throw new TypeError(
'`array.of()` sub-schema must be a valid yup schema, or `false` to negate a current sub-schema. ' +
'got: ' + typeOf(schema) + ' instead'
)

next._subType = schema;

return next
},

Expand Down
13 changes: 9 additions & 4 deletions src/util/reach.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,19 @@ module.exports = function (obj, path, value, context) {
forEach(path, (_part, isBracket, isArray) => {
let part = isBracket ? trim(_part) : _part;

if (isArray || has(obj, '_subType')) { // we skipped an array
let idx = isArray ? parseInt(part, 10) : 0
if (isArray || has(obj, '_subType')) { // we skipped an array: foo[].bar
let idx = isArray ? parseInt(part, 10) : 0;

obj = obj.resolve({ context, parent, value })._subType;

if (value) {

if (isArray && idx >= value.length) {
throw new Error(
`Yup.reach cannot resolve an array item at index: ${_part}, in the path: ${path}. ` +
`because there is no value at that index. `
)
}

value = value[idx]
}
}
Expand All @@ -45,5 +46,9 @@ module.exports = function (obj, path, value, context) {
}
})

return obj && obj.resolve({ context, parent, value })
if (obj) {
obj = obj.resolve({ context, parent, value });
}

return obj
}
16 changes: 16 additions & 0 deletions test/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ describe('Array types', function(){
.cast(['1', '3']).should.eql([1, 3])
})

it('should concat subType correctly', function(){
expect(
array()
.of(number())
.concat(array())
._subType
).to.exist

expect(
array()
.of(number())
.concat(array().of(false))
._subType
).to.equal(false)
})

it('should pass options to children', function(){
array(
object({ name: string() })
Expand Down

0 comments on commit 69c0ad4

Please sign in to comment.