Skip to content

Commit

Permalink
patch: add skipWhen for forward compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
ealush committed Oct 16, 2021
1 parent 6996d73 commit c2964e0
Show file tree
Hide file tree
Showing 14 changed files with 66 additions and 35 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Vest tries to remediate this by separating validation logic from feature logic s
## Example code ([Run in sandbox](https://codesandbox.io/s/vest-react-tutorial-finished-ztt8t?file=/src/validate.js))

```js
import { create, only, test, enforce, warn } from 'vest';
import { create, only, test, enforce, warn, skipWhen } from 'vest';

This comment has been minimized.

Copy link
@marconi1992

marconi1992 Dec 16, 2021

Hey @ealush I guess it should be a minor version upgrade 3.3.0, using add instead of patch in the commit message to make it work with the semantic releasing tool

This comment has been minimized.

Copy link
@ealush

ealush via email Dec 16, 2021

Author Owner

export default create('user_form', (data = {}, currentField) => {
only(currentField);
Expand All @@ -88,11 +88,11 @@ export default create('user_form', (data = {}, currentField) => {
enforce(data.password).matches(/[0-9]/);
});

if (data.password) {
skipWhen(!data.password, () => {
test('confirm_password', 'Passwords do not match', () => {
enforce(data.confirm_password).equals(data.password);
});
}
});

test('email', 'Email Address is not valid', () => {
enforce(data.email).isEmail();
Expand Down
1 change: 1 addition & 0 deletions jsconfig.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions packages/vest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Vest tries to remediate this by separating validation logic from feature logic s
## Example code ([Run in sandbox](https://codesandbox.io/s/vest-react-tutorial-finished-ztt8t?file=/src/validate.js))

```js
import { create, only, test, enforce, warn } from 'vest';
import { create, only, test, enforce, warn, skipWhen } from 'vest';

export default create('user_form', (data = {}, currentField) => {
only(currentField);
Expand All @@ -88,11 +88,11 @@ export default create('user_form', (data = {}, currentField) => {
enforce(data.password).matches(/[0-9]/);
});

if (data.password) {
skipWhen(!data.password, () => {
test('confirm_password', 'Passwords do not match', () => {
enforce(data.confirm_password).equals(data.password);
});
}
});

test('email', 'Email Address is not valid', () => {
enforce(data.email).isEmail();
Expand Down
6 changes: 3 additions & 3 deletions packages/vest/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Vest tries to remediate this by separating validation logic from feature logic s
## Example code ([Run in sandbox](https://codesandbox.io/s/vest-react-tutorial-finished-ztt8t?file=/src/validate.js))

```js
import { create, only, test, enforce, warn } from 'vest';
import { create, only, test, enforce, warn, skipWhen } from 'vest';

export default create('user_form', (data = {}, currentField) => {
only(currentField);
Expand All @@ -88,11 +88,11 @@ export default create('user_form', (data = {}, currentField) => {
enforce(data.password).matches(/[0-9]/);
});

if (data.password) {
skipWhen(!data.password, () => {
test('confirm_password', 'Passwords do not match', () => {
enforce(data.confirm_password).equals(data.password);
});
}
});

test('email', 'Email Address is not valid', () => {
enforce(data.email).isEmail();
Expand Down
18 changes: 9 additions & 9 deletions packages/vest/docs/cross_field_validations.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,44 +36,44 @@ export default create('form_name', (data = {}) => {
});
```

## if/else for conditionally skipping fields
## skipWhen for conditionally skipping fields

If your field depends on a different field's existence or a different simple condition, you could use a basic if/else statement.
If your field depends on a different field's existence or a different simple condition, you could use skipWhen.
In the following example I only validate `confirm` if password is not empty:

DEMO: https://codesandbox.io/s/demo-forked-z2ur9?file=/src/validate.js

```js
import { create, test, enforce } from 'vest';
import { create, test, enforce, skipWhen } from 'vest';
export default create('user_form', (data = {}) => {
test('password', 'Password is required', () => {
enforce(data.password).isNotEmpty();
});
if (data.password) {
skipWhen(!data.password, () => {
test('confirm', 'Passwords do not match', () => {
enforce(data.confirm).equals(data.password);
});
}
});
});
```

## if/else for conditionally skipping field based on a previous result
## skipWhen for conditionally skipping field based on a previous result

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.

This requires using the function created from create():

```js
import { create, test, enforce } from 'vest';
import { create, test, enforce, skipWhen } from 'vest';
const suite = create('user_form', (data = {}) => {
test('password', 'Password is required', () => {
enforce(data.password).isNotEmpty();
});
if (!suite.get().hasErrors('password')) {
skipWhen(suite.get().hasErrors('password'), () => {
test('password', 'Password is weak', () => {
enforce(data.password).longerThan(8);
});
}
});
});
export default suite;
```
8 changes: 4 additions & 4 deletions packages/vest/docs/exclusion.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,24 +55,24 @@ const validationResult = suite(formData);

## Conditionally excluding portions of the suite

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 an if statement.
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`.

In the following example we're skipping the server side verification of the username if the username is invalid to begin with:

```js
import { create, test, enforce } from 'vest';
import { create, test, enforce, skipWhen } from 'vest';

const suite = create('user_form', (data = {}) => {
test('username', 'Username is required', () => {
enforce(data.username).isNotEmpty();
});

if (!suite.get().hasErrors('username')) {
skipWhen(suite.get().hasErrors('username'), () => {
test('username', 'Username already exists', () => {
// this is an example for a server call
return doesUserExist(data.username);
});
}
});
});
export default suite;
```
Expand Down
4 changes: 2 additions & 2 deletions packages/vest/docs/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ const suite = vest.create('user_form', () => {

```js
const suite = create('user_form', () => {
if (suite.get().hasErrors('username')) {
skipWhen(suite.get().hasErrors('username'), () => {
/* ... */
}
});
});
```

Expand Down
10 changes: 5 additions & 5 deletions packages/vest/docs/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ This can be useful when running async validations on the server, or when you do
`promisify()` accepts a validation suite declaration, and returns a function that when called, returns a Promise.

```js
import { create, test } from 'vest';
import { create, test, skipWhen } from 'vest';
import promisify from 'vest/promisify';

const suite = promisify(
Expand All @@ -94,12 +94,12 @@ const suite = promisify(
);

suite(data).then(res => {
if (res.hasErrors('email')) {
skipWhen(res.hasErrors('email'), () => {
/* ... */
}
});

if (res.hasErrors('username')) {
skipWhen(res.hasErrors('username'), () => {
/* ... */
}
});
});
```
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ Object {
"only": [Function],
"optional": [Function],
"skip": [Function],
"skipWhen": [Function],
"test": [Function],
"warn": [Function],
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('Stateful behavior', () => {
});

describe('more complex', () => {
const { test, enforce, create } = vest;
const { test, enforce, create, skipWhen } = vest;

const data = {};

Expand Down Expand Up @@ -104,11 +104,11 @@ describe('more complex', () => {
enforce(data.password).isNotEmpty();
});

if (!suite.get().hasErrors('password')) {
skipWhen(suite.get().hasErrors('password'), () => {
test('confirm', 'passwords do not match', () => {
enforce(data.confirm).equals(data.password);
});
}
});
});
});

Expand Down
1 change: 1 addition & 0 deletions packages/vest/src/hooks/hooks.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { only, skip } from 'exclusive';
export { default as skipWhen } from 'skipWhen'
export { default as warn } from 'warn';
export { default as group } from 'group';
export { default as optional } from 'optionalTests';
15 changes: 15 additions & 0 deletions packages/vest/src/hooks/skipWhen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import isFunction from 'isFunction';
import { isFalsy } from 'isTruthy';
import optionalFunctionValue from 'optionalFunctionValue';

// This function by itself doesn't do much, and is only a wrapper around
// an if statement. The reason for it is to support version 4 api in version 3
// so that someone reading the latest docs can still run the code.

export default function skipWhen(conditional, callback) {
if (isFalsy(optionalFunctionValue(conditional))) {
if (isFunction(callback)) {
callback();
}
}
}
3 changes: 2 additions & 1 deletion packages/vest/src/vest.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import create from 'createSuite';
import enforce from 'enforce';
import { only, skip, warn, group, optional } from 'hooks';
import { only, skip, warn, group, optional, skipWhen } from 'hooks';
import test from 'test';

const VERSION = __LIB_VERSION__;
Expand All @@ -13,6 +13,7 @@ export default {
only,
optional,
skip,
skipWhen,
test,
warn,
};
16 changes: 14 additions & 2 deletions packages/vest/src/vest.mjs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import create from 'createSuite';
import enforce from 'enforce';
import { only, skip, warn, group, optional } from 'hooks';
import { only, skip, warn, group, optional, skipWhen } from 'hooks';
import test from 'test';

const VERSION = __LIB_VERSION__;
Expand All @@ -13,8 +13,20 @@ export default {
only,
optional,
skip,
skipWhen,
test,
warn,
};

export { VERSION, create, enforce, group, only, optional, skip, test, warn };
export {
VERSION,
create,
enforce,
group,
only,
optional,
skip,
skipWhen,
test,
warn,
};

0 comments on commit c2964e0

Please sign in to comment.