Browse Source

Add error predicate (#27)

iss58
Sam Verschueren 7 years ago
committed by Sindre Sorhus
parent
commit
f8b3191125
  1. 8
      source/index.ts
  2. 109
      source/lib/predicates/error.ts
  3. 83
      source/test/error.ts

8
source/index.ts

@ -5,6 +5,7 @@ import {NumberPredicate} from './lib/predicates/number';
import {BooleanPredicate} from './lib/predicates/boolean';
import {ArrayPredicate} from './lib/predicates/array';
import {DatePredicate} from './lib/predicates/date';
import {ErrorPredicate} from './lib/predicates/error';
export interface Ow {
(value: any, predicate: Predicate): void;
@ -40,6 +41,10 @@ export interface Ow {
* Test the value to be a Date.
*/
date: DatePredicate;
/**
* Test the value to be an Error.
*/
error: ErrorPredicate;
}
const main = (value: any, predicate: Predicate) => {
@ -75,6 +80,9 @@ Object.defineProperties(main, {
},
date: {
get: () => new DatePredicate()
},
error: {
get: () => new ErrorPredicate()
}
});

109
source/lib/predicates/error.ts

@ -0,0 +1,109 @@
import {Predicate, Context} from './predicate';
export class ErrorPredicate extends Predicate<Error> {
constructor(context?: Context) {
super('error', context);
}
/**
* Test an error to have a specific name.
*
* @param expected Expected name of the Error.
*/
name(expected: string) {
return this.addValidator({
message: error => `Expected error to have name \`${expected}\`, got \`${error.name}\``,
validator: error => error.name === expected
});
}
/**
* Test an error to have a specific message.
*
* @param expected Expected message of the Error.
*/
message(expected: string) {
return this.addValidator({
message: error => `Expected error message to be \`${expected}\`, got \`${error.message}\``,
validator: error => error.message === expected
});
}
/**
* Test the error message to include a specific message.
*
* @param message Message that should be included in the error.
*/
messageIncludes(message: string) {
return this.addValidator({
message: error => `Expected error message to include \`${message}\`, got \`${error.message}\``,
validator: error => error.message.includes(message)
});
}
/**
* Test the error object to have specific keys.
*
* @param keys One or more keys which should be part of the error object.
*/
hasKeys(...keys: string[]) {
return this.addValidator({
message: () => `Expected error message to have keys \`${keys.join('`, `')}\``,
validator: error => keys.every(key => error.hasOwnProperty(key))
});
}
/**
* Test an error to be of a specific instance type.
*
* @param instance The expected instance type of the error.
*/
instanceOf(instance: any) {
return this.addValidator({
message: error => `Expected \`${error.name}\` to be of type \`${instance.name}\``,
validator: error => error instanceof instance
});
}
/**
* Test an Error to be a TypeError.
*/
get typeError() {
return this.instanceOf(TypeError);
}
/**
* Test an Error to be an EvalError.
*/
get evalError() {
return this.instanceOf(EvalError);
}
/**
* Test an Error to be a RangeError.
*/
get rangeError() {
return this.instanceOf(RangeError);
}
/**
* Test an Error to be a ReferenceError.
*/
get referenceError() {
return this.instanceOf(ReferenceError);
}
/**
* Test an Error to be a SyntaxError.
*/
get syntaxError() {
return this.instanceOf(SyntaxError);
}
/**
* Test an Error to be a URIError.
*/
get uriError() {
return this.instanceOf(URIError);
}
}

83
source/test/error.ts

@ -0,0 +1,83 @@
import test from 'ava';
import m from '..';
class CustomError extends Error {
constructor(message: string) {
super(message);
this.name = 'CustomError';
}
}
test('error', t => {
t.notThrows(() => m(new Error('foo'), m.error));
t.throws(() => m('12', m.error), 'Expected argument to be of type `error` but received type `string`');
});
test('error.name', t => {
t.notThrows(() => m(new Error('foo'), m.error.name('Error')));
t.notThrows(() => m(new CustomError('foo'), m.error.name('CustomError')));
t.throws(() => m(new CustomError('foo'), m.error.name('Error')), 'Expected error to have name `Error`, got `CustomError`');
});
test('error.message', t => {
t.notThrows(() => m(new Error('foo'), m.error.message('foo')));
t.notThrows(() => m(new CustomError('bar'), m.error.message('bar')));
t.throws(() => m(new CustomError('foo'), m.error.message('bar')), 'Expected error message to be `bar`, got `foo`');
});
test('error.messageIncludes', t => {
t.notThrows(() => m(new Error('foo bar'), m.error.messageIncludes('foo')));
t.notThrows(() => m(new Error('foo bar'), m.error.messageIncludes('o')));
t.notThrows(() => m(new CustomError('foo bar'), m.error.messageIncludes('bar')));
t.throws(() => m(new CustomError('foo bar'), m.error.messageIncludes('unicorn')), 'Expected error message to include `unicorn`, got `foo bar`');
});
test('error.hasKeys', t => {
const err: any = new Error('foo');
err.unicorn = '🦄';
err.rainbow = '🌈';
t.notThrows(() => m(err, m.error.hasKeys('unicorn')));
t.notThrows(() => m(err, m.error.hasKeys('unicorn', 'rainbow')));
t.throws(() => m(err, m.error.hasKeys('foo')), 'Expected error message to have keys `foo`');
t.throws(() => m(err, m.error.hasKeys('unicorn', 'foo')), 'Expected error message to have keys `unicorn`, `foo`');
});
test('error.instanceOf', t => {
t.notThrows(() => m(new CustomError('foo'), m.error.instanceOf(CustomError)));
t.notThrows(() => m(new CustomError('foo'), m.error.instanceOf(Error)));
t.notThrows(() => m(new TypeError('foo'), m.error.instanceOf(Error)));
t.notThrows(() => m(new Error('foo'), m.error.instanceOf(Error)));
t.throws(() => m(new Error('foo'), m.error.instanceOf(CustomError)), 'Expected `Error` to be of type `CustomError`');
t.throws(() => m(new TypeError('foo'), m.error.instanceOf(EvalError)), 'Expected `TypeError` to be of type `EvalError`');
});
test('error.typeError', t => {
t.notThrows(() => m(new TypeError('foo'), m.error.typeError));
t.throws(() => m(new Error('foo'), m.error.typeError), 'Expected `Error` to be of type `TypeError`');
});
test('error.evalError', t => {
t.notThrows(() => m(new EvalError('foo'), m.error.evalError));
t.throws(() => m(new Error('foo'), m.error.evalError), 'Expected `Error` to be of type `EvalError`');
});
test('error.rangeError', t => {
t.notThrows(() => m(new RangeError('foo'), m.error.rangeError));
t.throws(() => m(new EvalError('foo'), m.error.rangeError), 'Expected `EvalError` to be of type `RangeError`');
});
test('error.referenceError', t => {
t.notThrows(() => m(new ReferenceError('foo'), m.error.referenceError));
t.throws(() => m(new Error('foo'), m.error.referenceError), 'Expected `Error` to be of type `ReferenceError`');
});
test('error.syntaxError', t => {
t.notThrows(() => m(new SyntaxError('foo'), m.error.syntaxError));
t.throws(() => m(new Error('foo'), m.error.syntaxError), 'Expected `Error` to be of type `SyntaxError`');
});
test('error.uriError', t => {
t.notThrows(() => m(new URIError('foo'), m.error.uriError));
t.throws(() => m(new Error('foo'), m.error.uriError), 'Expected `Error` to be of type `URIError`');
});
Loading…
Cancel
Save