Skip to content

Commit

Permalink
fix: #473 make concat compatible with (not)oneOf (#492)
Browse files Browse the repository at this point in the history
* fix: #473 make concat compatible with (not)oneOf

* Combine RefSet.union() and setminus() into single merge() function
  • Loading branch information
Philipp91 authored and jquense committed May 6, 2019
1 parent a8935b7 commit 8d21cc9
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 4 deletions.
31 changes: 27 additions & 4 deletions src/mixed.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ class RefSet {
Ref.isRef(value) ? this.refs.set(value.key, value) : this.list.add(value);
}
delete(value) {
Ref.isRef(value)
? this.refs.delete(value.key, value)
: this.list.delete(value);
Ref.isRef(value) ? this.refs.delete(value.key) : this.list.delete(value);
}
has(value, resolve) {
if (this.list.has(value)) return true;
Expand All @@ -38,6 +36,20 @@ class RefSet {

return false;
}
clone() {
const next = new RefSet();
next.list = new Set(this.list);
next.refs = new Map(this.refs);
return next;
}
merge(newItems, removeItems) {
const next = this.clone();
newItems.list.forEach(value => next.add(value));
newItems.refs.forEach(value => next.add(value));
removeItems.list.forEach(value => next.delete(value));
removeItems.refs.forEach(value => next.delete(value));
return next;
}
}

export default function SchemaType(options = {}) {
Expand Down Expand Up @@ -112,12 +124,23 @@ const proto = (SchemaType.prototype = {

var next = prependDeep(schema.clone(), this);

// new undefined default is overriden by old non-undefined one, revert
// new undefined default is overridden by old non-undefined one, revert
if (has(schema, '_default')) next._default = schema._default;

next.tests = this.tests;
next._exclusive = this._exclusive;

// manually merge the blacklist/whitelist (the other `schema` takes
// precedence in case of conflicts)
next._whitelist = this._whitelist.merge(
schema._whitelist,
schema._blacklist,
);
next._blacklist = this._blacklist.merge(
schema._blacklist,
schema._whitelist,
);

// manually add the new tests to ensure
// the deduping logic is consistent
next.withMutation(next => {
Expand Down
41 changes: 41 additions & 0 deletions test/mixed.js
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,47 @@ describe('Mixed Types ', () => {
);
});

it('concat should preserve oneOf', async function() {
let inst = string()
.oneOf(['a'])
.concat(string().default('hi'));

await inst.isValid('a').should.become(true);
});

it('gives whitelist precedence to second in concat', async function() {
let inst = string()
.oneOf(['a', 'b', 'c'])
.concat(string().notOneOf(['b']));

await inst.isValid('a').should.become(true);
await inst.isValid('b').should.become(false);
await inst.isValid('c').should.become(true);
});

it('gives blacklist precedence to second in concat', async function() {
let inst = string()
.notOneOf(['a', 'b', 'c'])
.concat(string().oneOf(['b', 'c']));

await inst.isValid('a').should.become(false);
await inst.isValid('b').should.become(true);
await inst.isValid('c').should.become(true);
});

it('concats whitelist with refs', async function() {
let inst = object({
x: string().required(),
y: string()
.oneOf([ref('$x'), 'b', 'c'])
.concat(string().notOneOf(['c', ref('$x')])),
});

await inst.isValid({ x: 'a', y: 'a' }).should.become(false);
await inst.isValid({ x: 'a', y: 'b' }).should.become(true);
await inst.isValid({ x: 'a', y: 'c' }).should.become(false);
});

it('defaults should be validated but not transformed', function() {
let inst = string()
.trim()
Expand Down

0 comments on commit 8d21cc9

Please sign in to comment.