What is the best way to test for event handling in objects? I can’t seem to figure this one out.
I have an object that sets up a few event listeners and when it observes these events being fired it changes a dom object on the page. When I have multiple test going the last one in the example below fails, if I comment out the others it’s fine.
I have a test suite that looks like
var TitleTest = TestCase('TitleTest');
TitleTest.prototype.defaultTitle = 'title';
TitleTest.prototype.defaultCount = '0';
TitleTest.prototype.setUp = function() {
var titleObj;
this.div = new Element('div');
$$('body').first().insert(this.div);
this.div.insert('<div id="title"><h1><span id="titleCaption">' + this.defaultTitle + '</span><span id="titleCount">' + this.defaultCount + '</span></h1></div>');
titleObj = new Title();
});
TitleTest.prototype.testNewItemsEvent = function() {
var data = {count: 10};
assertEquals('Count should be zero before events are fired', this.defaultCount, $('titleCount').innerHTML);
document.fire('custom:NewItems', data);
assertEquals('New count should be 10', data.count + '', $('titleCount').innerHTML);
});
// ... a few other simple tests like the one above
TitleTest.prototype.testUpdateSpecial = function() {
var data = {caption: 'Special Title', count: 10},
specialObj = {special: {type: 2, value: 5}};
// Emulate a special type of category, that can only be
// added at page load
document.fire('custom:UpdateTitle', data);
assertEquals(data.caption, $('titleCaption').innerHTML);
assertEquals(data.count, $('titleCount').innerHTML);
//Removing the special category should revert the title to its default
document.fire('custom:RemoveSpecial', specialObj);
assertEquals(this.defaultTitle, $('titleCaption').innerHTML);
assertEquals(this.defaultCount, $('titleCount').innerHTML);
// only way to get this added back in during non load is using
// javascript history so it needs to revert to previous state
document.fire('custom:AddSpecial', specialObj);
assertEquals(data.caption, $('titleCaption').innerHTML);
assertEquals(data.count + '', $('titleCount').innerHTML);
});
The last pair of asserts will always fail if the previous tests run, but will pass if the I comment out the other tests. I’m at a loss what I can do to get this working.
Edit: here’s the code that handles the add/remove of special titles
Event.observe(document, 'custom:UpdateTitle', function(event) {
if (event.memo.caption) {
this._updateCaption(event.memo.caption);
}
if (event.memo.count) {
this._updateCount(event.memo.count);
}
}.bind(this));
Event.observe(document, 'custom:RemoveSpecial', function(event) {
if (
event.memo.special.type === 1 ||
event.memo.special.type === 2 ||
(
event.memo.special.type === 3 &&
parseInt(event.memo.special.value, 10) === 8
)
){
this._previousTitle = $('titleCaption').innerHTML;
this._resetTitle();
}
}.bind(this));
Event.observe(document, 'custom:AddSpecial', function(event) {
if (
event.memo.special.type === 1 ||
event.memo.special.type === 2 ||
(
event.memo.special.type === 3 &&
parseInt(event.memo.special.value, 10) === 8
)
){
if (!this._previousTitle.blank()) {
this._updateCaption(this._previousTitle);
}
}
}.bind(this));
@meyertee alluded to the solution of my problem. I assumed that setup and teardown worked like PHPUnit where they are respectively fired only before and after of all the tests have run but jsTestDriver fires them before and after each test. Since I was setting up my DOM and Title event in the setup, a new title object was being created before each test and thus more listeners causing a race condition. I moved instantiation of my Title object out of the setup and this has fixed the issue.