diff options
Diffstat (limited to 'test/BrowserSpecs.js')
| -rw-r--r-- | test/BrowserSpecs.js | 230 |
1 files changed, 160 insertions, 70 deletions
diff --git a/test/BrowserSpecs.js b/test/BrowserSpecs.js index 5cc7ae65..e503a17d 100644 --- a/test/BrowserSpecs.js +++ b/test/BrowserSpecs.js @@ -2,7 +2,7 @@ describe('browser', function(){ - var browser, fakeWindow, xhr, logs, scripts, removedScripts, setTimeoutQueue; + var browser, fakeWindow, xhr, logs, scripts, removedScripts, setTimeoutQueue, sniffer; function fakeSetTimeout(fn) { return setTimeoutQueue.push(fn) - 1; //return position in the queue @@ -26,8 +26,32 @@ describe('browser', function(){ scripts = []; removedScripts = []; xhr = null; + sniffer = {history: true, hashchange: true}; + + // mock window, extract ? fakeWindow = { - location: {href:"http://server"}, + 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 }; @@ -59,7 +83,7 @@ describe('browser', function(){ error: function() { logs.error.push(slice.call(arguments)); }}; browser = new Browser(fakeWindow, jqLite(window.document), fakeBody, FakeXhr, - fakeLog); + fakeLog, sniffer); }); it('should contain cookie cruncher', function() { @@ -482,96 +506,162 @@ describe('browser', function(){ }); }); + describe('url', function() { + var pushState, replaceState, locationReplace; - describe('url api', function() { - it('should use $browser poller to detect url changes when onhashchange event is unsupported', - function() { + beforeEach(function() { + pushState = spyOn(fakeWindow.history, 'pushState'); + replaceState = spyOn(fakeWindow.history, 'replaceState'); + locationReplace = spyOn(fakeWindow.location, 'replace'); + }); - fakeWindow = { - location: {href:"http://server"}, - document: {}, - setTimeout: fakeSetTimeout - }; + it('should return current location.href', function() { + fakeWindow.location.href = 'http://test.com'; + expect(browser.url()).toEqual('http://test.com'); - browser = new Browser(fakeWindow, {}, {}); - browser.startPoller = function() {}; + fakeWindow.location.href = 'https://another.com'; + expect(browser.url()).toEqual('https://another.com'); + }); - var events = []; + it('should use history.pushState when available', function() { + sniffer.history = true; + browser.url('http://new.org'); - browser.onHashChange(function() { - events.push('x'); - }); + expect(pushState).toHaveBeenCalled(); + expect(pushState.argsForCall[0][2]).toEqual('http://new.org'); - fakeWindow.location.href = "http://server/#newHash"; - expect(events).toEqual([]); - fakeSetTimeout.flush(); - expect(events).toEqual(['x']); + expect(replaceState).not.toHaveBeenCalled(); + expect(locationReplace).not.toHaveBeenCalled(); + expect(fakeWindow.location.href).toEqual('http://server'); + }); - //don't do anything if url hasn't changed - events = []; - fakeSetTimeout.flush(); - expect(events).toEqual([]); + it('should use history.replaceState when available', function() { + sniffer.history = true; + browser.url('http://new.org', true); + + expect(replaceState).toHaveBeenCalled(); + expect(replaceState.argsForCall[0][2]).toEqual('http://new.org'); + + expect(pushState).not.toHaveBeenCalled(); + expect(locationReplace).not.toHaveBeenCalled(); + expect(fakeWindow.location.href).toEqual('http://server'); }); + it('should set location.href when pushState not available', function() { + sniffer.history = false; + browser.url('http://new.org'); - it('should use onhashchange events to detect url changes when supported by browser', - function() { + expect(fakeWindow.location.href).toEqual('http://new.org'); - var onHashChngListener; + expect(pushState).not.toHaveBeenCalled(); + expect(replaceState).not.toHaveBeenCalled(); + expect(locationReplace).not.toHaveBeenCalled(); + }); - fakeWindow = {location: {href:"http://server"}, - addEventListener: function(type, listener) { - expect(type).toEqual('hashchange'); - onHashChngListener = listener; - }, - attachEvent: function(type, listener) { - expect(type).toEqual('onhashchange'); - onHashChngListener = listener; - }, - removeEventListener: angular.noop, - detachEvent: angular.noop, - document: {} - }; - fakeWindow.onhashchange = true; + it('should use location.replace when history.replaceState not available', function() { + sniffer.history = false; + browser.url('http://new.org', true); - browser = new Browser(fakeWindow, {}, {}); + expect(locationReplace).toHaveBeenCalledWith('http://new.org'); - var events = [], - event = {type: "hashchange"}; + expect(pushState).not.toHaveBeenCalled(); + expect(replaceState).not.toHaveBeenCalled(); + expect(fakeWindow.location.href).toEqual('http://server'); + }); - browser.onHashChange(function(e) { - events.push(e); - }); + it('should return $browser to allow chaining', function() { + expect(browser.url('http://any.com')).toBe(browser); + }); + }); - expect(events).toEqual([]); - onHashChngListener(event); + describe('urlChange', function() { + var callback; - expect(events.length).toBe(1); - expect(events[0].originalEvent || events[0]).toBe(event); // please jQuery and jqLite + beforeEach(function() { + callback = jasmine.createSpy('onUrlChange'); + }); - // clean up the jqLite cache so that the global afterEach doesn't complain - if (!jQuery) { - jqLite(fakeWindow).dealoc(); - } + afterEach(function() { + if (!jQuery) jqLite(fakeWindow).dealoc(); }); - // asynchronous test - it('should fire onHashChange when location.hash change', function() { - var callback = jasmine.createSpy('onHashChange'); - browser = new Browser(window, {}, {}); - browser.onHashChange(callback); + it('should return registered callback', function() { + expect(browser.onUrlChange(callback)).toBe(callback); + }); - window.location.hash = 'new-hash'; - browser.addPollFn(function() {}); + it('should forward popstate event with new url when history supported', function() { + sniffer.history = true; + browser.onUrlChange(callback); + fakeWindow.location.href = 'http://server/new'; - waitsFor(function() { - return callback.callCount; - }, 'onHashChange callback to be called', 1000); + fakeWindow.fire('popstate'); + expect(callback).toHaveBeenCalledWith('http://server/new'); - runs(function() { - if (!jQuery) jqLite(window).dealoc(); - window.location.hash = ''; - }); + fakeWindow.fire('hashchange'); + fakeSetTimeout.flush(); + expect(callback.callCount).toBe(1); + }); + + it('should forward only popstate event when both history and hashchange supported', function() { + sniffer.history = true; + sniffer.hashchange = true; + browser.onUrlChange(callback); + fakeWindow.location.href = 'http://server/new'; + + fakeWindow.fire('popstate'); + expect(callback).toHaveBeenCalledWith('http://server/new'); + + fakeWindow.fire('hashchange'); + fakeSetTimeout.flush(); + expect(callback.callCount).toBe(1); + }); + + it('should forward hashchange event with new url when only hashchange supported', function() { + sniffer.history = false; + sniffer.hashchange = true; + browser.onUrlChange(callback); + fakeWindow.location.href = 'http://server/new'; + + fakeWindow.fire('hashchange'); + expect(callback).toHaveBeenCalledWith('http://server/new'); + + fakeWindow.fire('popstate'); + fakeSetTimeout.flush(); + expect(callback.callCount).toBe(1); + }); + + it('should use polling when neither history nor hashchange supported', function() { + sniffer.history = false; + sniffer.hashchange = false; + browser.onUrlChange(callback); + + fakeWindow.location.href = 'http://server.new'; + fakeSetTimeout.flush(); + expect(callback).toHaveBeenCalledWith('http://server.new'); + + fakeWindow.fire('popstate'); + fakeWindow.fire('hashchange'); + expect(callback.callCount).toBe(1); + }); + + it('should not fire urlChange if changed by browser.url method (polling)', function() { + sniffer.history = false; + sniffer.hashchange = false; + browser.onUrlChange(callback); + browser.url('http://new.com'); + + fakeSetTimeout.flush(); + expect(callback).not.toHaveBeenCalled(); + }); + + it('should not fire urlChange if changed by browser.url method (hashchange)', function() { + sniffer.history = false; + sniffer.hashchange = true; + browser.onUrlChange(callback); + browser.url('http://new.com'); + + fakeWindow.fire('hashchange'); + expect(callback).not.toHaveBeenCalled(); }); }); |
