node package manager

Introducing npm Enterprise add-ons. Integrate third-party dev tools into npm…

expectacle

A simple, sanely-syntaxed expectation library.

Expectacle

Expectacle is a simple expectation library with a sane syntax.

Expectacle can be used in the browser, on NodeJS and on any CommonJS environment that supports Modules/1.1.

Download expectacle.js and include it with a script tag:

<script type="text/javascript" src="/path/to/expectacle.js"></script>
<script type="text/javascript">
// window.expect();
</script> 

Expectacle is available on NPM:

$ npm install expectacle

You can then require it in your tests:

var expect = require('expectacle');

Download expectacle.js and use require:

var expect = require('./path/to/expectacle').expect;

Expectacle has one main function called expect, that is used to create a new expectation. It takes in one argument, the value of the expectation, which could be of any JavaScript type.

expect(1);

An expectation can then be tested using matchers. A matcher is a function that performs checks on the value of the expectation using zero or one arguments. It then returns either true or false depending on whether the value passes the check. If a matcher returns false, the expectation fails and an error is thrown.

expect(1).toBe(1); // passes, no error. 
expect(2).toBe(1); // fails, throws an ExpectationError. 

All expectations have a corresponding reversed expectation that can be accessed using the not member. This expectation has the same matchers as a regular expectations, but perform reversed tests with the matchers: the matcher returns false for success and true for failures.

expect(1).not.toBe(2); // passes, no error. 
expect(1).not.toBe(1); // fails, throws an ExpectationError. 

Expectacle comes with the following matchers by default:

The identity matcher checks whether the expectation's value is identical to the passed value. It uses the === operator internally, and therefore disregards any type casting rules.

The equality matcher checks whether the expectation's value is equal to the passed value. It uses the == operator internally, and therefore coerces types.

Checks whether the expected value is similar to the passed value. It uses a deep-comparison of keys and properties for objects.

Checks whether a function expected value throws an error.

This matcher can be used without passing the error argument, in which case the matcher only checks if the expected value throws.

Optionally, one could pass an error argument that could either be a string, a regular expression or a constructor function:

  • If the error argument is a string, the error argument is compared against the message of the expected value's thrown error.
  • If the error argument is a regular expression, the message of the expected value's thrown error is tested against the error argument.
  • If the error argument is a constructor function, the name property of the expected value's thrown error is compared against the name value of the constructor function's prototype.

Checks whether the expected value's string representation matches the passed regularExpression argument.

Checks whether the expected value is of the passed length.

This matcher uses the length property if it is available (e.g., in strings, arrays, arguments and any object that has a length property). If the expected value is an object without a length property, this matcher check the number of keys (i.e., member/property names).

Checks whether the expected value is empty.

This matcher uses the length property if it is available (e.g., in strings, arrays, arguments and any object that has a length property). If the expected value is an object without a length property, this matcher check the number of keys (i.e., member/property names).

Checks whether the expected value has a member (i.e., property or method) with a name corresponding to the passed argument.

Matches like toHaveMember, but disregards any inherited members.

Checks whether the expected value has a property (i.e., non-function member) with a name corresponding to the passed argument.

Matches like toHaveProperty, but disregards any inherited properties.

Checks whether the expected value has a method (i.e., function member) with a name corresponding to the passed argument.

Matches like toHaveMember, but disregards any inherited methods.

Checks whether the expectation's value is an instance of the the passed constructor argument. Will throw an ExpectationError if the passed constructor argument is not a function.

Checks whether the expectation's value has the type corresponding to the passed typeString.

This function is implemented using Object.prototype.toString to get the type's string representation. The following typeStrings are pre-populated: 'arguments', 'array', 'boolean', 'date', 'function','null', 'number', 'object', 'regexp', 'string', 'undefined'.

Checks whether the expected value is a boolean.

Checks whether the expected value is an array.

Checks whether the expected value is a function.

Checks whether the expected value is a number.

Checks whether the expected value is an object (but not an array).

Checks whether the expected value is a string.

Checks whether the expected value is null.

Checks whether the expected value is undefined.

Checks whether the expected value is NaN.

Checks whether the expected value is true.

Checks whether the expected value is false.

Checks whether the expected value is truthy (i.e., coerces as a boolean true value).

Checks whether the expected value is falsy (i.e., coerces as a boolean false value).

Checks whether the expected object has a particular shape. See the "Shapes" section below.

Shapes are a way to verify the structure of the expected value in your tests, without verifying the actual value.

You can use the toHaveShape() method, passing it a shape:

expect({
  str: 'something',
  num: 1,
  bool: true
}).toHaveShape({
  str: expect.shape.String(),
  num: expect.shape.Number(),
  bool: expect.shape.Boolean()
});

Shapes are not just limited to objects. You can check the shape of an array as well:

// Check that all array members are of a particular type: 
expect([1, 2, 3]).toHaveShape(expect.shape.Array(expect.shape.Number()));
 
// Check that array members match particular shapes: 
expect([1, 'string', {key: 'name'}]).toHaveShape(expect.shape.LiteralArray([
  expect.shape.Number(),
  expect.shape.String(),
  {key: expect.shape.String()}
]));

All built-in shapes are available via expect.shape.

Checks the expected value is of type "arguments".

When provided with a shape, checks whether the expected value is an array, each element of which has the provided shape.

If no shape is provided, it only checks that the expected value is an array.

Checks the expected value is of type "boolean".

Checks the expected value is of type "date".

Checks the expected value is of type "function".

Checks that the expected value is equal (===) to the given value.

Checks that each item in the expected array value corresponds to the shape in the same index in the provided shapesArray.

Checks the expected value is of type "null".

Checks the expected value is of type "number".

If an object shapeDescriptor is provided, checks if the expected object value's properties are of the shape of the corresponding shapeDescriptor.

If no shapeDescriptor is provided, it simply checks if the expected value is an object.

Checks the expected value is of type "regexp".

Checks the expected value is of type "string".

Checks the expected value is of type "undefined".

You can add a custom matcher function using the expect.addMatcher function:

expect.addMatcher(name, matcherFunction);

A matcherFunction is a function that receives two arguments and returns a boolean. The first argument is the expected value (i.e., the value passed to the expect function), and the second argument is the value passed to the matcher function when called (which can be empty; more on that in a bit).

expect.addMatcher('toStartWith', function(expected, prefix) {
  if (prefix == expect.NULL_VALUE || !prefix) {
    expect.fail('toStartWith requires a prefix argument.'); // throw an error 
  }
  return expected.toString().indexOf(prefix) == 0;
});
 
expect('hello').toStartWith('he'); // passes. 
expect('hello').not.toStartWith('he'); // fails; throws an error. 
expect('hello').toStartWith(); // fails; throws an error because no prefix. 

The matcherFunction must return true if the expected value passes the check and false if it doesn't. Expectacle handles throwing the function automatically, so a simple boolean return value will suffice. The addMatcher function also creates a reversed matcher automatically.

In cases where the user of the matcher does not provide an argument to the matcher, a special value expect.NULL_VALUE is passed to the matcher instead. This is done in order to distinguish when the user passes values like undefined and null or when they just fail to provide an argument entirely.

The function expect.typeOf can be used to get the type of a value. This function is used internally by the default matchers.

The function expect.fail can be used to raise an ExpectationError. It takes one argument, which is used as the error message.

Copyright 2015, Mark "Keeto" Obcena. Released under an MIT-Style License.