How do I factor out common before() calls with mocha?

I have a lot of duplication in my mocha tests:

describe("Some test", function() {
    before(helpers.testPrepare);
    beforeEach(helpers.freshDB);

    it("should foo", function(done) {
        //...
        done();
    });

    after(helpers.teardownServer);
});

describe("Another test", function() {
    before(helpers.testPrepare);
    beforeEach(helpers.freshDB);

    it("should bar", function(done) {
        //...
        done();
    });

    after(helpers.teardownServer);
});

This could cause problems if I forget to call beforeEach and it's a pain to refactor. I'd like to define a describe that ensures I always call my setup and teardown, so I can just write:

I would like to write this as:

var describe = require('./helpers').describe;

describe("Some test", function() {
    it("should foo", function(done) {
        //...
        done();
    });
});

How can I do this, since mocha is defining describe as a global? How do I ensure everything is executed in the right order?

You can compose describe blocks within each other. So now you can do . . .

describe('Database Tests', function () {
  before(helpers.testPrepare);
  beforeEach(helpers.freshDB);

  describe('Some test', function () {
   it('should foo', function (done) {
    done();
   });
  });

  describe('Another test', function () {
   it('should bar', function (done) {
     done();
   });
  });
});

EDIT: In regards to your comment you might try creating a module as such.

harness.js
module.exports.beforeHooks = function () {
 before(hlepers.testPrepare);
 beforeEach(helpers.freshDB);
}

and then do this ...

var harness = require('./harness.js');
describe('Database Tests', function () {
  harness.beforeHooks();

It might not work because the scoping is all messed up, but if that's the case you can pass those functions in your beforeHooks functions.

module.exports.beforeHooks(before, beforeEach)

and call it like before, but pass those functions in as objects like so.

harness.beforeHooks(before, beforeEach);

I would create a helpers.js file that contains this:

function beforeEachExample() { console.log("before each"); }

function beforeExample() { console.log("before"); }

function afterExample() { console.log("after"); }

function makeSuite(desc, cb) {
    describe(desc, function () {
        before(beforeExample);
        beforeEach(beforeEachExample);

        cb();

        after(afterExample);
    });
}

exports.makeSuite = makeSuite;

And then I could have test/something.js:

var makeSuite = require("../helpers").makeSuite;

makeSuite("something", function () {
    it("one", function () {});
    it("two", function () {});
});

And test/somethingelse.js:

var makeSuite = require("../helpers").makeSuite;

makeSuite("something else", function () {
    it("one", function () {});
    it("two", function () {});
});

Running the setup above gives:

$ mocha

  something
before
before each
    ✓ one 
before each
    ✓ two 
after

  something else
before
before each
    ✓ one 
before each
    ✓ two 
after

  4 passing (5ms)

If you want to run the same set of before/beforeEach hooks before EVERY TEST in your test suite, then you can declare these hooks at the global level, outside of any describe block.

// test/support/init.js
before(helpers.testPrepare);
beforeEach(helpers.freshDB);
after(helpers.teardownServer);

// test/mocha.opts
-r ./test/support/init.js

// test/some.test.js
describe("Some test", function() {
  it("should foo", function(done) {
    //...
    done();
  });
});

// test/another.test.js
describe("Another test", function() {
  it("should bar", function(done) {
    //...
    done();
  });
});

If you want to call the setup in a selected subset of tests only, then you can implement your helper method as follows:

helpers.describe = function decoratedDescribe(name, fn) {
  global.describe(name, function() {
    before(helpers.testPrepare);
    beforeEach(helpers.freshDB);
    after(helpers.teardownServer);

    fn();
  });
};

// test/some.test.js
var describe = require('./helpers').describe;
describe("Some test", function() {
  it("should foo", function(done) {
    //...
    done();
  });
});

Remember, all Node.js code is wrapped in a function when it's loaded by require(), thus var describe creates a local variable shadowing the global variable provided by Mocha.

The obvious downside of this solution is that nested describe blocks will add all your hooks again, which is almost certainly not what you want. In which case I am advising you to keep the original describe provided by Mocha and store your custom implementation under a different name.

// test/some.test.js
var describeWithSetup = require('./helpers').describe;
describeWithSetup("Some test", function() {
  describe("some context", function() {
    it("should foo", function(done) {
      //...
      done();
    });
  });
});