1

I'm working on a React app with Reflux and I'm having a problem connecting a store to a component.

Here's the code

// src/stores/post.js
var Reflux = require('reflux');
var $ = require('jquery');
var PostActions = require('../actions/post');

module.exports = Reflux.createStore({
  init: function() {
    this.listenTo(PostActions.vote, this.onVote);
  },

  getInitialData: function() {
    return {
      title: "Post 1",
      content: "This is a post!",
      voteCount: 6
    }
  },

  onVote: function(postId, studentId, voteValue) {
    this.trigger();
    console.log("VOTE ACTION TRIGGERED");
  }
});

// src/actions/post.js
var Reflux = require('reflux');

module.exports = Reflux.createActions([
  "vote"
]);

// src/components/posts/upvote.js
var React = require('react');
var Reflux = require('reflux');
var PostStore = require('../../stores/post');
var PostActions = require('../../actions/post');

module.exports = React.createClass({
  mixins: [Reflux.ListenerMixin],

  getInitialState: function() {
    return {
      voteCount: this.props.votes
    }
  },

  componentDidMount: function() {
    this.listenTo(PostStore, this.onVoteCountChange);
  },

  componentWillUnmount: function() {
    this.unsubscribe();
  },

  onVoteCountChange: function(newVoteCount) {
    this.setState({
      voteCount: newVoteCount
    });
  },

  handleClick: function() {
    console.log(PostActions);
    PostActions.vote(
      null, null, null
    );
  },

  render: function() {
    return (
      <div className="votes">
        <p>{this.state.voteCount}</p>

        <span className="glyphicon glyphicon-chevron-up"
          onClick={this.handleClick}></span>
      </div>
    )
  }
});

The problem is, the code works when I run it in the Node console:

> var PostStore = require('./src/stores/post');
undefined
> var PostActions = require('./src/actions/post');
undefined
> PostActions.vote(null, null, null);
undefined
> VOTE ACTION TRIGGERED

But when I run the tests, the event doesn't get logged. However, I know the click is happening because handleClick() is being called and the PostActions object is being printed to the console.

The PostStore is also being initialized (I had a console.log() in there to verify it). This leads me to believe that somehow the problem is in the React component, but as far as I can tell my code looks exactly like what's in the Reflux documentation.

Also, as an aside, is there a better way for me to debug my code during the Jest tests than with a bunch of console.log() calls thrown everywhere? Something like binding.pry in ruby?

EDIT: I'm including the tests:

jest.dontMock('../../../src/components/posts/upvote');
jest.dontMock('../../../src/actions/post.js');
jest.dontMock('../../../src/stores/post.js');

describe('Upvote', function() {
  var React = require('react/addons');
  var Upvote = require('../../../src/components/posts/upvote');
  var TestUtils = React.addons.TestUtils;
  var upvote;

  beforeEach(function() {
    upvote = TestUtils.renderIntoDocument(
      <Upvote postId="1" votes="6"/>
    );
  });

  it('should display the correct upvote count', function() {
    var votes = TestUtils.findRenderedDOMComponentWithTag(
      upvote, "p"
    ).getDOMNode().textContent;

    expect(votes).toEqual("6");
  });

  it('should handle upvote clicks', function() {
    var upArrow = TestUtils.findRenderedDOMComponentWithTag(
      upvote, "span"
    ).getDOMNode();

    TestUtils.Simulate.click(upArrow);

    // var votes = TestUtils.findRenderedDOMComponentWithTag(
    //   upvote, "p"
    // ).getDOMNode().textContent;

    // expect(votes).toEqual("7");
  });
});
Hugo
  • 2,186
  • 8
  • 28
  • 44
  • Could you post your tests? My initial guess is that Jest is auto-mocking your store. It would still initialize as you say, but every method would be mocked and essentially do nothing. – ginman Feb 12 '15 at 22:21
  • @ginman Will do, but I added calls to `jest.dontMock()` for the actions and the stores. I'll post it anyways though. – Hugo Feb 12 '15 at 22:24

1 Answers1

2

So as it turns out, I had two problems. The first one was that reflux was being mocked automatically. The second had to do with actions and timers, and I found the solution here.

I'm gonna post my code anyways:

// gulpfile.js

// the config is used for gulp-jest
var jestConfig = {
  "scriptPreprocessor": "./helpers/jsx-preprocessor.js", // relative to gulp.src
  "unmockedModulePathPatterns": [
    "../node_modules/react",
    "../node_modules/reflux" // this is where reflux gets unmocked
  ]
}

// __tests__/upvote.js

it('should handle upvote clicks', function() {
  var upArrow = TestUtils.findRenderedDOMComponentWithTag(
    upvote, "span"
  ).getDOMNode();

  TestUtils.Simulate.click(upArrow);

  jest.runAllTimers(); // this is where the magic happens

  var votes = TestUtils.findRenderedDOMComponentWithTag(
    upvote, "p"
  ).getDOMNode().textContent;

  expect(votes).toEqual("7");
});
Hugo
  • 2,186
  • 8
  • 28
  • 44