Unexpected is designed to be highly extensible with new data types, assertions, output styles and themes.

Here's a partial list of plugins for Unexpected:


The recommended way to get plugins is installing them via npm:

$ npm install unexpected-dom

And then in your test suite:

var expect = require('unexpected').clone()

For plugins that work in the browser, you'll either need to add an extra <script>, or use browserify or a script loader instead of the Common.js require in the above example. Please consult the documentation for each individual plugin.

Caveats with plugins that depend on other plugins

The unexpected-express, unexpected-mitm, and unexpected-http plugins all depend on unexpected-messy being available. If you use more than one of these in the same test suite, it's important that only one version of unexpected-messy is installed.

All three plugins list unexpected-messy under both peerDependencies and dependencies in their package.json. This strategy is carefully thought out to be forward compatible with how peerDependencies work with npm 3. Unfortunately, users of npm 1 and 2 will sometimes be in for a bit of a rough ride.

Unexpected's use method will throw an error if you install two different versions of unexpected-messy, so there's a stop gap that prevents expect from ending up in a broken state. Still, recovering from that error condition or an EPEERINVALID error can be tricky. We recommend trying the following:

  1. Upgrade to npm 3, then remove the node_modules folder and run a fresh npm install.
  2. If you're stuck on a previous npm version, you should still try to remove node_modules and run a fresh npm install.
  3. If that doesn't work, upgrade unexpected and the plugins you're using to the newest versions at once. The newest versions should be using the same version of unexpected-messy, which will resolve the problem in most cases.

Mixing plugins

All of these plugins should be able coexist in the same Unexpected instance and compose well together. For instance, you can grab a few and assert that an express app serves an HTML response body that contains a yellow <div>:

var expect = require('unexpected').clone()
var app = require('express')()
    .get('/myPage', function (req, res, next) {
        res.send('<html><body><div style="color: #ff0">Hey!</div></body></html>');
it('should deliver something pretty', function () {
    return expect(app, 'to yield exchange', {
        request: 'GET /myPage',
        response: {
            headers: { 'Content-Type': 'text/html; charset=utf-8' },
            body:'when parsed as HTML', 'queried for first', 'div', 'to satisfy', {
                attributes: {
                    style: {
                        color:'to be colored', 'yellow')

Or you could assert that a node.js readable stream outputs an image that's at most 10% different from a reference image:

var expect = require('unexpected').clone()
it('should spew out the expected image', function () {
    var myStream = require('fs').createReadStream('foo.png');
    return expect(
        'to yield output satisfying','to resemble', 'bar.png', {
            mismatchPercentage:'to be less than', 10)
        }).and('to have metadata satisfying', {
            format: 'PNG'
Fork me on GitHub