8

I'm having a problem doing integration testing with ember using Toran Billup's TDD guide.

I'm using Karma as my test runner with Qunit and Phantom JS.

I'm sure half of if has to do with my beginner's knowledge of the Ember runloop. My question is 2 parts:

1) How do I wrap a vist() test into the run loop properly?

2) How can I test for transitions? The index route ('/') should transition into a resource route called 'projects.index'.

module("Projects Integration Test:", {
  setup: function() {
    Ember.run(App, App.advanceReadiness);
  },
  teardown: function() {
    App.reset();
  }
});

test('Index Route Page', function(){
    expect(1);
    App.reset();    
        visit("/").then(function(){
            ok(exists("*"), "Found HTML");
        });
});

Thanks in advance for any pointers in the right direction.

ganicus
  • 321
  • 5
  • 12
  • What version of ember are you using? I failed to mention a critical bug in RC 6 that breaks when you visit the "/" route https://github.com/emberjs/ember.js/issues/2997 – Toran Billups Jul 27 '13 at 12:37
  • Ah! I'm using R6.1! Sorry, I forgot to mention in my question. Thanks so much for your help! – ganicus Jul 29 '13 at 19:28

2 Answers2

7

I just pushed up an example application that does a simple transition when you hit the "/" route using ember.js RC5

https://github.com/toranb/ember-testing-example

The simple "hello world" example looks like this

1.) the template you get redirected to during the transition

<table>
{{#each person in controller}}
<tr>
  <td class="name">{{person.fullName}}</td>
  <td><input type="submit" class="delete" value="delete" {{action deletePerson person}} /></td>
</tr>
{{/each}}
</table>

2.) the ember.js application code

App = Ember.Application.create();

App.Router.map(function() {
    this.resource("other", { path: "/" });
    this.resource("people", { path: "/people" });
});

App.OtherRoute = Ember.Route.extend({
    redirect: function() {
        this.transitionTo('people');
    }
});

App.PeopleRoute = Ember.Route.extend({
    model: function() {
        return App.Person.find();
    }
});

App.Person = Ember.Object.extend({
    firstName: '',
    lastName: ''
});

App.Person.reopenClass({
    people: [],
    find: function() {
        var self = this;
        $.getJSON('/api/people', function(response) {
            response.forEach(function(hash) {
                var person = App.Person.create(hash);
                Ember.run(self.people, self.people.pushObject, person);
            });
        }, this);
        return this.people;
    }
});

3.) the integration test looks like this

module('integration tests', {
    setup: function() {
        App.reset();
        App.Person.people = [];
    },
    teardown: function() {
        $.mockjaxClear();
    }
});

test('ajax response with 2 people yields table with 2 rows', function() {
    var json = [{firstName: "x", lastName: "y"}, {firstName: "h", lastName: "z"}];
    stubEndpointForHttpRequest('/api/people', json);
    visit("/").then(function() {
        var rows = find("table tr").length;
        equal(rows, 2, rows);
    });
});

4.) the integration helper I use on most of my ember.js projects

document.write('<div id="foo"><div id="ember-testing"></div></div>');

Ember.testing = true;

App.rootElement = '#ember-testing';
App.setupForTesting();
App.injectTestHelpers();

function exists(selector) {
    return !!find(selector).length;
}

function stubEndpointForHttpRequest(url, json) {
    $.mockjax({
        url: url,
        dataType: 'json',
        responseText: json
    });
}

$.mockjaxSettings.logging = false;
$.mockjaxSettings.responseTime = 0;
Toran Billups
  • 27,111
  • 40
  • 155
  • 268
4

I'm unfamiliar with Karma, but the portions of your test that needs to interact with ember should be pushed into the run loop (as you were mentioning)

Ember.run.next(function(){
  //do somethin
  transition stuff here etc
});

To check the current route you can steal information out of the ember out, here's some information I stole from stack overflow at some point.

var router = App.__container__.lookup("router:main"); //get the main router
var currentHandlerInfos = router.router.currentHandlerInfos; //get all handlers
var activeHandler = currentHandlerInfos[currentHandlerInfos.length - 1]; // get active handler
var activeRoute = activeHandler.handler; // active route

If you start doing controller testing, I wrote up some info on that http://discuss.emberjs.com/t/unit-testing-multiple-controllers-in-emberjs/1865

Kingpin2k
  • 47,277
  • 10
  • 78
  • 96
  • Ember.run.next() did get my test to run without an error, but I'm getting a Fail message stating that there were no assertions? I love the example above about tapping into the current route to get current info on handlers. I'll definitely play around with that in my testing! – ganicus Jul 29 '13 at 20:04