6

In my tutorial-like application I have a AddForm component:

var React = require('react');
var Input = require('react-bootstrap').Input;
var TeamActions = require('../actions/team_actions.js');

var AddForm = React.createClass({
  handleFormSubmit: function(e) {
    e.preventDefault();

    var name = this._trimmedValue(this.refs.name);
    var rating = this._trimmedValue(this.refs.rating);

    if (name && rating) {
      TeamActions.addTeam(
        {name: name, rating: rating}
      );
      this._clearField(this.refs.name);
      this._clearField(this.refs.rating);
    }
  },

  _trimmedValue: function(field) {
    return field.getInputDOMNode().value.trim();
  },

  _clearField: function(field) {
    field.getInputDOMNode().value = '';
  },

  render: function() {
    return (
        <form onSubmit={this.handleFormSubmit}>
          <Input label="Name" type="text" placeholder="Name" ref="name" />
          <Input label="Rating" type="text" placeholder="Rating" ref="rating" />
          <Input bsStyle="primary" type="submit" value="Add!" />
        </form>
    );
  }
})

module.exports = AddForm;

TeamActions:

var McFly = require('mcfly');
var Flux = new McFly();
var TeamConstants = require('../constants/team_constants.js');


var TeamActions = Flux.createActions({
  addTeam: function(team) {
    return {
      actionType: TeamConstants.ADD_TEAM,
      team: team
    }
  }
});

module.exports = TeamActions;

As you can see, I'm using McFly and React-Bootstrap here.

Now I want to test it, using jest.

I would like to have following test cases:

1) if someone tries to submit a form with empty inputs, nothing should happen (to be more specific - there should be no interaction on TeamActions mock)

2) if one submits a form with valid name and rating, then there should be a proper call to TeamActions mock

3) if one submits a form with valid name and rating, then name and rating inputs should be cleaned.

How do I test it? Should I access the DOM somehow, using react's TestUtils?

Should I somehow simulate form submission? If so, how do I do that?

And last thing - my AddForm depends on TeamActions. By writing:

jest.dontMock('../add_form.js');

is jest instructed to mock all those dependencies (react, react-bootstrap, team_actions) or should I somehow mock TeamActions myself?

// edit:

Because someone said I asked too much quuestions in one topic, to be more specific:

How can I simulate a form submission with specific payload, using TestUtils? Do I need to mock TeamActions myself or is is mocked for me automatically?

3
  • Can you simplify this to be a specific question? There are multiple issues and each is too broad for a good easily digestible StackOverflow answer. Commented Feb 22, 2015 at 16:26
  • Sure, will edit in a second. Commented Feb 22, 2015 at 16:29
  • @WiredPrairie I've edited my question. To be honest, I see one big issue with main topic 'how do I test it?'. And a proper code snippet will solve all my problems. But I tried to be more specific anyway. Commented Feb 22, 2015 at 16:40

1 Answer 1

5

React TestUtils allows you to simulate form submission:

var addForm = TestUtils.renderIntoDocument(AddForm(null));
var form = TestUtils.findRenderedDOMComponentWithTag(addForm, 'form');
TestUtils.Simulate.submit(form);

The way I would test the actions is by manually mocking out addTeam. Before simulating anything in the test, do something like:

var TeamActions = require('../actions/team_actions');
TeamActions.addTeam = jest.genMockFn();
/* then simulate submission... */
expect(TeamActions.addTeam).toBeCalledWith({name: 'name', rating: 'rating'});

For testing the input values, just use the refs.

addForm.refs.name.getDOMNode().value = 'Some Name';
/* perform some action that should clear input */
expect(addForm.refs.name.getDOMNode().value).toEqual('');

edit

To answer your edited question, it looks like you actually don't need to manually mock addTeam; I just tried it out and it seems like Jest figured out how to mock the McFly actions.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you. It works, but it's quite ugly. Isn't there a way of submit a form with parameters? I mean, something like TestUtils.Simulate.submit method, which takes a json as a parameter?
All the TestUtils,Simulate.{event} methods allow you to pass your own mock-event as the second parameter, so I think you could theoretically do something like: TestUtils.Simulate.submit(addForm, { target: [{value: 'name'}, {value: 'rating'}] })
Still kinda ugly, though. :-/ Usually when I have this type of situation I just allow the values to be specified as optional component props.
Did you try the approach with additional parameter? Looks a little bit better than this ugly playing with DOMNode values. Optionally, I could provide a method on my component, which allows to fulfill form, but I don't like this approach.
The problem with additional parameter approach is that I think you'd have to change handleFormSubmit to get the values from the event object rather than the refs, so you're making the app code a lot uglier for the sake of the tests. Personally, I'd just stick with the refs or the TestUtils helpers for finding DOM nodes. If somebody has a more elegant approach, I'd love to hear it, though.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.