Reputation: 370
I'm looking to write some tests that test the wiring between Backbone views and their models. I essentially want to load up my view with a model and make sure everything is peachy (events properly triggered/handled, elements added to the DOM, etc). I see this as different from acceptance/functional/e2e testing, but larger than simple unit tests. In other words, I'm not looking to write:
var browser = new Browser()
, fakeData = readFixtures("persons.json");
fakeAPIResponse('/persons', fakeData);
browser.visit("http://localhost:3000/", function () {
assert.ok(browser.success);
var persons = browser.queryAll(".persons li");
assert.lengthOf(persons, 20);
});
but rather something like
var router = require('routers/main'),
UserModel = require('models/user'),
AccountView = require('views/account');
...
# In a test
var model = new UserModel({ userId: 1 });
router._showView(new AccountView({ model: model });
expect(document.getElementsByClassName('account-panel')).to.have.length(1);
model.set('name', 'Test Testerson');
expect(document.getElementById('name-field').value).to.equal('Test Testerson');
Maybe I'm way off and should just put together some end-to-end tests but this seems to me like it'd be a valuable way of testing. My question is: how can I accomplish this? I need a full DOM, so I'm thinking that these should run in something like PhantomJS; the DOM should be reset before each test, but it seems silly/inefficient to have the browser navigate to a new page for each individual test. Is there a framework out there for running a test this way? Feel free to tell me I'm wrong for wanting this.
Upvotes: 1
Views: 261
Reputation: 11148
We are doing this using casperJs. Casper will give you the full DOM, but this should not be the reason the choose integration test over unit test. When I find myself going way out of my way to create a test environment, I tend to choose integration.
However, having said that, I think you can get away with doing a unit test and here is how I would do it. We are using testem with chaiJs assertions for such tests. If you setup a fixture, you can do something like this (and you'll have the full DOM, and ability to test events and everything else listed in your OP).
beforeEach(function () {
var theModel = new Backbone.Model(),
theViewToTest = new TheViewToTest({
model: theModel,
el: $(fixtures.get('some-fixture.html'))
});
theViewToTest.render();
this.theViewToTest = theViewToTest;
});
describe('Checking event handlers', function () {
it('Should fire some events', function () {
// I would setup a spy here and listen to the button handler
this.theViewToTest.$el.find('.some-button').trigger('click');
// Assert the spy was called once
});
});
Upvotes: 1