diff --git a/.travis.yml b/.travis.yml index 5917fb86..a565d613 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ cache: notifications: email: false node_js: + - '10' - '9' - '8' - '6' diff --git a/spec/predicates/isArray.spec.ts b/spec/predicates/isArray.spec.ts index 62bb0027..a87c2429 100644 --- a/spec/predicates/isArray.spec.ts +++ b/spec/predicates/isArray.spec.ts @@ -27,7 +27,7 @@ describe('predicates', () => { {}, false, 5, - ).it('complains if the value is not an array and provides', (value: any) => { + ).it('complains if the value is not an array', (value: any) => { expect(() => new Strings(value)).to.throw(`Collection should be an array`); }); }); diff --git a/spec/predicates/isBoolean.spec.ts b/spec/predicates/isBoolean.spec.ts new file mode 100644 index 00000000..1c59d8d8 --- /dev/null +++ b/spec/predicates/isBoolean.spec.ts @@ -0,0 +1,34 @@ +import 'mocha'; +import { given } from 'mocha-testdata'; + +import { ensure, isBoolean, TinyType } from '../../src'; +import { expect } from '../expect'; + +describe('predicates', () => { + + /** @test {isBoolean} */ + describe('::isBoolean', () => { + + class MarketingOptIn extends TinyType { + constructor(public readonly value: boolean) { + super(); + + ensure('MarketingOptIn', value, isBoolean()); + } + } + + it('ensures that the argument is a boolean value', () => { + expect(new MarketingOptIn(false)).to.not.throw; // tslint:disable-line:no-unused-expression + }); + + given( + undefined, + null, + {}, + 'string', + 5, + ).it('complains if the value is not a boolean', (value: any) => { + expect(() => new MarketingOptIn(value)).to.throw(`MarketingOptIn should be a boolean value`); + }); + }); +}); diff --git a/spec/predicates/isNumber.spec.ts b/spec/predicates/isNumber.spec.ts new file mode 100644 index 00000000..8e9fee0a --- /dev/null +++ b/spec/predicates/isNumber.spec.ts @@ -0,0 +1,44 @@ +import 'mocha'; +import { given } from 'mocha-testdata'; + +import { ensure, isNumber, TinyType } from '../../src'; +import { expect } from '../expect'; + +describe('predicates', () => { + + /** @test {isNumber} */ + describe('::isNumber', () => { + class Percentage extends TinyType { + constructor(public readonly value: number) { + super(); + + ensure('Percentage', value, isNumber()); + } + } + + it('ensures that the argument in a number', () => { + expect(new Percentage(42)).to.not.throw; // tslint:disable-line:no-unused-expression + }); + + given( + 1 / 3, + 0.42, + 0o3, + 0xB4D455, + NaN, + Infinity, + -Infinity, + ).it('works for any type of number', (value: any) => { + expect(() => new Percentage(value)).to.not.throw; // tslint:disable-line:no-unused-expression + }); + + given( + undefined, + null, + {}, + 'string', + ).it('complains if the value is not a number', (value: any) => { + expect(() => new Percentage(value)).to.throw(`Percentage should be a number`); + }); + }); +}); diff --git a/spec/predicates/isString.spec.ts b/spec/predicates/isString.spec.ts new file mode 100644 index 00000000..3786f979 --- /dev/null +++ b/spec/predicates/isString.spec.ts @@ -0,0 +1,33 @@ +import 'mocha'; +import { given } from 'mocha-testdata'; + +import { ensure, isString, TinyType } from '../../src'; +import { expect } from '../expect'; + +describe('predicates', () => { + + /** @test {isString} */ + describe('::isString', () => { + class FirstName extends TinyType { + constructor(public readonly value: string) { + super(); + + ensure('FirstName', value, isString()); + } + } + + it('ensures that the argument in a string', () => { + expect(new FirstName('Jan')).to.not.throw; // tslint:disable-line:no-unused-expression + }); + + given( + undefined, + null, + {}, + [], + 42, + ).it('complains if the value is not a string', (value: any) => { + expect(() => new FirstName(value)).to.throw(`FirstName should be a string`); + }); + }); +}); diff --git a/src/predicates/index.ts b/src/predicates/index.ts index ac601a3a..28443b37 100644 --- a/src/predicates/index.ts +++ b/src/predicates/index.ts @@ -1,6 +1,7 @@ export * from './and'; export * from './hasLengthOf'; export * from './isArray'; +export * from './isBoolean'; export * from './isDefined'; export * from './isEqualTo'; export * from './isGreaterThan'; @@ -9,6 +10,8 @@ export * from './isInRange'; export * from './isInteger'; export * from './isLessThan'; export * from './isLessThanOrEqualTo'; +export * from './isNumber'; export * from './isOneOf'; +export * from './isString'; export * from './or'; export * from './Predicate'; diff --git a/src/predicates/isBoolean.ts b/src/predicates/isBoolean.ts new file mode 100644 index 00000000..fd23c837 --- /dev/null +++ b/src/predicates/isBoolean.ts @@ -0,0 +1,19 @@ +import { Predicate } from './Predicate'; + +/** + * @desc Ensures that the `value` is a {@link Boolean} value. + * + * @example + * import { ensure, isBoolean, TinyType } from 'tiny-types'; + * + * class MarketingOptIn extends TinyType { + * constructor(public readonly value: boolean) { + * ensure('MarketingOptIn', value, isBoolean()); + * } + * } + * + * @returns {Predicate} + */ +export function isBoolean(): Predicate { + return Predicate.to(`be a boolean value`, (value: boolean) => typeof value === 'boolean'); +} diff --git a/src/predicates/isNumber.ts b/src/predicates/isNumber.ts new file mode 100644 index 00000000..dc77456c --- /dev/null +++ b/src/predicates/isNumber.ts @@ -0,0 +1,19 @@ +import { Predicate } from './Predicate'; + +/** + * @desc Ensures that the `value` is a {@link Number}. + * + * @example + * import { ensure, isNumber, TinyType } from 'tiny-types'; + * + * class Percentage extends TinyType { + * constructor(public readonly value: number) { + * ensure('Percentage', value, isNumber()); + * } + * } + * + * @returns {Predicate} + */ +export function isNumber(): Predicate { + return Predicate.to(`be a number`, (value: number) => typeof value === 'number'); +} diff --git a/src/predicates/isString.ts b/src/predicates/isString.ts new file mode 100644 index 00000000..56c92444 --- /dev/null +++ b/src/predicates/isString.ts @@ -0,0 +1,19 @@ +import { Predicate } from './Predicate'; + +/** + * @desc Ensures that the `value` is an integer {@link Number}. + * + * @example + * import { ensure, isString, TinyType } from 'tiny-types'; + * + * class FirstName extends TinyType { + * constructor(public readonly value: string) { + * ensure('FirstName', value, isString()); + * } + * } + * + * @returns {Predicate} + */ +export function isString(): Predicate { + return Predicate.to(`be a string`, (value: string) => typeof value === 'string'); +}