0

When running tests on stores with karma & jasmine (instead of jest), the store's state persists between tests. What's the best way to reset the state for every test?

With jest, every test is run in its own environment automatically. This post includes instructions for how to clear the require cache between tests for karma (copied below) to imitate jest, but I can't seem to get it to work.

//tests.webpack.js (suggested by linked article, modified to match my project structure)
// Create a Webpack require context so we can dynamically require our
// project's modules. Exclude test files in this context.
'use strict';

var projectContext = require.context('./path/to/js', true, /^(?!\.test).js$/);
// Extract the module ids that Webpack uses to track modules.
var projectModuleIds = projectContext.keys().map(function (module) {
  return String(projectContext.resolve(module));
});

beforeEach(function () {
  // Remove our modules from the require cache before each test case.
  projectModuleIds.forEach(function (id) {
    return delete require.cache[id];
  });
});

My current file:

tests.webpack.js (current)
var context = require.context('./path/to/js', true, /\.test\.js$/);
context.keys().forEach(context);

Not sure if it helps, but here's a simplified version of the code from my tests that shows the store's state persisting between tests.

MissionStore.test.js
describe('MissionStore', function() {

  beforeEach(function() {
    this.MissionStore = rewire("./MissionStore");
    this.registeredCallback = this.MissionStore.__get__("registeredCallback");
  });

  // A bunch of initialization tests without data
  describe("set data", function(){
    beforeEach(function(){
        // Sets this.MissionStore.getMissions() to some sample data
        this.registeredCallback(fetchMissions); 
    });

    it('modifies mission data', function(){
        var mission = this.MissionStore.getMissions()[0];
        expect(mission.edit).not.toEqual(true);

        // modify mission to add an edit flag = true
        this.registeredCallback({
            actionType: MissionConstants.MISSION_TOGGLE_EDIT_FLAG,
            mission : mission
        });

        expect(this.MissionStore.getMissions()[0].edit).toEqual(true);
    });

    it('do something else', function(){
        expect(this.MissionStore.getMissions()[0].edit).not.toEqual(true); // Failing test
        console.log(this.MissionStore.getMissions()[0]);

        // prints {..., edit: true}
    });
  });
});

In the 'do something else' test, I'm expecting the this.MissionStore state to be reset between tests so edit won't be equal to true anymore. How would I go about doing this?

Michelle Tilley
  • 157,729
  • 40
  • 374
  • 311
Andrew Cross
  • 1,921
  • 2
  • 19
  • 32

1 Answers1

1

Your /^(?!\.test).js$/ RegExp supposed to match every file ending with .js but not with .test.js is wrong, it will only ever match .js. It should be /^(?!.*\.test\.js$).*\.js$/. See Negative lookahead Regular Expression.

So my guess is that projectModuleIds is empty, and that you are not invalidating anything between require calls.

Community
  • 1
  • 1
Alexandre Kirszenberg
  • 35,938
  • 10
  • 88
  • 72
  • You're right about the RegExp being wrong, although that's not what was causing the stores not to be reset. Turns out modifying the mission data in the store with the edit = true flag was modifying fetchMission data (it was passed by reference). Hence when it was run again it was forcing the edit = true flag everywhere. Thanks for your help though! – Andrew Cross Apr 23 '15 at 16:48