Skip to content

Commit 0f1bd38

Browse files
authored
Merge pull request #104 from intech/master
add unique validation in array rule
2 parents f2af4dd + 72533e9 commit 0f1bd38

File tree

5 files changed

+34
-0
lines changed

5 files changed

+34
-0
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,18 @@ v.validate({ roles: ["user", "admin"] }, schema); // Valid
355355
v.validate({ roles: ["guest"] }, schema); // Fail
356356
```
357357

358+
**Example for `unique`:**
359+
```js
360+
const schema = {
361+
roles: { type: "array", unique: true }
362+
}
363+
364+
v.validate({ roles: ["user"] }, schema); // Valid
365+
v.validate({ roles: [{role:"user"},{role:"admin"},{role:"user"}] }, schema); // Valid
366+
v.validate({ roles: ["user", "admin", "user"] }, schema); // Fail
367+
v.validate({ roles: [1, 2, 1] }, schema); // Fail
368+
```
369+
358370
### Properties
359371
Property | Default | Description
360372
-------- | -------- | -----------
@@ -363,6 +375,7 @@ Property | Default | Description
363375
`max` | `null` | Maximum count of elements.
364376
`length` | `null` | Fix count of elements.
365377
`contains` | `null` | The array must contain this element too.
378+
`unique` | `null` | The array must be unique (array of objects is always unique).
366379
`enum` | `null` | Every element must be an element of the `enum` array.
367380
`items` | `null` | Schema for array items.
368381

@@ -969,6 +982,7 @@ Name | Default text
969982
`arrayMax` | The '{field}' field must contain less than or equal to {expected} items.
970983
`arrayLength` | The '{field}' field must contain {expected} items.
971984
`arrayContains` | The '{field}' field must contain the '{expected}' item.
985+
`arrayUnique` | The '{actual}' value in '{field}' field does not unique the '{expected}' values.
972986
`arrayEnum` | The '{actual}' value in '{field}' field does not match any of the '{expected}' values.
973987
`boolean` | The '{field}' field must be a boolean.
974988
`function` | The '{field}' field must be a function.

lib/messages.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module.exports = {
3131
arrayMax: "The '{field}' field must contain less than or equal to {expected} items.",
3232
arrayLength: "The '{field}' field must contain {expected} items.",
3333
arrayContains: "The '{field}' field must contain the '{expected}' item.",
34+
arrayUnique: "The '{actual}' value in '{field}' field does not unique the '{expected}' values.",
3435
arrayEnum: "The '{actual}' value in '{field}' field does not match any of the '{expected}' values.",
3536

3637
boolean: "The '{field}' field must be a boolean.",

lib/rules/array.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ module.exports = function({ schema, messages }, path, context) {
5454
`);
5555
}
5656

57+
if (schema.unique === true) {
58+
src.push(`
59+
if(len > (new Set(value)).size) {
60+
${this.makeError({ type: "arrayUnique", expected: "Array.from(new Set(value.filter((item, index) => value.indexOf(item) !== index)))", actual: "value", messages })}
61+
}
62+
`);
63+
}
64+
5765
if (schema.enum != null) {
5866
const enumStr = JSON.stringify(schema.enum);
5967
src.push(`

test/messages.spec.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ describe("Test Messages", () => {
3030
expect(msg.arrayMax).toBeDefined();
3131
expect(msg.arrayLength).toBeDefined();
3232
expect(msg.arrayContains).toBeDefined();
33+
expect(msg.arrayUnique).toBeDefined();
3334
expect(msg.arrayEnum).toBeDefined();
3435
expect(msg.boolean).toBeDefined();
3536
expect(msg.function).toBeDefined();

test/rules/array.spec.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ describe("Test rule: array", () => {
7171
expect(check([8, 5, 2])).toEqual(true);
7272
});
7373

74+
it("check unique", () => {
75+
const check = v.compile({ $$root: true, type: "array", unique: true });
76+
77+
expect(check(["bob","john","bob"])).toEqual([{ type: "arrayUnique", expected: ["bob"], actual: ["bob", "john", "bob"], message: "The 'bob,john,bob' value in '' field does not unique the 'bob' values." }]);
78+
expect(check(["bob","john","bob","bob","john"])).toEqual([{ type: "arrayUnique", expected: ["bob","john"], actual: ["bob","john","bob","bob","john"], message: "The 'bob,john,bob,bob,john' value in '' field does not unique the 'bob,john' values." }]);
79+
expect(check([1,2,1,false,true,false])).toEqual([{ type: "arrayUnique", expected: [1,false], actual: [1,2,1,false,true,false], message: "The '1,2,1,false,true,false' value in '' field does not unique the '1,false' values." }]);
80+
expect(check([{name:"bob"},{name:"john"},{name:"bob"}])).toEqual(true);
81+
expect(check(["john", "bob"])).toEqual(true);
82+
});
83+
7484
it("check enum", () => {
7585
const check = v.compile({ $$root: true, type: "array", enum: ["male", "female"] });
7686

0 commit comments

Comments
 (0)