Skip to content

Commit

Permalink
fix: support object value in within, notIn and unique validators
Browse files Browse the repository at this point in the history
  • Loading branch information
3cp committed Sep 15, 2020
1 parent 6834d4f commit 752c3f2
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 23 deletions.
8 changes: 4 additions & 4 deletions src/standard-validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,14 +286,14 @@ export function config (validation) {

// {validate: 'within', items: [ ... ], caseInsensitive: true}
validation.addValidator("within", [
{if: "!$caseInsensitive", validate: "isTrue", value: "_.includes($items, $value)", message: "must be one of ${_.join($items, ', ')}"},
{if: "$caseInsensitive", validate: "isTrue", value: "_.includes(_.map($items, _.toLower), _.toLower($value))", message: "must be one of ${_.join($items, ', ')}"},
{if: "!$caseInsensitive", validate: "isTrue", value: "_.differenceWith([$value], $items, _.isEqual).length === 0", message: "must be one of ${_.join(_.map($items, JSON.stringify), ', ')}"},
{if: "$caseInsensitive", validate: "isTrue", value: "_.includes(_.map($items, _.toLower), _.toLower($value))", message: "must be one of ${_.join(_.map($items, JSON.stringify), ', ')}"},
]);

// {validate: 'notIn', items: [ ... ], caseInsensitive: true}
validation.addValidator("notIn", [
{if: "!$caseInsensitive", validate: "isFalse", value: "_.includes($items, $value)", message: "must not be one of ${_.join($items, ', ')}"},
{if: "$caseInsensitive", validate: "isFalse", value: "_.includes(_.map($items, _.toLower), _.toLower($value))", message: "must not be one of ${_.join($items, ', ')}"},
{if: "!$caseInsensitive", validate: "isFalse", value: "_.differenceWith([$value], $items, _.isEqual).length === 0", message: "must not be one of ${_.join(_.map($items, JSON.stringify), ', ')}"},
{if: "$caseInsensitive", validate: "isFalse", value: "_.includes(_.map($items, _.toLower), _.toLower($value))", message: "must not be one of ${_.join(_.map($items, JSON.stringify), ', ')}"},
]);

// {validate: 'contain', item: obj, /* or items: [...] */}
Expand Down
1 change: 1 addition & 0 deletions src/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,5 +262,6 @@ Validation.addValidator = addValidator;
config(Validation);
// Add lodash to helper by default
Validation.addHelper('_', _);
Validation.addHelper('JSON', JSON);

export default Validation;
18 changes: 9 additions & 9 deletions test/standard-transformers-and-validators/unique.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ test('unique: tests unique across neighbours on primitive value', t => {
t.end();
});

test('unique: works behind nested rule', t => {
test('unique: works behind nested rule, works with object value', t => {
let rule = {
meta: {
customers: {
foreach: {
details: {name: ["mandatory", "unique"]}
details: {name: ["mandatory", "unique"], ref: "unique"}
}
}
}
Expand All @@ -66,19 +66,19 @@ test('unique: works behind nested rule', t => {
t.deepEqual(v.validate({
meta: {
customers: [
{details: {name: 'Bob'}},
{details: {name: 'Ali'}},
{details: {name: 'Bob'}},
{details: {name: ' '}},
{details: {name: 'Cloc'}}
{details: {name: 'Bob', ref: {id: 1}}},
{details: {name: 'Ali', ref: {id: 2}}},
{details: {name: 'Bob', ref: {id: 3}}},
{details: {name: ' ', ref: {id: 3}}},
{details: {name: 'Cloc', ref: {id: 4}}}
]
}
}, rule), {
meta: {
customers: {
'0': {details: {name: ['must be unique']}},
'2': {details: {name: ['must be unique']}},
'3': {details: {name: ['must not be empty']}}
'2': {details: {name: ['must be unique'], ref: ['must be unique']}},
'3': {details: {name: ['must not be empty'], ref: ['must be unique']}},
}
}
});
Expand Down
31 changes: 23 additions & 8 deletions test/standard-transformers-and-validators/within.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,56 @@ const v = new Validation();

test('within: tests wthin', t => {
let rule = {a: {validate: "within", items:['a', 'b']}};
t.deepEqual(v.validate({a: 'c'}, rule), {a: ["must be one of a, b"]});
t.deepEqual(v.validate({a: 'c'}, rule), {a: ['must be one of "a", "b"']});
t.equal(v.validate({a: 'b'}, rule), undefined);
t.deepEqual(v.validate({a: 'B'}, rule), {a: ["must be one of a, b"]});
t.deepEqual(v.validate({a: 'B'}, rule), {a: ['must be one of "a", "b"']});
t.end();
});

test('within: tests wthin case insensitively', t => {
let rule = {a: {validate: "within", items:['a', 'b'], caseInsensitive: true}};
t.deepEqual(v.validate({a: 'c'}, rule), {a: ["must be one of a, b"]});
t.deepEqual(v.validate({a: 'c'}, rule), {a: ['must be one of "a", "b"']});
t.equal(v.validate({a: 'b'}, rule), undefined);
t.equal(v.validate({a: 'B'}, rule), undefined);
t.end();
});

test('within: tests wthin with runtime bind', t => {
let rule = {a: {validate: "within", 'items.bind': "$input.split(',')", input:'a,b', caseInsensitive: true}};
t.deepEqual(v.validate({a: 'c'}, rule), {a: ["must be one of a, b"]});
t.deepEqual(v.validate({a: 'c'}, rule), {a: ['must be one of "a", "b"']});
t.equal(v.validate({a: 'b'}, rule), undefined);
t.equal(v.validate({a: 'B'}, rule), undefined);
t.end();
});

test('within: tests wthin with object values', t => {
let rule = {a: {validate: "within", items:[{v: 'a'}, {v: 'b'}]}};
t.deepEqual(v.validate({a: {v: 'c'}}, rule), {a: ['must be one of {"v":"a"}, {"v":"b"}']});
t.equal(v.validate({a: {v: 'b'}}, rule), undefined);
t.deepEqual(v.validate({a: {v: 'B'}}, rule), {a: ['must be one of {"v":"a"}, {"v":"b"}']});
t.end();
});

test('notIn: tests not within', t => {
let rule = {a: {validate: "notIn", items:['a', 'b']}};
t.equal(v.validate({a: 'c'}, rule), undefined);
t.deepEqual(v.validate({a: 'b'}, rule), {a: ["must not be one of a, b"]});
t.deepEqual(v.validate({a: 'b'}, rule), {a: ['must not be one of "a", "b"']});
t.equal(v.validate({a: 'B'}, rule),undefined);
t.end();
});


test('notIn: tests not within case insensitively', t => {
let rule = {a: {validate: "notIn", items:['a', 'b'], caseInsensitive: true}};
t.equal(v.validate({a: 'c'}, rule), undefined);
t.deepEqual(v.validate({a: 'b'}, rule), {a: ["must not be one of a, b"]});
t.deepEqual(v.validate({a: 'B'}, rule), {a: ["must not be one of a, b"]});
t.deepEqual(v.validate({a: 'b'}, rule), {a: ['must not be one of "a", "b"']});
t.deepEqual(v.validate({a: 'B'}, rule), {a: ['must not be one of "a", "b"']});
t.end();
});

test('notIn: tests not within with object values', t => {
let rule = {a: {validate: "notIn", items:[{v: 'a'}, {v: 'b'}]}};
t.equal(v.validate({a: {v: 'c'}}, rule), undefined);
t.deepEqual(v.validate({a: {v: 'b'}}, rule), {a: ['must not be one of {"v":"a"}, {"v":"b"}']});
t.equal(v.validate({a: {v: 'B'}}, rule),undefined);
t.end();
});
4 changes: 2 additions & 2 deletions test/validation.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ test('Validation: user defined validator', t => {
};

t.equal(v.validate({value: 'NA'}, rule), undefined);
t.deepEqual(v.validate({value: 'C'}, rule), {value: ["must be one of A, B"]});
t.deepEqual(v.validate({value: 'C'}, rule), {value: ['must be one of "A", "B"']});
t.end();
});

Expand All @@ -366,7 +366,7 @@ test('Validation: user defined global validator', t => {
const v = new Validation();

t.equal(v.validate({value: 'NA'}, rule), undefined);
t.deepEqual(v.validate({value: 'C'}, rule), {value: ["must be one of A, B"]});
t.deepEqual(v.validate({value: 'C'}, rule), {value: ['must be one of "A", "B"']});
t.end();
});

Expand Down

0 comments on commit 752c3f2

Please sign in to comment.