Testing guide article

Would love to see a PR to the testing guide to fix this!

Thatā€™s exactly the reason why I held off doing chimp testing on my boilerplate code.

Letā€™s say Iā€™m writing a unit test for a Blaze component based on the section A Simple Unit Test in the guide, using the withRenderedTemplate() helper from the test-helpers.js provided in that section.

Letā€™s also say my component has some internal state that I want to write an assertion against (the example test only shows how to write assertions against the rendered DOM result).

In other words, Iā€™m trying to get a hold of the componentā€™s state (or at least its Template instance) from the callback inside the withRenderedTemplate() helper.

I tried multiple different ways, including passing a callback that is called (using this.autorun()) whenever the internal state that I want to observe has changed.

For the sake of staying close to the example, letā€™s imagine I want to write a test in which I assert that onEditingChange() is actually called. So I want to trigger the 'focus event on the <input> and then ensure the callback is called.

How would I accomplish that?

EDIT: Hereā€™s some code for what I am trying to accomplish:

  it('calls onEditingChange when input is focused', function (done) {
    const todo = Factory.build('todo');
    const data = {
      todo,
      editing: true,
      onEditingChange: (state) => {
        // ensure `onEditingChange` is called
        chai.assert.equal(state, true);
        done();
      },
    };

    withRenderedTemplate('Todos_item', data, el => {
      // find input and place focus on it
      $(el).find('input[type=text]').focus();
    });
  });

And the result:

That looks conceptually pretty good. Itā€™s not clear to me whatā€™s going wrong. Is the callback ever called? Does this line of code run when you do $(..).focus()?

I cannot run tests in CircleCI because the package dispatch:mocha-phantomjs recommended in the guide is throwingerrors when I try to run them:

? MochaRunner.runServerTests: Starting server side tests with run id Q67uyntpZBJ4izAkC
I20160603-00:03:15.383(2)? ClientServerReporter.constructor: Missing reporter to run tests. Use MochaRunner.setReporter(reporter) to set one.
I20160603-00:03:15.383(2)?
I20160603-00:03:15.383(2)?   phantomjs://code/phantomjsScript.js:15 in onError
I20160603-00:03:15.384(2)?     http://localhost:3000/packages/dispatch_mocha-phantomjs.js?hash=019974c286d86870150433903c12317cf464f435: 258
I20160603-00:03:15.384(2)?
I20160603-00:03:15.384(2)?   phantomjs://code/phantomjsScript.js:17
I20160603-00:03:15.529(2)? All client and server tests finished!

Iā€™ve seen that there are some tickets in github, but I want to ask: Has anybody solved that?

EDIT:

I also get this error when removing practicalmeteor:mocha
meteor test --once --driver-package dispatch:mocha-phantomjs returned exit code 130

Thanks for the response @tmeasday.

Actually, this is not the real test I am having trouble with. I just adapted the example from the guide to something that I thought was equivalent. I have gotten a similar test to work.

The one I havenā€™t gotten to work relies on a callback that takes longer to trigger than .focus() (i.e. thereā€™s a network request involved). My guess about why it wonā€™t work is that the withRenderedTemplate() helper uses the callback in a synchronous manner, and does ends up removing the rendered view before the callback returns.

I guess Iā€™ll just have to try and rewrite that helper to support asynchronous callbacks as wellā€¦

1 Like

And publish it as a package? Would love to remove that custom code from Todos!

@tmeasday great idea! My first thought when I saw the helper in this article was ā€œwhy isnā€™t there a package with some premade helpers for this?ā€

1 Like

@tmeasday Maybe you can help me with this:

I have a Blaze component and Iā€™m testing it as described in this article, using the withRenderedTemplate helper.

Letā€™s say I want to write a test for a method Iā€™ve attached to the template instance (in Template.name.onCreated). I canā€™t for the life of me figure out how to get hold of the Template instance that was rendered.

As it is, the helper calls the callback only with the DOM element that the template was rendered into, but not the instance. Iā€™ve spent an hour reading the docs and trying different things, but I canā€™t seem to get the template instance from either the el or Blaze.renderWithData.

What am I missing here?

const view = Blaze.renderWithData(...);
const templateInstance = view.templateInstance();

@Sanjo I tried that. Iā€™m getting TypeError: view.templateInstance is not a function.

Iā€™m using Meteor v1.3.3.

Hmm, probably the result of renderWithData is the data view rather than the template.

Maybe you could try something like:

const parentView = View.With(data, function() {});
const templateView = Blaze.render(template, ..., parentView);

You might have to play around with it (and thereā€™s probably a better way to do it!)

Probably a good thing to include in the helper lib :wink:

Is it possible to use ā€œmocha --grepā€ in meteor test cli? It is so useful for TDD

@tmeasday

Hi guys, I feel like I am incredibly late to the party here so sorry for raising this from the depths butā€¦

I am unable to work out how to set a Reactive Var in a Mocha Unit test for Blaze.

Use case:

I want to test that my ā€œEditā€ and ā€œDeleteā€ buttons are appearing when I click an ā€œEdit My Casesā€ button (button#editAllCases), which uses a Reactive Var to determine the state.

Relevant View Code:

[....]

Template.Cases.onCreated(function() {
  this.editModeCases = new ReactiveVar(false);
  Meteor.subscribe('cases');
});

Template.Cases.events({
  'click #editAllCases, click #cancelEditMode'(event, template) {
    event.preventDefault();

    template.editModeCases.set(!template.editModeCases.get());
  },

[...]

Expected behaviour:

I can set the Reactive Var directly in my mocha unit test to test the Blaze View.

Actual behaviour:

No clear way to set Reactive Vars so they are recognised by the withRenderedTemplate function.

Attempted solutions:

  1. Putting this in a before clause
describe('Cases', function() {
  before(function() {
    resetDatabase();

    Template.Cases.onCreated(function() {
      this.editModeCases = new ReactiveVar(false);
    });
  });
[...]
  1. Setting the data parameter of withRenderedTemplate as the Reactive Var name (I didnā€™t think this would work but got to the point of trying anything :frowning:
it('click Edit it can delete entries', function () {
    let data = {
      editModeCases: () => true,
    };

    withRenderedTemplate('Cases', data, el => {
      expect($(el).context.innerText).to.include("Exit Edit Mode")
      expect($(el).context.innerText).to.include("Edit")
      expect($(el).context.innerHTML).to.include("Delete")
    });
  });

NB: The actual functionality works, its just the test that I canā€™t figure outā€¦

Happy to provide further code / repo if it helps, but thought it might be unnecessary at this pointā€¦

I think this kind of test case is kind of hard to write in general, and is why I think you see a movement (esp in React) to separate presentation from state (see ā€œstateless functional componentsā€ in React and the ā€œwithStateā€ recompose higher order component).

So if you were following that movement youā€™d split your ā€œstatefulā€ CasesWithState from Cases (which took editMode and onSetEditMode as arguments), and write your tests against Cases.

A simpler approach is just to synthetically click the edit button in your test case.

Thereā€™s not really a good way to actually mess directly with the ReactiveVar, unless you write your code to allow it, which seems a bit of a bad idea.

Thanks for the rapid reply.

In that case, I will write a Chimp test as a workaround for now to provide coverage, though that is a resource heavy way of testing such simple functionality.

Very interested about what you wrote regarding separating presentation and state - will look further into this. React is on my (long!) list of things to learn.

Hi guys,

I am having problems getting mocha to work with XML on CirclCi. It seems like practicalmeteor/mocha and dispatch:mocha are both having problems genererating XML files.

Does anyone have a solution?

Here are the details as an extra topic HOW to run mocha unit-tests on CircleCi and output XML?.

Do you have configure Karma using Meteor + Angular2 with typescript, I have some issues trying to configure it,any help!!!

This guide is obsolete, doesnā€™t work for Meteor 1.6.1 anymore, would be nice to update it to use meteortesting:mocha instead of practicalmeteor:mocha.

  1. Meteor 1.6.1 - Practical Mocha invalid reporter "[object Object]"
  2. https://github.com/meteor/meteor/blob/devel/History.md#v161-2018-01-19
 One notable example is the practicalmeteor:mocha package. If you have been using this test-driver package, we strongly recommend switching to meteortesting:mocha instead. 

Another option (might be easier) is to use the cult of coder meteor mocha version. The previous meteor/mocha integration broke due to the update of coffee script.