Stepping through integration tests


#1

Does anybody have any good examples of somewhat complex interactions inside integration tests?

I am still trying to figure out some of the nuance of chained together user interactions.

In particular I am trying to test some cancel button behavior in my app.

  • User visits edit page for a particular resource/model
  • Updates data bound model via input form
  • Clicks cancel button
  • Is returned back to index page where original model property it restored to value before editing began

In my route I have a save and cancel action handlers and also a deactivate method. Rollback behavior happens either when deactivating, or else cancel method is called.

This behavior appears to work correctly when I test the app manually but I can’t seem to get a working test for the behavior.

In my integration test I have some stubbing out of the model with pretender.

But here is the core test case I can’t get working correctly:

test('Should be able to cancel edit product', function() {
  visit('/products/1/edit');

  andThen(function() {
    fillIn('input.product-name', 'My edited product');
    click('button.cancel');
    andThen(function() {
       equal(find('ul.items li:first').text(), 'Some product 1');
    });  
  });
});

A couple of questions:

  1. Not sure about the chaining of the andThen promises. Should the be nested?
  2. How can I slow down or step through the sequence of user interactions so that I can see exactly what is happening in the little preview window when I run this in qunit. Would like to step through the test and inspect what is happening at each user interaction.
  3. Any way to conveniently spit back the DOM so I can inspect exactly what the test is seeing with my jQuery find methods? I am wondering if there is something about the DOM and how I have written the test case itself.

#2

A little more context:

I can get the test to work if I manually walk through the interaction but it is as if the redirect that is performed in my cancel method is not being captured in my test.

test('Should be able to cancel edit product', function() {
  visit('/products/1/edit');

  andThen(function() {
    fillIn('input.product-name', 'My edited product');
    click('button.cancel');
    andThen(function() {
      visit('/products/1');
      andThen(function() {
        equal(find('h2').text(), 'Some product 1');
      });
    });  
  });
});

This is what my cancel action does in my edit route

  actions: {
    save: function(model) {
      var self = this;
      model.save().then(function(saved) {
        self.transitionTo('products.show', saved);
      });
    },

    cancel: function() {
      var model = this.controller.get('model');
      if (model.get('isDirty')) {
        model.rollback();
      }
      this.transitionTo('products.show', model);
    }
  }

I am really trying to capture and document that rollback behavior in my integration test.

But wondering if the way the tests are setup the model state is reinitialized and therefore the whole test is not actually testing what I want to test which is the rollback undo behavior caused by the user.

I guess it is that extra call to

visit('/products/1');

Which seems unnecessary if the cancel action is going to rollback and perform that transition for me.