vest 3.2.8-dev-6d7c74 → 3.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +115 -0
  2. package/any.d.ts +3 -0
  3. package/any.js +1 -0
  4. package/classNames.d.ts +14 -0
  5. package/classNames.js +1 -0
  6. package/docs/.nojekyll +0 -0
  7. package/docs/README.md +115 -0
  8. package/docs/_assets/favicon.ico +0 -0
  9. package/docs/_assets/vest-logo.png +0 -0
  10. package/docs/_sidebar.md +19 -0
  11. package/docs/_sidebar.md.bak +14 -0
  12. package/docs/cross_field_validations.md +79 -0
  13. package/docs/enforce.md +18 -0
  14. package/docs/enforce.md.bak +13 -0
  15. package/docs/exclusion.md +128 -0
  16. package/docs/getting_started.md +79 -0
  17. package/docs/group.md +142 -0
  18. package/docs/index.html +41 -0
  19. package/docs/migration.md +107 -0
  20. package/docs/n4s/compound.md +187 -0
  21. package/docs/n4s/custom.md +52 -0
  22. package/docs/n4s/external.md +54 -0
  23. package/docs/n4s/rules.md +1282 -0
  24. package/docs/n4s/template.md +53 -0
  25. package/docs/node.md +43 -0
  26. package/docs/optional.md +51 -0
  27. package/docs/result.md +238 -0
  28. package/docs/state.md +102 -0
  29. package/docs/test.md +172 -0
  30. package/docs/utilities.md +105 -0
  31. package/docs/warn.md +82 -0
  32. package/enforce.d.ts +230 -0
  33. package/esm/package.json +1 -0
  34. package/esm/vest.es.development.js +2493 -0
  35. package/esm/vest.es.production.js +2490 -0
  36. package/esm/vest.es.production.min.js +1 -0
  37. package/package.json +65 -12
  38. package/promisify.d.ts +7 -0
  39. package/{dist/umd/promisify.production.js → promisify.js} +1 -1
  40. package/schema.d.ts +26 -0
  41. package/schema.js +1 -0
  42. package/vest.cjs.development.js +2494 -0
  43. package/vest.cjs.production.js +2491 -0
  44. package/vest.cjs.production.min.js +1 -0
  45. package/vest.d.ts +254 -0
  46. package/vest.js +7 -0
  47. package/vest.umd.development.js +2711 -0
  48. package/vest.umd.production.js +2708 -0
  49. package/vest.umd.production.min.js +1 -0
  50. package/vestResult.d.ts +105 -0
  51. package/CHANGELOG.md +0 -94
  52. package/LICENSE +0 -21
  53. package/classnames/index.js +0 -7
  54. package/classnames/package.json +0 -1
  55. package/dist/cjs/classnames.development.js +0 -67
  56. package/dist/cjs/classnames.production.js +0 -1
  57. package/dist/cjs/promisify.development.js +0 -20
  58. package/dist/cjs/promisify.production.js +0 -1
  59. package/dist/cjs/vest.development.js +0 -1616
  60. package/dist/cjs/vest.production.js +0 -1
  61. package/dist/es/classnames.development.js +0 -65
  62. package/dist/es/classnames.production.js +0 -1
  63. package/dist/es/promisify.development.js +0 -18
  64. package/dist/es/promisify.production.js +0 -1
  65. package/dist/es/vest.development.js +0 -1604
  66. package/dist/es/vest.production.js +0 -1
  67. package/dist/umd/classnames.development.js +0 -73
  68. package/dist/umd/classnames.production.js +0 -1
  69. package/dist/umd/promisify.development.js +0 -26
  70. package/dist/umd/vest.development.js +0 -1622
  71. package/dist/umd/vest.production.js +0 -1
  72. package/index.js +0 -7
  73. package/promisify/index.js +0 -7
  74. package/promisify/package.json +0 -1
  75. package/types/classnames.d.ts +0 -71
  76. package/types/classnames.d.ts.map +0 -1
  77. package/types/promisify.d.ts +0 -61
  78. package/types/promisify.d.ts.map +0 -1
  79. package/types/vest.d.ts +0 -271
  80. package/types/vest.d.ts.map +0 -1
package/README.md CHANGED
@@ -0,0 +1,115 @@
1
+ ![Vest](https://cdn.jsdelivr.net/gh/ealush/vest@assets/vest-logo.png 'Vest')
2
+
3
+ # Vest 🦺 Declarative Validation Testing
4
+
5
+ ![Github Stars](https://githubbadges.com/star.svg?user=ealush&repo=vest&style=flat)
6
+ ![Npm downloads](https://img.shields.io/npm/dt/vest?label=Downloads&logo=npm)
7
+
8
+ [![npm version](https://badge.fury.io/js/vest.svg)](https://badge.fury.io/js/vest) [![Build Status](https://travis-ci.org/ealush/vest.svg?branch=latest)](https://travis-ci.org/ealush/vest) [![Known Vulnerabilities](https://snyk.io/test/npm/vest/badge.svg)](https://snyk.io/test/npm/vest)
9
+ ![minifiedSize](https://img.shields.io/bundlephobia/min/vest?color=blue&logo=npm)
10
+
11
+ [![Join discord](https://img.shields.io/discord/757686103292641312?label=Join%20Discord&logo=discord&logoColor=green)](https://discord.gg/WmADZpJnSe)
12
+
13
+ - [Documentation homepage](https://vestjs.dev)
14
+ - **Try vest live**
15
+ - [Vanilla JS Example](https://stackblitz.com/edit/vest-vanilla-support-example?file=validation.js)
16
+ - ReactJS Examples:
17
+ - [Example 1 (groups)](https://codesandbox.io/s/ecstatic-waterfall-4i2ne?file=/src/validate.js)
18
+ - [Example 2 (Async)](https://codesandbox.io/s/youthful-williamson-loijb?file=/src/validate.js)
19
+ - [Example 3](https://stackblitz.com/edit/vest-react-support-example?file=validation.js)
20
+ - [Example 4](https://stackblitz.com/edit/vest-react-registration?file=validate.js)
21
+ - [Example 5 (Password validator)](https://codesandbox.io/s/password-validator-example-6puvy?file=/src/validate.js)
22
+ - [VueJS Example](https://codesandbox.io/s/vest-vue-example-1j6r8?file=/src/validations.js)
23
+ - [Svelte Example](https://codesandbox.io/s/vestdocssvelteexample-k87t7?file=/validate.js)
24
+
25
+ ## Tutorials
26
+
27
+ [Step By Step React Tutorial](https://dev.to/ealush/dead-simple-form-validation-with-vest-5gf8)
28
+
29
+ ## [Release Notes](https://github.com/ealush/vest/releases)
30
+
31
+ ## 🦺 What is Vest?
32
+
33
+ Vest is a validations library for JS apps that derives its syntax from modern JS unit testing frameworks such as Mocha or Jest. It is easy to learn due to its use of already common declarative patterns.
34
+ It works great with user-input validation and with validating upon user interaction to provide the best possible user experience.
35
+
36
+ The idea behind Vest is that your validations can be described as a 'spec' or a contract that reflects your form or feature structure. Your validations run in production, and they are framework agnostic - meaning Vest works well with React, Angular, Vue, or even without a framework at all.
37
+
38
+ Using Vest for form validation can reduce bloat, improve feature readability and maintainability.
39
+
40
+ **Basic Example**
41
+ ![full](https://cdn.jsdelivr.net/gh/ealush/vest@assets/demos/full_3.gif 'full')
42
+
43
+ **Memoized async test**
44
+ ![memo](https://cdn.jsdelivr.net/gh/ealush/vest@assets/demos/memo.gif 'memo')
45
+
46
+ ## ✅ Motivation
47
+
48
+ Writing forms is an integral part of building web apps, and even though it may seem trivial at first - as your feature grows over time, so does your validation logic grows in complexity.
49
+
50
+ Vest tries to remediate this by separating validation logic from feature logic so it is easier to maintain over time and refactor when needed.
51
+
52
+ ## ✨ Vest's features
53
+
54
+ - 🎨 Framework agnostic (BYOUI)
55
+ - ⚡️ Rich, extendable, assertions library (enforce) ([doc](http://vestjs.dev/#/enforce))
56
+ - 🚥 Multiple validations for the same field
57
+ - ⚠️ Warning (non failing) tests ([doc](http://vestjs.dev/#/warn))
58
+ - 📝 Validate only the fields the user interacted with ([doc](http://vestjs.dev/#/exclusion))
59
+ - ⏳ Memoize async validations to reduce calls to the server ([doc](http://vestjs.dev/#/test?id=testmemo-for-memoized-tests))
60
+ - 🚦 Test grouping ([doc](http://vestjs.dev/#/group))
61
+
62
+ ## Example code ([Run in sandbox](https://codesandbox.io/s/vest-react-tutorial-finished-ztt8t?file=/src/validate.js))
63
+
64
+ ```js
65
+ import { create, only, test, enforce, warn, skipWhen } from 'vest';
66
+
67
+ export default create('user_form', (data = {}, currentField) => {
68
+ only(currentField);
69
+
70
+ test('username', 'Username is required', () => {
71
+ enforce(data.username).isNotEmpty();
72
+ });
73
+
74
+ test('username', 'Username is too short', () => {
75
+ enforce(data.username).longerThanOrEquals(3);
76
+ });
77
+
78
+ test('password', 'Password is required', () => {
79
+ enforce(data.password).isNotEmpty();
80
+ });
81
+
82
+ test('password', 'Password must be at least 6 chars long', () => {
83
+ enforce(data.password).longerThanOrEquals(6);
84
+ });
85
+
86
+ test('password', 'Password is weak, Maybe add a number?', () => {
87
+ warn();
88
+ enforce(data.password).matches(/[0-9]/);
89
+ });
90
+
91
+ skipWhen(!data.password, () => {
92
+ test('confirm_password', 'Passwords do not match', () => {
93
+ enforce(data.confirm_password).equals(data.password);
94
+ });
95
+ });
96
+
97
+ test('email', 'Email Address is not valid', () => {
98
+ enforce(data.email).isEmail();
99
+ });
100
+
101
+ test('tos', () => {
102
+ enforce(data.tos).isTruthy();
103
+ });
104
+ });
105
+ ```
106
+
107
+ ## Why Vest?
108
+
109
+ - 🧠 Vest is really easy to learn. You can take your existing knowledge of unit tests and transfer it to validations.
110
+ - ✏️ Vest takes into account user interaction and warn only validations.
111
+ - 🧱 Your validations are structured, making it very simple to read and write. All validation files look the same.
112
+ - 🖇 Your validation logic is separate from your feature logic, preventing the spaghetti code that's usually involved with writing validations.
113
+ - 🧩 Validation logic is easy to share and reuse across features.
114
+
115
+ **Vest is an evolution of [Passable](https://github.com/fiverr/passable) by Fiverr.**
package/any.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ declare function any(...args: any[]): boolean;
2
+
3
+ export default any;
package/any.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self)["any@anyone"]=n()}(this,(function(){var e=function(e){if("function"==typeof e)try{return n(e())}catch(e){return!1}return n(e)},n=function(e){return!!Array.isArray(e)||0!=e&&!!e};return function(){for(var n=arguments.length,t=Array(n),r=0;r<n;r++)t[r]=arguments[r];return t.some(e)}}));
@@ -0,0 +1,14 @@
1
+ import { IVestResult } from './vestResult';
2
+
3
+ declare function classNames(
4
+ res: Partial<IVestResult>,
5
+ classes?: {
6
+ valid?: string;
7
+ tested?: string;
8
+ invalid?: string;
9
+ warning?: string;
10
+ untested?: string;
11
+ }
12
+ ): (fieldName: string) => string;
13
+
14
+ export default classNames;
package/classNames.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).classNames=e()}(this,(function(){function t(t){return!(isNaN(parseFloat(t))||isNaN(Number(t))||!isFinite(t))}return function(e,n){if(void 0===n&&(n={}),!e||"function"!=typeof e.hasErrors)throw Error("[vest/classNames]: Expected first argument to be Vest's result object.");var r={},s={tested:function(n){return Object.prototype.hasOwnProperty.call(r,n)?r[n]:((o=Object.prototype.hasOwnProperty.call(e.tests,n))&&(o=t(o=e.tests[n].testCount)&&t(0)&&Number(o)>Number(0)),r[n]=o,s.tested(n));var o},untested:function(t){return!s.tested(t)},invalid:function(t){return s.tested(t)&&e.hasErrors(t)},warning:function(t){return s.tested(t)&&e.hasWarnings(t)},valid:function(t){return s.tested(t)&&!e.hasWarnings(t)&&!e.hasErrors(t)}};return function(t){var e,r=[];for(e in n)s[e]&&s[e](t)&&r.push(n[e]);return r.join(" ")}}}));
package/docs/.nojekyll ADDED
File without changes
package/docs/README.md ADDED
@@ -0,0 +1,115 @@
1
+ ![Vest](https://cdn.jsdelivr.net/gh/ealush/vest@assets/vest-logo.png 'Vest')
2
+
3
+ # Vest 🦺 Declarative Validation Testing
4
+
5
+ ![Github Stars](https://githubbadges.com/star.svg?user=ealush&repo=vest&style=flat)
6
+ ![Npm downloads](https://img.shields.io/npm/dt/vest?label=Downloads&logo=npm)
7
+
8
+ [![npm version](https://badge.fury.io/js/vest.svg)](https://badge.fury.io/js/vest) [![Build Status](https://travis-ci.org/ealush/vest.svg?branch=latest)](https://travis-ci.org/ealush/vest) [![Known Vulnerabilities](https://snyk.io/test/npm/vest/badge.svg)](https://snyk.io/test/npm/vest)
9
+ ![minifiedSize](https://img.shields.io/bundlephobia/min/vest?color=blue&logo=npm)
10
+
11
+ [![Join discord](https://img.shields.io/discord/757686103292641312?label=Join%20Discord&logo=discord&logoColor=green)](https://discord.gg/WmADZpJnSe)
12
+
13
+ - [Documentation homepage](https://vestjs.dev)
14
+ - **Try vest live**
15
+ - [Vanilla JS Example](https://stackblitz.com/edit/vest-vanilla-support-example?file=validation.js)
16
+ - ReactJS Examples:
17
+ - [Example 1 (groups)](https://codesandbox.io/s/ecstatic-waterfall-4i2ne?file=/src/validate.js)
18
+ - [Example 2 (Async)](https://codesandbox.io/s/youthful-williamson-loijb?file=/src/validate.js)
19
+ - [Example 3](https://stackblitz.com/edit/vest-react-support-example?file=validation.js)
20
+ - [Example 4](https://stackblitz.com/edit/vest-react-registration?file=validate.js)
21
+ - [Example 5 (Password validator)](https://codesandbox.io/s/password-validator-example-6puvy?file=/src/validate.js)
22
+ - [VueJS Example](https://codesandbox.io/s/vest-vue-example-1j6r8?file=/src/validations.js)
23
+ - [Svelte Example](https://codesandbox.io/s/vestdocssvelteexample-k87t7?file=/validate.js)
24
+
25
+ ## Tutorials
26
+
27
+ [Step By Step React Tutorial](https://dev.to/ealush/dead-simple-form-validation-with-vest-5gf8)
28
+
29
+ ## [Release Notes](https://github.com/ealush/vest/releases)
30
+
31
+ ## 🦺 What is Vest?
32
+
33
+ Vest is a validations library for JS apps that derives its syntax from modern JS unit testing frameworks such as Mocha or Jest. It is easy to learn due to its use of already common declarative patterns.
34
+ It works great with user-input validation and with validating upon user interaction to provide the best possible user experience.
35
+
36
+ The idea behind Vest is that your validations can be described as a 'spec' or a contract that reflects your form or feature structure. Your validations run in production, and they are framework agnostic - meaning Vest works well with React, Angular, Vue, or even without a framework at all.
37
+
38
+ Using Vest for form validation can reduce bloat, improve feature readability and maintainability.
39
+
40
+ **Basic Example**
41
+ ![full](https://cdn.jsdelivr.net/gh/ealush/vest@assets/demos/full_3.gif 'full')
42
+
43
+ **Memoized async test**
44
+ ![memo](https://cdn.jsdelivr.net/gh/ealush/vest@assets/demos/memo.gif 'memo')
45
+
46
+ ## ✅ Motivation
47
+
48
+ Writing forms is an integral part of building web apps, and even though it may seem trivial at first - as your feature grows over time, so does your validation logic grows in complexity.
49
+
50
+ Vest tries to remediate this by separating validation logic from feature logic so it is easier to maintain over time and refactor when needed.
51
+
52
+ ## ✨ Vest's features
53
+
54
+ - 🎨 Framework agnostic (BYOUI)
55
+ - ⚡️ Rich, extendable, assertions library (enforce) ([doc](http://vestjs.dev/#/enforce))
56
+ - 🚥 Multiple validations for the same field
57
+ - ⚠️ Warning (non failing) tests ([doc](http://vestjs.dev/#/warn))
58
+ - 📝 Validate only the fields the user interacted with ([doc](http://vestjs.dev/#/exclusion))
59
+ - ⏳ Memoize async validations to reduce calls to the server ([doc](http://vestjs.dev/#/test?id=testmemo-for-memoized-tests))
60
+ - 🚦 Test grouping ([doc](http://vestjs.dev/#/group))
61
+
62
+ ## Example code ([Run in sandbox](https://codesandbox.io/s/vest-react-tutorial-finished-ztt8t?file=/src/validate.js))
63
+
64
+ ```js
65
+ import { create, only, test, enforce, warn, skipWhen } from 'vest';
66
+
67
+ export default create('user_form', (data = {}, currentField) => {
68
+ only(currentField);
69
+
70
+ test('username', 'Username is required', () => {
71
+ enforce(data.username).isNotEmpty();
72
+ });
73
+
74
+ test('username', 'Username is too short', () => {
75
+ enforce(data.username).longerThanOrEquals(3);
76
+ });
77
+
78
+ test('password', 'Password is required', () => {
79
+ enforce(data.password).isNotEmpty();
80
+ });
81
+
82
+ test('password', 'Password must be at least 6 chars long', () => {
83
+ enforce(data.password).longerThanOrEquals(6);
84
+ });
85
+
86
+ test('password', 'Password is weak, Maybe add a number?', () => {
87
+ warn();
88
+ enforce(data.password).matches(/[0-9]/);
89
+ });
90
+
91
+ skipWhen(!data.password, () => {
92
+ test('confirm_password', 'Passwords do not match', () => {
93
+ enforce(data.confirm_password).equals(data.password);
94
+ });
95
+ });
96
+
97
+ test('email', 'Email Address is not valid', () => {
98
+ enforce(data.email).isEmail();
99
+ });
100
+
101
+ test('tos', () => {
102
+ enforce(data.tos).isTruthy();
103
+ });
104
+ });
105
+ ```
106
+
107
+ ## Why Vest?
108
+
109
+ - 🧠 Vest is really easy to learn. You can take your existing knowledge of unit tests and transfer it to validations.
110
+ - ✏️ Vest takes into account user interaction and warn only validations.
111
+ - 🧱 Your validations are structured, making it very simple to read and write. All validation files look the same.
112
+ - 🖇 Your validation logic is separate from your feature logic, preventing the spaghetti code that's usually involved with writing validations.
113
+ - 🧩 Validation logic is easy to share and reuse across features.
114
+
115
+ **Vest is an evolution of [Passable](https://github.com/fiverr/passable) by Fiverr.**
Binary file
Binary file
@@ -0,0 +1,19 @@
1
+ - [Getting Started](./getting_started)
2
+ - [enforce](./enforce)
3
+ - [List of Enforce rules](./n4s/rules)
4
+ - [Creating Custom Rules](./n4s/custom)
5
+ - [Shape and schema validation](./n4s/compound)
6
+ - [Enforce templates](./n4s/template)
7
+ - [Consuming external rules](./n4s/external)
8
+ - [The result object](./result)
9
+ - [test](./test)
10
+ - [How to fail a test](./test#failing_a_test)
11
+ - [Warn only tests](./warn)
12
+ - [Grouping tests](./group)
13
+ - [Optional Tests](./optional)
14
+ - Advanced cases
15
+ - [Cross Field Validations](./cross_field_validations)
16
+ - [Excluding or including tests](./exclusion)
17
+ - [Using with node](./node)
18
+ - [Utilities](./utilities)
19
+ - [Migration Guides](./migration)
@@ -0,0 +1,14 @@
1
+ - [Getting Started](./getting_started)
2
+ - [enforce](./enforce){{ENFORCE_DOCS}}
3
+ - [The result object](./result)
4
+ - [test](./test)
5
+ - [How to fail a test](./test#failing_a_test)
6
+ - [Warn only tests](./warn)
7
+ - [Grouping tests](./group)
8
+ - [Optional Tests](./optional)
9
+ - Advanced cases
10
+ - [Cross Field Validations](./cross_field_validations)
11
+ - [Excluding or including tests](./exclusion)
12
+ - [Using with node](./node)
13
+ - [Utilities](./utilities)
14
+ - [Migration Guides](./migration)
@@ -0,0 +1,79 @@
1
+ # Cross Field Validations
2
+
3
+ Sometimes it is not enough to only validate a field by itself, because its validity is dependant on the validity or invalidity of a different field.
4
+
5
+ Take for example the password confirmation field, by itself it serves no purpose, and as long as the password itself is not field, you might choose to not validate it to begin with. That's an **AND** relationship between fields. There can also be an **OR** relationship between fields, for example - either email address or phone number have to be filled, but neither is required as long the other was filled by the user.
6
+
7
+ All these cases can be easily handled with Vest in different ways, depending on your requirements and validation strategy.
8
+
9
+ ## The Any utility
10
+
11
+ Your specific example can be handled with the `any` utility function. The `any` utility function takes a series of functions or expressions, and as long as at least one evaluates to `true`, it will mark your validation as passing.
12
+
13
+ ### Use any to use different conditions in the same test
14
+
15
+ You could also use any within your test, if you have a joined test for both scenarios. This means that you have to return a boolean from your tests.
16
+
17
+ Demo: https://codesandbox.io/s/demo-forked-ltn8l?file=/src/validate.js
18
+
19
+ ```js
20
+ import { create, test, enforce } from 'vest';
21
+ import any from 'vest/any';
22
+
23
+ export default create('form_name', (data = {}) => {
24
+ test('email_or_phone', 'Email or phone must be set', () =>
25
+ any(
26
+ () => {
27
+ enforce(data.email).isNotEmpty();
28
+ return true;
29
+ },
30
+ () => {
31
+ enforce(data.phone).isNotEmpty();
32
+ return true;
33
+ }
34
+ )
35
+ );
36
+ });
37
+ ```
38
+
39
+ ## skipWhen for conditionally skipping fields
40
+
41
+ If your field depends on a different field's existence or a different simple condition, you could use skipWhen.
42
+ In the following example I only validate `confirm` if password is not empty:
43
+
44
+ DEMO: https://codesandbox.io/s/demo-forked-z2ur9?file=/src/validate.js
45
+
46
+ ```js
47
+ import { create, test, enforce, skipWhen } from 'vest';
48
+ export default create('user_form', (data = {}) => {
49
+ test('password', 'Password is required', () => {
50
+ enforce(data.password).isNotEmpty();
51
+ });
52
+ skipWhen(!data.password, () => {
53
+ test('confirm', 'Passwords do not match', () => {
54
+ enforce(data.confirm).equals(data.password);
55
+ });
56
+ });
57
+ });
58
+ ```
59
+
60
+ ## skipWhen for conditionally skipping field based on a previous result
61
+
62
+ Sometimes you might want to run a certain validation based on the validation result of a previously run test, for example - only test for password strength if password DOESN'T have Errors. You could access the intermediate validation result and use it mid-run.
63
+
64
+ This requires using the function created from create():
65
+
66
+ ```js
67
+ import { create, test, enforce, skipWhen } from 'vest';
68
+ const suite = create('user_form', (data = {}) => {
69
+ test('password', 'Password is required', () => {
70
+ enforce(data.password).isNotEmpty();
71
+ });
72
+ skipWhen(suite.get().hasErrors('password'), () => {
73
+ test('password', 'Password is weak', () => {
74
+ enforce(data.password).longerThan(8);
75
+ });
76
+ });
77
+ });
78
+ export default suite;
79
+ ```
@@ -0,0 +1,18 @@
1
+ # Enforce
2
+
3
+ Enforce is Vest's assertion library. It is used to validate values within, or outside of a Vest test.
4
+
5
+ ```js
6
+ import { enforce, test } from 'vest';
7
+
8
+ test('username', 'Must be at least three characters long', () => {
9
+ enforce(username).longerThan(2);
10
+ });
11
+ ```
12
+
13
+ - Further Reading:
14
+ - [List of Enforce rules](./n4s/rules)
15
+ - [Creating Custom Rules](./n4s/custom)
16
+ - [Shape and schema validation](./n4s/compound)
17
+ - [Enforce templates](./n4s/template)
18
+ - [Consuming external rules](./n4s/external)
@@ -0,0 +1,13 @@
1
+ # Enforce
2
+
3
+ Enforce is Vest's assertion library. It is used to validate values within, or outside of a Vest test.
4
+
5
+ ```js
6
+ import { enforce, test } from 'vest';
7
+
8
+ test('username', 'Must be at least three characters long', () => {
9
+ enforce(username).longerThan(2);
10
+ });
11
+ ```
12
+
13
+ - Further Reading:{{ENFORCE_DOCS}}
@@ -0,0 +1,128 @@
1
+ # Excluding and including tests
2
+
3
+ When performing validations in real world-scenarios, you may need to only run tests of a single field in your suite, or skip certain tests according to some logic. That's why Vest includes `skip()` and `only()`.
4
+
5
+ `skip()` and `only()` are functions that take a name of the test, or a list of names to either include or exclude fields from being validated. They should be called from the body of suite callback, and in order for them to take effect, they should be called before anything else.
6
+
7
+ !> **NOTE** When using `only()` or `skip()` you must place them before any of the tests defined in the suite. Hooks run in order of appearance, which means that if you place your `skip` hook after the field you're skipping - it won't have any effect.
8
+
9
+ ### Only running specific tests (including)
10
+
11
+ When validating upon user interactions, you will usually want to only validate the input the user currently interacts with to prevent errors appearing in unrelated places. For this, you can use `only()` with the name of the test currently being validated.
12
+
13
+ In the example below, we're assuming the argument `fieldName` is being populated with the name of the field we want to test. If none is passed, the call to `only` will be ignored, and all tests will run as usual. This allows us to test each field at a time during the interaction, but test all on form submission.
14
+
15
+ ```js
16
+ import { create, enforce, test, only } from 'vest';
17
+
18
+ const suite = create('New User', (data, fieldName) => {
19
+ only(fieldName);
20
+
21
+ test('username', 'Username is invalid', () => {
22
+ /* some validation logic*/
23
+ });
24
+ test('email', 'Email is invalid', () => {
25
+ /* some validation logic*/
26
+ });
27
+ test('password', 'Password is invalid', () => {
28
+ /* some validation logic*/
29
+ });
30
+ });
31
+
32
+ const validationResult = suite(formData, changedField);
33
+ ```
34
+
35
+ ### Skipping tests
36
+
37
+ There are not many cases for skipping tests, but they do exist. For example, when you wish to prevent validation of a promo code when none provided.
38
+
39
+ In this case, and in similar others, you can use `skip()`. When called, it will only skip the specified fields, all other tests will run as they should.
40
+
41
+ ```js
42
+ import { create, enforce, test, skip } from 'vest';
43
+
44
+ const suite = create('purchase', data => {
45
+ if (!data.promo) skip('promo');
46
+
47
+ // this test won't run when data.promo is falsy.
48
+ test('promo', 'Promo code is invalid', () => {
49
+ /* some validation logic*/
50
+ });
51
+ });
52
+
53
+ const validationResult = suite(formData);
54
+ ```
55
+
56
+ ## Conditionally excluding portions of the suite
57
+
58
+ In some cases we might need to skip a test or a group based on a given condition, for example - based on the intermediate state of the currently running suite. To allow this, can use `skipWhen`.
59
+
60
+ In the following example we're skipping the server side verification of the username if the username is invalid to begin with:
61
+
62
+ ```js
63
+ import { create, test, enforce, skipWhen } from 'vest';
64
+
65
+ const suite = create('user_form', (data = {}) => {
66
+ test('username', 'Username is required', () => {
67
+ enforce(data.username).isNotEmpty();
68
+ });
69
+
70
+ skipWhen(suite.get().hasErrors('username'), () => {
71
+ test('username', 'Username already exists', () => {
72
+ // this is an example for a server call
73
+ return doesUserExist(data.username);
74
+ });
75
+ });
76
+ });
77
+ export default suite;
78
+ ```
79
+
80
+ !> **Note** Using suite.get() within the suite runs returns a **DRAFT** result. This means that it may not contain the final validation result.
81
+
82
+ ## Including and excluding groups of tests
83
+
84
+ Similar to the way you use `skip` and `only` to include and exclude tests, you can use `skip.group` and `only.group` to exclude and include whole groups.
85
+
86
+ These two functions are very powerful and give you control of whole portions of your suite at once.
87
+
88
+ ```js
89
+ import { create, test, group, enforce, skip } from 'vest';
90
+
91
+ create('authentication_form', data => {
92
+ skip.group(data.userExists ? 'signUp' : 'signIn');
93
+
94
+ test('userName', "Can't be empty", () => {
95
+ enforce(data.username).isNotEmpty();
96
+ });
97
+ test('password', "Can't be empty", () => {
98
+ enforce(data.password).isNotEmpty();
99
+ });
100
+
101
+ group('signIn', () => {
102
+ test(
103
+ 'userName',
104
+ 'User not found. Please check if you typed it correctly.',
105
+ findUserName(data.username)
106
+ );
107
+ });
108
+
109
+ group('signUp', () => {
110
+ test('email', 'Email already registered', isEmailRegistered(data.email));
111
+
112
+ test('age', 'You must be at least 18 years old to join', () => {
113
+ enforce(data.age).largerThanOrEquals(18);
114
+ });
115
+ });
116
+ });
117
+ ```
118
+
119
+ ## Things to know about how these functions work:
120
+
121
+ **only.group()**:
122
+ When using `only.group`, other groups won't be tested - but top level tests that aren't nested in any groups will. The reasoning is that the top level space is a shared are that will always be executed. If you want only your group to run, nest everything else under groups as well.
123
+
124
+ If you combine `only.group` with `skip`, if you skip a field inside a group that is included, that field will be excluded during this run regardless of its group membership.
125
+
126
+ **skip.group()**
127
+
128
+ If you combine `skip.group` with `only` your included field declared within the skipped tests will be ignored.
@@ -0,0 +1,79 @@
1
+ # Installation
2
+
3
+ To install the stable version of Vest:
4
+
5
+ ```
6
+ npm install vest
7
+ ```
8
+
9
+ You can also add Vest directly as a script tag to your page:
10
+
11
+ ```html
12
+ <script src="https://unpkg.com/vest@3"></script>
13
+ ```
14
+
15
+ Vest tests are very much like unit tests, with only slight differences. Instead of using `describe/it/expect`, you will use `validate/[test](./test)/[enforce](./enforce)`.
16
+
17
+ - `test`: A single validation unit, validating a field or a single value. It takes the name of the field being validated, a failure message (to display to the user), and a callback function that contains the validation logic. [Read more about test].
18
+ - `enforce`: This is our assertion function. We’ll use it to make sure our validations pass. [Read more about enforce].
19
+
20
+ ## Writing tests
21
+
22
+ First, you need to initialize your validation suite using `create()`. This initializes your validation suite state and allows validation results to be merged with future validations.
23
+
24
+ ```js
25
+ import { create } from 'vest';
26
+
27
+ const suite = create('formName', () => {
28
+ // validation suite content goes here.
29
+ });
30
+
31
+ const validationResult = suite();
32
+ ```
33
+
34
+ `create()` takes the following arguments:
35
+
36
+ | Name | Type | Optional | Description |
37
+ | -------- | ---------- | -------- | -------------------------------------------------------------- |
38
+ | `name` | `string` | Yes | Suite name. |
39
+ | callback | `function` | No | Your validation suite's body. This is where your tests reside. |
40
+
41
+ `create` returns a "suite" function which runs your validation suite. All the arguments you pass to it are being forwarded to your tests callback. You can use it to pass form data to your validation, excluded fields, and anything required for during your validation runtime.
42
+
43
+ A simple validation suite would look somewhat like this:
44
+
45
+ ```js
46
+ // suite.js
47
+ import { create, test, enforce } from ‘vest’;
48
+
49
+ const suite = create('NewUserForm', (formData) => {
50
+     test('username', 'Must be between 2 and 10 chars', () => {
51
+         enforce(formData.username)
52
+             .longerThanOrEquals(2)
53
+             .shorterThan(10);
54
+     });
55
+
56
+     test('password', 'Must contain at least one digit', () => {
57
+         enforce(formData.password)
58
+             .matches(/(?=.*[0-9])/);
59
+     });
60
+ });
61
+
62
+ export default suite;
63
+ ```
64
+
65
+ ```js
66
+ // myFeature.js
67
+
68
+ import suite from './suite.js';
69
+
70
+ const res = suite(formData);
71
+ ```
72
+
73
+ In the above example, we validate a form called `NewUserForm` containing username and a password.
74
+
75
+ **Read next about:**
76
+
77
+ - [Vest's result object](./result).
78
+ - [Using the test function](./test).
79
+ - [Asserting with enforce](./enforce).