Repository: jquense/yup
Pull request #910 (2020-05-25 20:42:31)

add `isTrue` and `isFalse` checks on boolean
This resolves https://github.com/jquense/yup/issues/904 :) 


Patch:
diff --git a/README.md b/README.md
index e637630..27f1cee 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,7 @@ Yup's API is heavily inspired by [Joi](https://github.com/hapijs/joi), but leane
 <!-- START doctoc generated TOC please keep comment here to allow auto update -->
 <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
 
+
 - [Install](#install)
 - [Usage](#usage)
   - [Using a custom locale dictionary](#using-a-custom-locale-dictionary)
@@ -37,10 +38,10 @@ Yup's API is heavily inspired by [Joi](https://github.com/hapijs/joi), but leane
     - [`mixed.strip(stripField: boolean = true): Schema`](#mixedstripstripfield-boolean--true-schema)
     - [`mixed.withMutation(builder: (current: Schema) => void): void`](#mixedwithmutationbuilder-current-schema--void-void)
     - [`mixed.default(value: any): Schema`](#mixeddefaultvalue-any-schema)
-    - [`mixed.default(): Any`](#mixeddefault-any)
+    - [`mixed.getDefault(options?: object): Any`](#mixedgetdefaultoptions-object-any)
     - [`mixed.nullable(isNullable: boolean = true): Schema`](#mixednullableisnullable-boolean--true-schema)
     - [`mixed.required(message?: string | function): Schema`](#mixedrequiredmessage-string--function-schema)
-    - [`mixed.notRequired(): Schema`](#mixednotrequired-schema)
+    - [`mixed.notRequired(): Schema` Alias: `optional()`](#mixednotrequired-schema-alias-optional)
     - [`mixed.defined(): Schema`](#mixeddefined-schema)
     - [`mixed.typeError(message: string): Schema`](#mixedtypeerrormessage-string-schema)
     - [`mixed.oneOf(arrayOfValues: Array<any>, message?: string | function): Schema` Alias: `equals`](#mixedoneofarrayofvalues-arrayany-message-string--function-schema-alias-equals)
@@ -79,7 +80,7 @@ Yup's API is heavily inspired by [Joi](https://github.com/hapijs/joi), but leane
     - [`date.max(limit: Date | string | Ref, message?: string | function): Schema`](#datemaxlimit-date--string--ref-message-string--function-schema)
   - [array](#array)
     - [`array.of(type: Schema): Schema`](#arrayoftype-schema-schema)
-    - [`array.required(message?: string | function): Schema`](#arrayrequiredmessage-string--function-schema)
+    - [`array.length(length: number | Ref, message?: string | function): Schema`](#arraylengthlength-number--ref-message-string--function-schema)
     - [`array.min(limit: number | Ref, message?: string | function): Schema`](#arrayminlimit-number--ref-message-string--function-schema)
     - [`array.max(limit: number | Ref, message?: string | function): Schema`](#arraymaxlimit-number--ref-message-string--function-schema)
     - [`array.ensure(): Schema`](#arrayensure-schema)
@@ -87,6 +88,8 @@ Yup's API is heavily inspired by [Joi](https://github.com/hapijs/joi), but leane
   - [object](#object)
     - [Object schema defaults](#object-schema-defaults)
     - [`object.shape(fields: object, noSortEdges?: Array<[string, string]>): Schema`](#objectshapefields-object-nosortedges-arraystring-string-schema)
+    - [`object.pick(keys: string[]): Schema`](#objectpickkeys-string-schema)
+    - [`object.omit(keys: string[]): Schema`](#objectomitkeys-string-schema)
     - [`object.from(fromKey: string, toKey: string, alias: boolean = false): Schema`](#objectfromfromkey-string-tokey-string-alias-boolean--false-schema)
     - [`object.noUnknown(onlyKnownKeys: boolean = true, message?: string | function): Schema`](#objectnounknownonlyknownkeys-boolean--true-message-string--function-schema)
     - [`object.camelCase(): Schema`](#objectcamelcase-schema)
diff --git a/src/boolean.js b/src/boolean.js
index a886fa7..481a5d7 100644
--- a/src/boolean.js
+++ b/src/boolean.js
@@ -1,5 +1,7 @@
 import inherits from './util/inherits';
 import MixedSchema from './mixed';
+import { boolean as locale } from './locale';
+import isAbsent from './util/isAbsent';
 
 export default BooleanSchema;
 
@@ -25,4 +27,28 @@ inherits(BooleanSchema, MixedSchema, {
 
     return typeof v === 'boolean';
   },
+
+  isTrue(message = locale.isValue) {
+    return this.test({
+      message,
+      name: 'is-value',
+      exclusive: true,
+      params: { value: 'true' },
+      test(value) {
+        return isAbsent(value) || value === true;
+      },
+    });
+  },
+
+  isFalse(message = locale.isValue) {
+    return this.test({
+      message,
+      name: 'is-value',
+      exclusive: true,
+      params: { value: 'false' },
+      test(value) {
+        return isAbsent(value) || value === false;
+      },
+    });
+  },
 });
diff --git a/src/locale.js b/src/locale.js
index 2fdbe80..fc5144a 100644
--- a/src/locale.js
+++ b/src/locale.js
@@ -52,7 +52,9 @@ export let date = {
   max: '${path} field must be at earlier than ${max}',
 };
 
-export let boolean = {};
+export let boolean = {
+  isValue: '${path} field must be ${value}',
+};
 
 export let object = {
   noUnknown: '${path} field has unspecified keys: ${unknown}',


Test patch:
diff --git a/src/util/runTests.js b/src/util/runTests.js
index fd8b193..cf0c47b 100644
--- a/src/util/runTests.js
+++ b/src/util/runTests.js
@@ -7,11 +7,14 @@ export default function runTests(options, cb) {
   let callback = once(cb);
   let count = tests.length;
 
-  if (!count) return callback(null, value);
-
   const nestedErrors = [];
   errors = errors ? errors : [];
 
+  if (!count)
+    return errors.length
+      ? callback(new ValidationError(errors, value, path))
+      : callback(null, value);
+
   for (let i = 0; i < tests.length; i++) {
     const test = tests[i];
 
diff --git a/test/bool.js b/test/bool.js
index ca27567..fc9fd86 100644
--- a/test/bool.js
+++ b/test/bool.js
@@ -56,4 +56,34 @@ describe('Boolean types', () => {
         }),
     ]);
   });
+
+  it('should check isTrue correctly', () => {
+    return Promise.all([
+      bool()
+        .isTrue()
+        .isValid(true)
+        .should.eventually()
+        .equal(true),
+      bool()
+        .isTrue()
+        .isValid(false)
+        .should.eventually()
+        .equal(false),
+    ]);
+  });
+
+  it('should check isFalse correctly', () => {
+    return Promise.all([
+      bool()
+        .isFalse()
+        .isValid(false)
+        .should.eventually()
+        .equal(true),
+      bool()
+        .isFalse()
+        .isValid(true)
+        .should.eventually()
+        .equal(false),
+    ]);
+  });
 });