aboutsummaryrefslogtreecommitdiffstats
path: root/test/BrowserSpecs.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/BrowserSpecs.js')
-rw-r--r--test/BrowserSpecs.js230
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();
});
});