From 494cc40994927f5b53762c51273465c5e2346260 Mon Sep 17 00:00:00 2001 From: Sam Verschueren Date: Wed, 1 Nov 2017 15:37:27 +0100 Subject: [PATCH] Add `not` predicate (#12) --- source/lib/operators/not.ts | 22 ++++++++++++++++++++++ source/lib/predicates/predicate.ts | 9 +++++++++ source/test/test.ts | 9 +++++++++ 3 files changed, 40 insertions(+) create mode 100644 source/lib/operators/not.ts create mode 100644 source/test/test.ts diff --git a/source/lib/operators/not.ts b/source/lib/operators/not.ts new file mode 100644 index 0000000..aac1982 --- /dev/null +++ b/source/lib/operators/not.ts @@ -0,0 +1,22 @@ +import { Predicate, Validator, validatorSymbol } from '../predicates/predicate'; + +/** + * Operator which inverts all the validations. + * + * @param predictate Predicate to wrap inside the operator. + */ +export const not = (predicate: T) => { + predicate['addValidator'] = (validator: Validator) => { // tslint:disable-line:no-string-literal + const fn = validator.validator; + const message = validator.message; + + validator.message = (x: any) => `[NOT] ${message(x)}`; + validator.validator = (x: any) => !fn(x); + + predicate[validatorSymbol].push(validator); + + return predicate; + }; + + return predicate; +}; diff --git a/source/lib/predicates/predicate.ts b/source/lib/predicates/predicate.ts index e647259..030ae19 100644 --- a/source/lib/predicates/predicate.ts +++ b/source/lib/predicates/predicate.ts @@ -1,4 +1,5 @@ import * as is from '@sindresorhus/is'; +import { not } from '../operators/not'; export interface Validator { message(value: T): string; @@ -12,6 +13,7 @@ export interface Context { export const validatorSymbol = Symbol('validators'); export abstract class Predicate { + constructor( type: string, private context: Context = { validators: [] } @@ -26,6 +28,13 @@ export abstract class Predicate { return this.context.validators; } + /** + * Invert the following validators. + */ + get not() { + return not(this); + } + /** * Register a new validator. * diff --git a/source/test/test.ts b/source/test/test.ts new file mode 100644 index 0000000..3802497 --- /dev/null +++ b/source/test/test.ts @@ -0,0 +1,9 @@ +import test from 'ava'; +import * as m from '..'; + +test('not', t => { + t.notThrows(() => m(1, m.number.not.infinite)); + t.notThrows(() => m(1, m.number.not.infinite.greaterThan(5))); + t.notThrows(() => m('foo!', m.string.not.alphanumeric)); + t.throws(() => m('', m.string.not.empty), '[NOT] Expected string to be empty, got ``'); +});