npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

labbable

v2.1.2

Published

No-fuss hapi server testing

Readme

labbable

No-fuss hapi server testing

Build Status Coverage Status

Lead Maintainer - Devin Ivy

Note

Under hapi v17+ and async/await, labbable no longer provides much utility and is deprecated until any further needs arise surrounding hapi testing. It is suggested that your server entrypoint export a function that asynchronously returns a hapi server and starts/initializes the server as is appropriate. For a full-fledged example, see this server and this corresponding test.

Here is a simple example just for illustrative purposes.

server.js

const Hapi = require('hapi');

exports.deployment = async (start) => {

    const server = Hapi.server();

    await server.initialize();

    if (!start) {
        return server;
    }

    await server.start();

    console.log('Server started');

    return server;
};

if (!module.parent) {
    exports.deployment(true).catch(console.error);
}

test/index.js


// Load modules

const Code = require('code');
const Lab = require('lab');
const Server = require('../server');

// Test shortcuts

const { describe, it } = exports.lab = Lab.script();
const { expect } = Code;

describe('Deployment', () => {

    it('returns a server.', async () => {

        const server = await Server.deployment();

        expect(server.route).to.be.a.function();
    });
});

Introduction

It can be a pain to get your hapi server into your tests, especially when using otherwise wonderful tools such as glue. Labbable makes this process very simple, and encourages the best practice of testing an initialized (but not started) hapi server.

Why initialize the server for tests?

Plugin dependencies are only enforced at the time of server initialization. This means code that relies on a plugin being present (typically by the after callback of server.dependency(deps, after) will only run during initialization. And if there are any dependencies missing, those errors will surface only during initialization. Your server's caches will also be started and onPreStart server extensions will run.

Should you so desire, labbable can also pass an uninitialized server into your tests using options for labbable.ready().

Usage

See also the API Reference

Directly (as plugin)

In this case the server is immediately available and can be placed in module.exports. Registering the Labbable.plugin hapi plugin adds a server decoration server.labbableReady() that can be used in a test to guarantee the server is initialized.

server.js

const Hapi = require('hapi');
const Labbable = require('labbable');

// Step 1.
// Simply export your server
const server = module.exports = new Hapi.Server();

server.connection();

// Step 2.
// Register the labbable plugin plus any others
server.register([Labbable.plugin], (err) => {

    if (err) {
        throw err;
    }

    // Step 3.
    // Initialize your server
    server.initialize((err) => {

        if (err) {
            throw err;
        }

        // Don't continue to start server if module
        // is being require()'d (likely in a test)
        if (module.parent) {
            return;
        }

        server.start((err) => {

            if (err) {
                throw err;
            }

            console.log('Server started');
        });
    });
});

test/index.js

const Code = require('code');
const Lab = require('lab');
const MyServer = require('../server.js');

const lab = exports.lab = Lab.script();
const describe = lab.describe;
const before = lab.before;
const it = lab.it;
const expect = Code.expect;

describe('My server', () => {

    const server = MyServer;

    before((done) => {

        // Callback fires once the server is initialized
        // or immediately if the server is already initialized
        server.labbableReady((err) => {

            if (err) {
                return done(err);
            }

            return done();
        });
    });

    // server is now available to be tested
    it('initializes.', (done) => {

        // server.isInitialized() can be used to check the server's init state
        expect(server.isInitialized()).to.equal(true);
        done();
    });
});

With glue

In this case the server is composed by glue then made available asynchronously, so it can't be exported as in the previous example.

Instead we export an instance lababble of Labbable, then call labbable.using(server) as soon as the server is available. The method labbable.ready() can then be used in a test to get a hold of server once it's initialized.

server.js

const Glue = require('glue');
const Labbable = require('labbable');

// Step 1.
// Make an instance of Labbable
// to which we can pass the server
const labbable = module.exports = new Labbable();
const manifest = {/* ... */};

Glue.compose(manifest, (err, server) => {

    if (err) {
        throw err;
    }

    // Step 2.
    // Show the server to our instance of labbable
    labbable.using(server);

    // Step 3.
    // Initialize your server
    server.initialize((err) => {

        if (err) {
            throw err;
        }

        // Don't continue to start server if module
        // is being require()'d (likely in a test)
        if (module.parent) {
            return;
        }

        server.start((err) => {

            if (err) {
                throw err;
            }

            console.log('Server started');
        });
    });
});

test/index.js

const Code = require('code');
const Lab = require('lab');
const LabbableServer = require('../server.js');

const lab = exports.lab = Lab.script();
const describe = lab.describe;
const before = lab.before;
const it = lab.it;
const expect = Code.expect;

describe('My server', () => {

    let server;

    before((done) => {

        // Callback fires once the server is initialized
        // or immediately if the server is already initialized
        LabbableServer.ready((err, srv) => {

            if (err) {
                return done(err);
            }

            server = srv;

            return done();
        });
    });

    // server is now available to be tested
    it('initializes.', (done) => {

        expect(server).to.exist();

        // isInitialized() can be used to check the server's init state
        expect(LabbableServer.isInitialized()).to.equal(true);
        done();
    });
});