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 🙏

© 2026 – Pkg Stats / Ryan Hefner

mocha-given

v0.4.0

Published

Adds a Given-When-Then DSL to mocha as an alternative style for specs

Readme

mocha-given

CI npm

Mocha-given is a mocha interface that helps you write cleaner specs using Given, When, Then and And. It is a shameless port of Justin Searls' jasmine-given which is a tribute to Jim Weirich's terrific rspec-given gem.

Zero dependencies. Works with mocha 8 through 11.

Install

$ npm install --save-dev mocha mocha-given

Run your specs with the interface set to mocha-given:

$ mocha --ui mocha-given

Example specs

JavaScript

describe('assigning stuff to this', function () {
  Given(function () { this.number = 24; });
  When(function () { this.number++; });
  And(function () { this.number *= 2; });
  Then(function () { return this.number === 50; });
});

describe('assigning stuff to variables', function () {
  let subject = null;
  Given(() => { subject = []; });
  When(() => { subject.push('foo'); });
  Then(() => subject.length === 1);
});

describe('Testing deferred', function () {
  Given(function () { this.t = Date.now(); });
  Then.after(1500, 'so much time has passed', function () {
    return Date.now() - this.t >= 1500;
  });
});

describe('Testing async', function () {
  Given(function () { this.subject = new User(); });
  Then('save user', function (done) { this.subject.save(done); });
});

CoffeeScript

describe 'assigning stuff to this', ->
	Given -> @number = 24
	When  -> @number++
	And   -> @number *= 2
	Then  -> @number == 50

describe 'assigning stuff to variables', ->
	subject = null
	Given -> subject = []
	When  -> subject.push('foo')
	Then  -> subject.length == 1

describe 'Testing deferred', ->
	Given -> @t = Date.now()
	Then.after 1500, 'so much time has passed', -> Date.now() - @t >= 1500

describe 'Testing async', ->
	Given -> @subject = new User()
	Then 'save user', (done) -> @subject.save(done);

CoffeeScript specs need the compiler registered yourself, which mocha-given no longer does for you:

$ mocha --ui mocha-given --require coffeescript/register --extension coffee

Arrow functions and this

Both styles below work, but they are not interchangeable.

State shared between Given, When and Then lives on mocha's test context, which you reach through this. Arrow functions do not bind this, and neither call nor apply can change that, so a spec that touches this must use a classic function:

Given(function () { this.number = 24; });     // writes to the test context
Then(function () { return this.number === 24; });

Given(() => { this.number = 24; });            // writes to module scope
Then(() => this.number === 24);                // reads module scope

The arrow version is worse than it looks. It often passes, because in CommonJS the module-level this is module.exports, so both arrows share one object. But that object is global to the file and is never reset between tests, so state leaks from one spec into the next:

describe('first', function () {
  Given(() => { this.n = 1; });
  Then(() => this.n === 1);        // passes
});
describe('second', function () {
  Then(() => this.n === 1);        // also passes, with no Given at all
});

Specs built on closure variables have no such constraint, and arrows read better there:

let subject = null;
Given(() => { subject = []; });
Then(() => subject.length === 0);

| Spec style | Use | | --- | --- | | this.foo shared state | function | | closure variables | arrow, or function |

And after Then

An And following a Then becomes part of that same spec, so the Given and When setup runs once for the whole group rather than once per assertion:

Given(function () { this.subject = expensiveSetup(); });
When(function () { this.result = this.subject.run(); });
Then(function () { return this.result.ok === true; });
And(function () { return this.result.items.length === 3; });
And(function () { return this.result.errors.length === 0; });

That is one test, one setup. Its title joins the assertions:

✔ then this.result.ok === true and this.result.items.length === 3 and this.result.errors.length === 0

Two separate Thens still run the setup twice, which is the distinction rspec-given and jasmine-given draw. Use And when several assertions describe one outcome, and a second Then when you want a fresh fixture.

And after a Given, When or Invariant is unchanged: it repeats that construct.

Promises

Given, When, Invariant and Then may all return a promise, and each step is awaited before the next one runs.

describe('loading a user', function () {
  Given('user', async () => fetchUser(1));
  When('name', function () { return this.user.name; });
  Then(function () { return this.name === 'Ada'; });
});

The named forms assign the resolved value, not the promise, so this.user above is the user object.

A Then that resolves to false fails, and a rejection fails with its own error. A step may take a done callback or return a promise, but not both.

API

| | | | --- | --- | | Given(fn) | Runs before each Then in scope. Sets up state | | Given(name, fn) | Assigns the return value to this[name] | | When(fn) | Runs after all Givens, immediately before each Then | | When(name, fn) | Assigns the return value to this[name] | | Then(fn) | A spec. Fails if fn returns false or throws | | Then(label, fn) | Same, with an explicit title | | Then.after(ms, label, fn) | Runs the assertion after a delay | | Then.only(...) | Runs only this spec | | And(fn) | Repeats whichever of Given, When or Invariant came last. After a Then it adds an assertion to that same spec | | Invariant(fn) | Asserted before every Then in scope |

A Then without a label takes its title from the source of the expression, so Then(() => this.sum === 5) reads as then this.sum === 5. Comments inside the function body end up in the title, so keep them above the call.

When an assertion fails, the comparison is reported with both sides evaluated:

1) then this.sum === 99:
   Error: return value is false
   Expected '5' to strictly equal '99'
   Comparison: this.sum === 99

Run tests programmatically

const Mocha = require('mocha');
const fs = require('fs');
const path = require('path');

// require mocha-given after Mocha is loaded
require('mocha-given');

const testDir = 'test';

const mocha = new Mocha({
  ui: 'mocha-given',
  reporter: 'spec',
});

fs.readdirSync(testDir)
  .filter((file) => /\.(coffee|js)$/.test(file))
  .forEach((file) => mocha.addFile(path.join(testDir, file)));

mocha.run((failures) => {
  process.exitCode = failures ? 1 : 0;
});

Contributing

$ npm install
$ npm test

npm test runs the JavaScript specs and then a small CoffeeScript spec that guards against breaking CoffeeScript users.

Credits

Thanks to SinnerSchrader for their support and the time to work on this project.

License

MIT