Skip to content

Commit

Permalink
feat: finalize resolve()
Browse files Browse the repository at this point in the history
  • Loading branch information
vonagam committed Feb 4, 2019
1 parent d02ff5e commit 2ed8456
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 27 deletions.
25 changes: 13 additions & 12 deletions src/Condition.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import isSchema from './util/isSchema';

function callOrConcat(schema) {
if (typeof schema === 'function') return schema;

return base => base.concat(schema);
if (!schema) return base => base;
return (base, options) => base.concat(schema.resolve(options));
}

class Conditional {
Expand Down Expand Up @@ -32,27 +32,28 @@ class Conditional {
: (...values) => values.every(value => value === is);

this.fn = function(...values) {
let currentSchema = values.pop();
let options = values.pop();
let schema = values.pop();
let option = isFn(...values) ? then : otherwise;

return option(currentSchema);
return option(schema, options);
};
}
}

getValue(parent, context) {
let values = this.refs.map(r => r.getValue(parent, context));
resolve(ctx, options) {
let values = this.refs.map(r =>
r.getValue(options.parent, options.context),
);

return values;
}
let schema = this.fn.apply(ctx, values.concat(ctx, options));

resolve(ctx, values) {
let schema = this.fn.apply(ctx, values.concat(ctx));
if (schema === undefined) return ctx;

if (schema !== undefined && !isSchema(schema))
if (!isSchema(schema))
throw new TypeError('conditions must return a schema object');

return schema || ctx;
return schema.resolve(options);
}
}

Expand Down
11 changes: 6 additions & 5 deletions src/Lazy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import isSchema from './util/isSchema';

class Lazy {
constructor(mapFn) {
this._resolve = (...args) => {
let schema = mapFn(...args);
this._resolve = (value, options) => {
let schema = mapFn(value, options);

if (!isSchema(schema))
throw new TypeError('lazy() functions must return a valid schema');

return schema;
return schema.resolve(options);
};
}
resolve({ value, ...rest }) {
return this._resolve(value, rest);
resolve(options) {
return this._resolve(options.value, options);
}
cast(value, options) {
return this._resolve(value, options).cast(value, options);
Expand Down
21 changes: 12 additions & 9 deletions src/mixed.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,19 @@ const proto = (SchemaType.prototype = {
return !this._typeCheck || this._typeCheck(v);
},

resolve({ context, parent }) {
if (this._conditions.length) {
return this._conditions.reduce(
(schema, match) =>
match.resolve(schema, match.getValue(parent, context)),
this,
);
}
resolve(options) {
if (!this._conditions.length) return this;

let schema = this.clone();
let conditions = this._conditions;

schema._conditions = [];
schema = conditions.reduce(
(schema, condition) => condition.resolve(schema, options),
schema,
);

return this;
return schema.resolve(options);
},

cast(value, options = {}) {
Expand Down
36 changes: 35 additions & 1 deletion test/mixed.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
import { array, mixed, string, number, object, ref, reach, bool } from '../src';
import {
array,
mixed,
string,
number,
object,
ref,
reach,
bool,
lazy,
ValidationError,
} from '../src';

let noop = () => {};

function ensureSync(fn) {
Expand Down Expand Up @@ -701,6 +713,28 @@ describe('Mixed Types ', () => {
inst.default().should.eql({ prop: undefined });
});

it('should allow nested conditions and lazies', async function() {
let inst = string().when('$check', {
is: value => typeof value === 'string',
then: string().when('$check', {
is: value => /hello/.test(value),
then: lazy(() => string().min(6)),
}),
});

await inst
.validate('pass', { context: { check: false } })
.should.be.fulfilled();

await inst
.validate('pass', { context: { check: 'hello' } })
.should.be.rejectedWith(ValidationError, /must be at least/);

await inst
.validate('passes', { context: { check: 'hello' } })
.should.be.fulfilled();
});

it('should use label in error message', async function() {
let label = 'Label';
let inst = object({
Expand Down

0 comments on commit 2ed8456

Please sign in to comment.