lundi 1 août 2016

Unit testing for states in Meteor + React

I'm starting making unit tests in Meteor + React, I followed the simple todos tutorial from the Meteor page and started the Unit Testing React part from the Meteor documentation and also this tutorial which has a more developed todos list. So far I made some easy unit tests but I find quite difficult making one with states. In the official documentation from Meteor and the other tutorial that I've been reading, when making a UI test that simulates the changes of a state, both tutorials take another approach that I don't understand. I don't know how to simulate the change of state, I'm using mocha and ensyme, I'll explain were I'm lost with the code:

This is my App.test.jsx and I have no idea how properly call my toggle method in this test.

import { Meteor } from 'meteor/meteor';
import React from 'react';
import { shallow } from 'enzyme';
import { sinon } from 'meteor/practicalmeteor:sinon';
import { chai } from 'meteor/practicalmeteor:chai';
import App from './App.jsx';

describe('App', () => {
  if (Meteor.isServer) return;

  it ('should update status when checked', () => {
  // set up- I don't know how to call my toggleHideCompleted
  sinon.stub(toggleHideCompleted, 'call');
  const task = { text: 'test task checked', checked: true };
  const item = shallow(<App task={task} />);

  //exercise
  item.find('input[type="checkbox"]').simulate('change', {
    target: { checked: true },
  });

  //verify:
  sinon.assert.calledWith(toggleHideCompleted.call, {
   todoId: todo._id,
   toggleHideCompleted: true,
  });

  //teardown
  setCheckedStatus.call.restore();
 });
}); 

It obviously throws an error. This is the code from my App.jsx:

import ... more imports

class App extends Component {
  constructor(props) {
   super(props);
   this.state = {
    hideCompleted: false,
   };
  }

 toggleHideCompleted() {
   this.setState({
    hideCompleted: !this.state.hideCompleted,
   });
  }

 render() {
  return (
    <div className="container">
      <header>
        <h1>Todo List ({this.props.incompleteCount})</h1>

        <label className="hide-completed">
         <input
           type="checkbox"
           readOnly
           checked={this.state.hideCompleted}
           onClick={this.toggleHideCompleted.bind(this)}
          />
         Hide Completed Tasks
        </label>

        { this.props.currentUser ?
        <form className="new-task" onSubmit=   
        {this.handleSubmit.bind(this)} >
          <input
            type="text"
            ref="textInput"
            placeholder="Type to add new tasks"
          />
          </form> : ''
         }
      </header>
        <ul>
         {this.renderTasks()}
        </ul>
     </div>
   );
 }
}

And finally this are my methods:

import { check } from 'meteor/check';

export const Tasks = new Mongo.Collection('tasks');

if (Meteor.isServer) {
 Meteor.publish('tasks', function tasksPublication() {
 return Tasks.find({
   $or: [
     { private: { $ne: true } },
     { owner: this.userId },
    ],
   });
 });
} 
Meteor.methods({
'tasks.setChecked'(taskId, setChecked) {
   check(taskId, String);
   check(setChecked, Boolean);

   const task = Tasks.findOne(taskId);
   if (task.private && task.owner !== this.userId) {
     throw new Meteor.Error('not-authorized');
   }
   Tasks.update(taskId, { $set: { checked: setChecked } });
   },
 });

I hope someone could help me, I'm new in this unit testing stuff and a really need this for a bigger project.

Aucun commentaire:

Enregistrer un commentaire