refactor($browser): extract MockWindow, use toHaveBeenCalledOnce

This commit is contained in:
Vojta Jina 2011-06-23 17:21:47 +02:00
parent 988ed451b5
commit cbedf55641

View file

@ -1,60 +1,61 @@
'use strict'; 'use strict';
describe('browser', function(){ function MockWindow() {
var events = {};
var timeouts = this.timeouts = [];
var browser, fakeWindow, xhr, logs, scripts, removedScripts, setTimeoutQueue, sniffer; this.setTimeout = function(fn) {
return timeouts.push(fn) - 1;
};
function fakeSetTimeout(fn) { this.clearTimeout = function(id) {
return setTimeoutQueue.push(fn) - 1; //return position in the queue timeouts[id] = noop;
} };
function fakeClearTimeout(deferId) { this.setTimeout.flush = function() {
setTimeoutQueue[deferId] = noop; //replace fn with noop to preserve other deferId indexes var length = timeouts.length;
} while (length-- > 0) timeouts.shift()();
};
fakeSetTimeout.flush = function() { this.addEventListener = function(name, listener) {
var currentTimeoutQueue = setTimeoutQueue; if (isUndefined(events[name])) events[name] = [];
setTimeoutQueue = []; events[name].push(listener);
forEach(currentTimeoutQueue, function(fn) { };
fn();
this.attachEvent = function(name, listener) {
this.addEventListener(name.substr(2), listener);
};
this.removeEventListener = noop;
this.detachEvent = noop;
this.fire = function(name) {
forEach(events[name], function(fn) {
fn({type: name}); // type to make jQuery happy
}); });
}; };
this.location = {
href: 'http://server',
replace: noop
};
this.history = {
replaceState: noop,
pushState: noop
};
}
describe('browser', function(){
var browser, fakeWindow, xhr, logs, scripts, removedScripts, sniffer;
beforeEach(function(){ beforeEach(function(){
setTimeoutQueue = [];
scripts = []; scripts = [];
removedScripts = []; removedScripts = [];
xhr = null; xhr = null;
sniffer = {history: true, hashchange: true}; sniffer = {history: true, hashchange: true};
fakeWindow = new MockWindow();
// mock window, extract ?
fakeWindow = {
events: {},
fire: function(name) {
forEach(this.events[name], function(listener) {
listener.apply(null, arguments);
});
},
addEventListener: function(name, listener) {
if (isUndefined(this.events[name])) {
this.events[name] = [];
}
this.events[name].push(listener);
},
attachEvent: function(name, listener) {
if (isUndefined(this.events[name])) {
this.events[name] = [];
}
this.events[name].push(listener);
},
removeEventListener: noop,
detachEvent: noop,
location: {href: 'http://server', replace: noop},
history: {replaceState: noop, pushState: noop},
setTimeout: fakeSetTimeout,
clearTimeout: fakeClearTimeout
};
var fakeBody = [{appendChild: function(node){scripts.push(node);}, var fakeBody = [{appendChild: function(node){scripts.push(node);},
removeChild: function(node){removedScripts.push(node);}}]; removeChild: function(node){removedScripts.push(node);}}];
@ -226,22 +227,24 @@ describe('browser', function(){
describe('defer', function() { describe('defer', function() {
it('should execute fn asynchroniously via setTimeout', function() { it('should execute fn asynchroniously via setTimeout', function() {
var counter = 0; var callback = jasmine.createSpy('deferred');
browser.defer(function() {counter++;});
expect(counter).toBe(0);
fakeSetTimeout.flush(); browser.defer(callback);
expect(counter).toBe(1); expect(callback).not.toHaveBeenCalled();
fakeWindow.setTimeout.flush();
expect(callback).toHaveBeenCalledOnce();
}); });
it('should update outstandingRequests counter', function() { it('should update outstandingRequests counter', function() {
var callback = jasmine.createSpy('callback'); var callback = jasmine.createSpy('deferred');
browser.defer(callback); browser.defer(callback);
expect(callback).not.toHaveBeenCalled(); expect(callback).not.toHaveBeenCalled();
fakeSetTimeout.flush(); fakeWindow.setTimeout.flush();
expect(callback).toHaveBeenCalled(); expect(callback).toHaveBeenCalledOnce();
}); });
@ -265,7 +268,7 @@ describe('browser', function(){
expect(log).toEqual([]); expect(log).toEqual([]);
browser.defer.cancel(deferId1); browser.defer.cancel(deferId1);
browser.defer.cancel(deferId3); browser.defer.cancel(deferId3);
fakeSetTimeout.flush(); fakeWindow.setTimeout.flush();
expect(log).toEqual(['ok']); expect(log).toEqual(['ok']);
}); });
}); });
@ -482,21 +485,21 @@ describe('browser', function(){
browser.addPollFn(function(){log+='a';}); browser.addPollFn(function(){log+='a';});
browser.addPollFn(function(){log+='b';}); browser.addPollFn(function(){log+='b';});
expect(log).toEqual(''); expect(log).toEqual('');
fakeSetTimeout.flush(); fakeWindow.setTimeout.flush();
expect(log).toEqual('ab'); expect(log).toEqual('ab');
fakeSetTimeout.flush(); fakeWindow.setTimeout.flush();
expect(log).toEqual('abab'); expect(log).toEqual('abab');
}); });
it('should startPoller', function(){ it('should startPoller', function(){
expect(setTimeoutQueue.length).toEqual(0); expect(fakeWindow.timeouts.length).toEqual(0);
browser.addPollFn(function(){}); browser.addPollFn(function(){});
expect(setTimeoutQueue.length).toEqual(1); expect(fakeWindow.timeouts.length).toEqual(1);
//should remain 1 as it is the check fn //should remain 1 as it is the check fn
browser.addPollFn(function(){}); browser.addPollFn(function(){});
expect(setTimeoutQueue.length).toEqual(1); expect(fakeWindow.timeouts.length).toEqual(1);
}); });
it('should return fn that was passed into addPollFn', function() { it('should return fn that was passed into addPollFn', function() {
@ -527,7 +530,7 @@ describe('browser', function(){
sniffer.history = true; sniffer.history = true;
browser.url('http://new.org'); browser.url('http://new.org');
expect(pushState).toHaveBeenCalled(); expect(pushState).toHaveBeenCalledOnce();
expect(pushState.argsForCall[0][2]).toEqual('http://new.org'); expect(pushState.argsForCall[0][2]).toEqual('http://new.org');
expect(replaceState).not.toHaveBeenCalled(); expect(replaceState).not.toHaveBeenCalled();
@ -539,7 +542,7 @@ describe('browser', function(){
sniffer.history = true; sniffer.history = true;
browser.url('http://new.org', true); browser.url('http://new.org', true);
expect(replaceState).toHaveBeenCalled(); expect(replaceState).toHaveBeenCalledOnce();
expect(replaceState.argsForCall[0][2]).toEqual('http://new.org'); expect(replaceState.argsForCall[0][2]).toEqual('http://new.org');
expect(pushState).not.toHaveBeenCalled(); expect(pushState).not.toHaveBeenCalled();
@ -598,8 +601,8 @@ describe('browser', function(){
expect(callback).toHaveBeenCalledWith('http://server/new'); expect(callback).toHaveBeenCalledWith('http://server/new');
fakeWindow.fire('hashchange'); fakeWindow.fire('hashchange');
fakeSetTimeout.flush(); fakeWindow.setTimeout.flush();
expect(callback.callCount).toBe(1); expect(callback).toHaveBeenCalledOnce();
}); });
it('should forward only popstate event when both history and hashchange supported', function() { it('should forward only popstate event when both history and hashchange supported', function() {
@ -612,8 +615,8 @@ describe('browser', function(){
expect(callback).toHaveBeenCalledWith('http://server/new'); expect(callback).toHaveBeenCalledWith('http://server/new');
fakeWindow.fire('hashchange'); fakeWindow.fire('hashchange');
fakeSetTimeout.flush(); fakeWindow.setTimeout.flush();
expect(callback.callCount).toBe(1); expect(callback).toHaveBeenCalledOnce();
}); });
it('should forward hashchange event with new url when only hashchange supported', function() { it('should forward hashchange event with new url when only hashchange supported', function() {
@ -626,8 +629,8 @@ describe('browser', function(){
expect(callback).toHaveBeenCalledWith('http://server/new'); expect(callback).toHaveBeenCalledWith('http://server/new');
fakeWindow.fire('popstate'); fakeWindow.fire('popstate');
fakeSetTimeout.flush(); fakeWindow.setTimeout.flush();
expect(callback.callCount).toBe(1); expect(callback).toHaveBeenCalledOnce();
}); });
it('should use polling when neither history nor hashchange supported', function() { it('should use polling when neither history nor hashchange supported', function() {
@ -636,12 +639,12 @@ describe('browser', function(){
browser.onUrlChange(callback); browser.onUrlChange(callback);
fakeWindow.location.href = 'http://server.new'; fakeWindow.location.href = 'http://server.new';
fakeSetTimeout.flush(); fakeWindow.setTimeout.flush();
expect(callback).toHaveBeenCalledWith('http://server.new'); expect(callback).toHaveBeenCalledWith('http://server.new');
fakeWindow.fire('popstate'); fakeWindow.fire('popstate');
fakeWindow.fire('hashchange'); fakeWindow.fire('hashchange');
expect(callback.callCount).toBe(1); expect(callback).toHaveBeenCalledOnce();
}); });
it('should not fire urlChange if changed by browser.url method (polling)', function() { it('should not fire urlChange if changed by browser.url method (polling)', function() {
@ -650,7 +653,7 @@ describe('browser', function(){
browser.onUrlChange(callback); browser.onUrlChange(callback);
browser.url('http://new.com'); browser.url('http://new.com');
fakeSetTimeout.flush(); fakeWindow.setTimeout.flush();
expect(callback).not.toHaveBeenCalled(); expect(callback).not.toHaveBeenCalled();
}); });