Avoid confusing JavaScript Mocha test bugs

The Problem

  1. You have a global this.fixture that you use as the default DOM for testing
  2. You have nested describe blocks that redefine this.fixture in their own beforeEach blocks for specific cases
  3. Your component attaches events to the DOM in the fixture (important!)
  4. You consistently tear down the test fixture in a global afterEach.
  5. Most of your tests pass except one which behaves unexplainably weird
  6. When you add a console.log to debug the problem you notice it gets called multiple times

Why?

Your global afterEach is only tearing down the default fixture as this in the describe blocks is a completely different object and so the nested this.fixture blocks don’t get torn down. Events attached to the DOM for these orphaned fixture prevent them from being garbage collected.

What’s the solution?

Always use a single global (highest containing scope) context variable so that all afterEach blocks can see and tear down the same fixture.

Examples

BAD:

describe('Whatever', function() {
  'use strict';

  beforeEach(function() {
    this.fixture = someDOMthing();
  });

  afterEach(function() {
    this.fixture.cleanupProperly();
    this.fixture = null;
  });

  describe('Test the thing', function() {
    beforeEach(function() {
      // !!!!!!!!!!!!!!! `this` is an entirely different object to
      // parent scope `this`
      this.fixture = someTestSpecificDOMthing();
    });

    // ...
  }

GOOD:

describe('Whatever', function() {
  'use strict';

  // Use the context from this scope throughout so all nested blocks
  // see the same objects
  var context = this;

  beforeEach(function() {
    context.fixture = someDOMthing();
  });

  afterEach(function() {
    context.fixture.cleanupProperly();
    context.fixture = null;
  });

  describe('Test the thing', function() {
    beforeEach(function() {
      context.fixture = someTestSpecificDOMthing();
    });

    // ...
  }

For background info see: http://stackoverflow.com/a/27575978/369171