Skip to content

Instantly share code, notes, and snippets.

@noelrappin noelrappin/description.md
Last active Dec 14, 2015

Embed
What would you like to do?
Problem I'm having with Ember and Jasmine

I'm trying to run an Ember controller in a Jasmine test, and it's giving me some trouble.

This spec works, in that it renders the controller, and most of the controller is rendered accurately and can be tested.

However, there is clearly a difference between how I'm setting up these objects in the test, and how Ember sets them up at run time, because parts of the controller are not working in the test...

Details:

  • The itemController is not accessed at all, which means that the reference to "startDateDisplay" (which is defined in the item controller) comes up empty.

  • In a probably related story, the action referenced in the template can not be triggered in the test with a $(".trip").click() jQuery event.

I tried a few workarounds -- I tried changing the {{each}} in the template to:

{{#each trip in controller}}

Which gives me the error 

Error: assertion failed: an Ember.CollectionView's content must implement Ember.Array. You passed <TimeTravel.IndexTripController:ember258>

Which I take to mean that whatever magic causes looping over a controller to refer to its content is not being invoked when rendered in the test.

I also tried the more explicit 

{{#each trip in controller.content itemController="IndexTrip"}}

Which fails with

TypeError: Cannot call method 'child' of null 
at Ember.ArrayController.Ember.ArrayProxy.extend.controllerAt (http://js_travel.dev/assets/ember.js?body=1:12492:53)
at Ember.ArrayController.Ember.ArrayProxy.extend.objectAtContent (http://js_travel.dev/assets/ember.js?body=1:12445:21)

Which I don't get at all, but has something to do with containers.

{{! This is part of the template I'm trying to render -- the relevant part is the each, which triggers the use of
the itemController}
<div class="admin_trips span-12">
{{#each trip in controller}}
<div class="trip">
<div class="header" {{action selectTrip trip}}>
{{trip.name}}
{{trip.totalRevenueDisplay}}
</div>
{{log trip.startDateDisplay}}
<div class="dates">{{trip.startDateDisplay}} - {{trip.endDateDisplay}}</div>
<div class="price">{{trip.priceDisplay}}</div>
</div>
{{/each}}
</div>
// This is the controller -- it has other details, but those aren't important right now
TimeTravel.IndexController = Ember.ArrayController.extend({
itemController: "indexTrip",
})
// Here's the spec -- it creates a controller, a dummy view, and renders the view.
describe("with an index controller", function() {
beforeEach(function() {
Ember.testing = true;
Ember.run(function() {
trip = TimeTravel.Trip.createRecord({
name: "Mayflower",
startDate: "1620-09-06",
endDate: "1620-11-21"
});
controller = TimeTravel.IndexController.create();
controller.set('content', [trip]);
view = Ember.View.create({
controller: controller,
templateName: 'index'
});
view.append();
});
});
afterEach(function() {
Ember.run(function() {
view.remove();
});
});
describe("basic stuff", function() {
it("displays trips", function() {
Ember.run(function() {
expect($(".admin_trips").length).toEqual(1)
expect($(".trip").length).toEqual(1)
expect($(".trip .dates").text()).toEqual("Sep 6, 1620 - Nov 21, 1620")
});
});
it("manages clicks", function() {
Ember.run(function() {
$(".trip .header").first().click();
});
expect($(".selected_name").text()).toEqual("Mayflower");
});
});
});
@wagenet

This comment has been minimized.

Copy link

wagenet commented Feb 25, 2013

controller = TimeTravel.IndexTripController.create();
controller.set('content', [trip]);

The above seems wrong since you've said that IndexTripController is an ObjectController. Am I mistaken?

@noelrappin

This comment has been minimized.

Copy link
Owner Author

noelrappin commented Feb 25, 2013

No, you are right, but if I change that, then I get the same error that I do when I explicitly set the itemController in the template, namely:

TypeError: Cannot call method 'child' of null
at Ember.ArrayController.Ember.ArrayProxy.extend.controllerAt (http://js_travel.dev/assets/ember.js?body=1:12492:53)
at Ember.ArrayController.Ember.ArrayProxy.extend.objectAtContent (http://js_travel.dev/assets/ember.js?body=1:12445:21)
at superWrapper as objectAtContent
at Ember.ArrayProxy.Ember.Object.extend.objectAt (http://js_travel.dev/assets/ember.js?body=1:11365:41)
at superWrapper as objectAt
at Ember.Array.Ember.Mixin.create.arrayContentDidChange (http://js_travel.dev/assets/ember.js?body=1:8487:14)
at Ember.ArrayController.Ember.ArrayProxy.extend.arrayContentDidChange (http://js_travel.dev/assets/ember.js?body=1:12476:10)
at superWrapper as arrayContentDidChange
at Ember.ArrayProxy.Ember.Object.extend.arrangedContentArrayDidChange (http://js_travel.dev/assets/ember.js?body=1:11385:10)
at Ember.ArrayProxy.Ember.Object.extend._arrangedContentDidChange (http://js_travel.dev/assets/ember.js?body=1:11336:10)

@wagenet

This comment has been minimized.

Copy link

wagenet commented Feb 25, 2013

It's really hard for me to know what's going on beyond this without being able to interact with the code.

@noelrappin

This comment has been minimized.

Copy link
Owner Author

noelrappin commented Feb 25, 2013

That said, it's clearly a change that needs to be made in the spec. I wandered through the error, and it seems to have to do with containers or subcontainers not being created properly.

So, is this a reasonable way to test Ember, or should I be trying to go through the router?

@wagenet

This comment has been minimized.

Copy link

wagenet commented Feb 25, 2013

It definitely seems possible that containers are an issue here. The general line of thought recently has been that most Ember app testing should be integration tests and not unit tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.