aboutsummaryrefslogtreecommitdiffstats
path: root/test/service/locationSpec.js
diff options
context:
space:
mode:
authorVojta Jina2011-06-29 18:30:39 +0200
committerVojta Jina2011-09-08 23:00:49 +0200
commit5ba227c7cd3ddfcd3bffc3fd15daf8d6ec9b8713 (patch)
tree6cdcd3dec9b9b3c4d2c5e290e414f9019e72e10e /test/service/locationSpec.js
parentf37f0ea16edd4b487ef8812ff69a78d9a287fa60 (diff)
downloadangular.js-5ba227c7cd3ddfcd3bffc3fd15daf8d6ec9b8713.tar.bz2
feat($location): $location service with html5 history api support
See documentation of $location for more info Breaks $location has no properties, only get/set methods Closes #168 Closes #146 Closes #281 Closes #234
Diffstat (limited to 'test/service/locationSpec.js')
-rw-r--r--test/service/locationSpec.js722
1 files changed, 537 insertions, 185 deletions
diff --git a/test/service/locationSpec.js b/test/service/locationSpec.js
index a137149d..e798aa81 100644
--- a/test/service/locationSpec.js
+++ b/test/service/locationSpec.js
@@ -1,251 +1,463 @@
'use strict';
+/**
+ * Create jasmine.Spy on given method, but ignore calls without arguments
+ * This is helpful when need to spy only setter methods and ignore getters
+ */
+function spyOnlyCallsWithArgs(obj, method) {
+ var spy = spyOn(obj, method);
+ obj[method] = function() {
+ if (arguments.length) return spy.apply(this, arguments);
+ return spy.originalValue.apply(this);
+ };
+ return spy;
+}
+
+
describe('$location', function() {
- var scope, $location, $browser;
+ var url;
- beforeEach(function(){
- scope = angular.scope();
- $location = scope.$service('$location');
- $browser = scope.$service('$browser');
- });
+ describe('NewUrl', function() {
+ beforeEach(function() {
+ url = new LocationUrl('http://www.domain.com:9877/path/b?search=a&b=c&d#hash');
+ });
- afterEach(function(){
- dealoc(scope);
- });
+ it('should provide common getters', function() {
+ expect(url.absUrl()).toBe('http://www.domain.com:9877/path/b?search=a&b=c&d#hash');
+ expect(url.protocol()).toBe('http');
+ expect(url.host()).toBe('www.domain.com');
+ expect(url.port()).toBe(9877);
+ expect(url.path()).toBe('/path/b');
+ expect(url.search()).toEqual({search: 'a', b: 'c', d: true});
+ expect(url.hash()).toBe('hash');
+ expect(url.url()).toBe('/path/b?search=a&b=c&d#hash');
+ });
- it("should update location object immediately when update is called", function() {
- var href = 'http://host:123/p/a/t/h.html?query=value#path?key=value&flag&key2=';
- $location.update(href);
- expect($location.href).toEqual(href);
- expect($location.protocol).toEqual("http");
- expect($location.host).toEqual("host");
- expect($location.port).toEqual("123");
- expect($location.path).toEqual("/p/a/t/h.html");
- expect($location.search).toEqual({query:'value'});
- expect($location.hash).toEqual('path?key=value&flag&key2=');
- expect($location.hashPath).toEqual('path');
- expect($location.hashSearch).toEqual({key: 'value', flag: true, key2: ''});
- });
+ it('path() should change path', function() {
+ url.path('/new/path');
+ expect(url.path()).toBe('/new/path');
+ expect(url.absUrl()).toBe('http://www.domain.com:9877/new/path?search=a&b=c&d#hash');
+ });
- it('should update location when browser url changed', function() {
- var origUrl = $location.href;
- expect(origUrl).toEqual($browser.url());
+ it('search() should accept string', function() {
+ url.search('x=y&c');
+ expect(url.search()).toEqual({x: 'y', c: true});
+ expect(url.absUrl()).toBe('http://www.domain.com:9877/path/b?x=y&c#hash');
+ });
- var newUrl = 'http://somenew/url#foo';
- $browser.url(newUrl);
- $browser.poll();
- expect($location.href).toEqual(newUrl);
- });
+ it('search() should accept object', function() {
+ url.search({one: 1, two: true});
+ expect(url.search()).toEqual({one: 1, two: true});
+ expect(url.absUrl()).toBe('http://www.domain.com:9877/path/b?one=1&two#hash');
+ });
- it('should update browser at the end of $eval', function() {
- var origBrowserUrl = $browser.url();
- $location.update('http://www.angularjs.org/');
- $location.update({path: '/a/b'});
- expect($location.href).toEqual('http://www.angularjs.org/a/b');
- expect($browser.url()).toEqual('http://www.angularjs.org/a/b');
- $location.path = '/c';
- scope.$digest();
- expect($browser.url()).toEqual('http://www.angularjs.org/c');
- });
+ it('search() should change single parameter', function() {
+ url.search({id: 'old', preserved: true});
+ url.search('id', 'new');
+
+ expect(url.search()).toEqual({id: 'new', preserved: true});
+ });
- it('should update hashPath and hashSearch on hash update', function(){
- $location.update('http://server/#path?a=b');
- expect($location.hashPath).toEqual('path');
- expect($location.hashSearch).toEqual({a:'b'});
- $location.update({hash: ''});
- expect($location.hashPath).toEqual('');
- expect($location.hashSearch).toEqual({});
- });
+ it('search() should remove single parameter', function() {
+ url.search({id: 'old', preserved: true});
+ url.search('id', null);
+ expect(url.search()).toEqual({preserved: true});
+ });
- it('should update hash on hashPath or hashSearch update', function() {
- $location.update('http://server/#path?a=b');
- scope.$digest();
- $location.update({hashPath: '', hashSearch: {}});
- expect($location.hash).toEqual('');
- });
+ it('hash() should change hash fragment', function() {
+ url.hash('new-hash');
+ expect(url.hash()).toBe('new-hash');
+ expect(url.absUrl()).toBe('http://www.domain.com:9877/path/b?search=a&b=c&d#new-hash');
+ });
- it('should update hashPath and hashSearch on $location.hash change upon eval', function(){
- $location.update('http://server/#path?a=b');
- scope.$digest();
+ it('url() should change the path, search and hash', function() {
+ url.url('/some/path?a=b&c=d#hhh');
+ expect(url.url()).toBe('/some/path?a=b&c=d#hhh');
+ expect(url.absUrl()).toBe('http://www.domain.com:9877/some/path?a=b&c=d#hhh');
+ expect(url.path()).toBe('/some/path');
+ expect(url.search()).toEqual({a: 'b', c: 'd'});
+ expect(url.hash()).toBe('hhh');
+ });
- $location.hash = '';
- scope.$digest();
- expect($location.href).toEqual('http://server/');
- expect($location.hashPath).toEqual('');
- expect($location.hashSearch).toEqual({});
- });
+ it('replace should set $$replace flag and return itself', function() {
+ expect(url.$$replace).toBe(false);
+ url.replace();
+ expect(url.$$replace).toBe(true);
+ expect(url.replace()).toBe(url);
+ });
- it('should update hash on $location.hashPath or $location.hashSearch change upon eval',
- function() {
- $location.update('http://server/#path?a=b');
- expect($location.href).toEqual('http://server/#path?a=b');
- expect($location.hashPath).toEqual('path');
- expect($location.hashSearch).toEqual({a:'b'});
- $location.hashPath = '';
- $location.hashSearch = {};
- scope.$digest();
+ it('should parse new url', function() {
+ url = new LocationUrl('http://host.com/base');
+ expect(url.path()).toBe('/base');
- expect($location.href).toEqual('http://server/');
- expect($location.hash).toEqual('');
- });
+ url = new LocationUrl('http://host.com/base#');
+ expect(url.path()).toBe('/base');
+ });
- it('should sync $location upon eval before watches are fired', function(){
- scope.$location = scope.$service('$location'); //publish to the scope for $watch
+ it('should prefix path with forward-slash', function() {
+ url = new LocationUrl('http://server/a');
+ url.path('b');
- var log = '';
- scope.$watch('$location.hash', function(scope){
- log += scope.$location.hashPath + ';';
+ expect(url.path()).toBe('/b');
+ expect(url.absUrl()).toBe('http://server/b');
});
- expect(log).toEqual('');
- scope.$digest();
- expect(log).toEqual(';');
- log = '';
- scope.$location.hash = '/abc';
- scope.$digest();
- expect(scope.$location.hash).toEqual('/abc');
- expect(log).toEqual('/abc;');
- });
+ it('should set path to forward-slash when empty', function() {
+ url = new LocationUrl('http://server');
+ expect(url.path()).toBe('/');
+ expect(url.absUrl()).toBe('http://server/');
+ });
- describe('sync', function() {
- it('should update hash with escaped hashPath', function() {
- $location.hashPath = 'foo=bar';
- scope.$digest();
- expect($location.hash).toBe('foo%3Dbar');
+ it('setters should return Url object to allow chaining', function() {
+ expect(url.path('/any')).toBe(url);
+ expect(url.search('')).toBe(url);
+ expect(url.hash('aaa')).toBe(url);
+ expect(url.url('/some')).toBe(url);
});
- it('should give $location.href the highest precedence', function() {
- $location.hashPath = 'hashPath';
- $location.hashSearch = {hash:'search'};
- $location.hash = 'hash';
- $location.port = '333';
- $location.host = 'host';
- $location.href = 'https://hrefhost:23/hrefpath';
+ it('should not preserve old properties when parsing new url', function() {
+ url.$$parse('http://www.domain.com:9877/a');
- scope.$digest();
+ expect(url.path()).toBe('/a');
+ expect(url.search()).toEqual({});
+ expect(url.hash()).toBe('');
+ expect(url.absUrl()).toBe('http://www.domain.com:9877/a');
+ });
- expect($location).toEqualData({href: 'https://hrefhost:23/hrefpath',
- protocol: 'https',
- host: 'hrefhost',
- port: '23',
- path: '/hrefpath',
- search: {},
- hash: '',
- hashPath: '',
- hashSearch: {}
- });
+
+ it('should prepend path with basePath', function() {
+ url = new LocationUrl('http://server/base/abc?a', '/base');
+ expect(url.path()).toBe('/abc');
+ expect(url.search()).toEqual({a: true});
+
+ url.path('/new/path');
+ expect(url.absUrl()).toBe('http://server/base/new/path?a');
});
- it('should give $location.hash second highest precedence', function() {
- $location.hashPath = 'hashPath';
- $location.hashSearch = {hash:'search'};
- $location.hash = 'hash';
- $location.port = '333';
- $location.host = 'host';
- $location.path = '/path';
+ it('should throw error when invalid url given', function() {
+ url = new LocationUrl('http://server.org/base/abc', '/base');
- scope.$digest();
+ expect(function() {
+ url.$$parse('http://server.org/path#/path');
+ }).toThrow('Invalid url "http://server.org/path#/path", missing path prefix "/base" !');
+ });
+
+
+ describe('encoding', function() {
+
+ it('should encode special characters', function() {
+ url.path('/a <>#');
+ url.search({'i j': '<>#'});
+ url.hash('<>#');
+
+ expect(url.path()).toBe('/a <>#');
+ expect(url.search()).toEqual({'i j': '<>#'});
+ expect(url.hash()).toBe('<>#');
+ expect(url.absUrl()).toBe('http://www.domain.com:9877/a%20%3C%3E%23?i%20j=%3C%3E%23#%3C%3E%23');
+ });
+
+
+ it('should not encode !$:@', function() {
+ url.path('/!$:@');
+ url.search('');
+ url.hash('!$:@');
- expect($location).toEqualData({href: 'http://host:333/path#hash',
- protocol: 'http',
- host: 'host',
- port: '333',
- path: '/path',
- search: {},
- hash: 'hash',
- hashPath: 'hash',
- hashSearch: {}
- });
+ expect(url.absUrl()).toBe('http://www.domain.com:9877/!$:@#!$:@');
+ });
+
+
+ it('should decode special characters', function() {
+ url = new LocationUrl('http://host.com/a%20%3C%3E%23?i%20j=%3C%3E%23#x%20%3C%3E%23');
+ expect(url.path()).toBe('/a <>#');
+ expect(url.search()).toEqual({'i j': '<>#'});
+ expect(url.hash()).toBe('x <>#');
+ });
});
});
- describe('update()', function() {
+ describe('HashbangUrl', function() {
+
+ beforeEach(function() {
+ url = new LocationHashbangUrl('http://www.server.org:1234/base#!/path?a=b&c#hash', '!');
+ });
+
+
+ it('should parse hashband url into path and search', function() {
+ expect(url.protocol()).toBe('http');
+ expect(url.host()).toBe('www.server.org');
+ expect(url.port()).toBe(1234);
+ expect(url.path()).toBe('/path');
+ expect(url.search()).toEqual({a: 'b', c: true});
+ expect(url.hash()).toBe('hash');
+ });
+
+
+ it('absUrl() should return hashbang url', function() {
+ expect(url.absUrl()).toBe('http://www.server.org:1234/base#!/path?a=b&c#hash');
+
+ url.path('/new/path');
+ url.search({one: 1});
+ url.hash('hhh');
+ expect(url.absUrl()).toBe('http://www.server.org:1234/base#!/new/path?one=1#hhh');
+ });
+
+
+ it('should preserve query params in base', function() {
+ url = new LocationHashbangUrl('http://www.server.org:1234/base?base=param#/path?a=b&c#hash', '');
+ expect(url.absUrl()).toBe('http://www.server.org:1234/base?base=param#/path?a=b&c#hash');
+
+ url.path('/new/path');
+ url.search({one: 1});
+ url.hash('hhh');
+ expect(url.absUrl()).toBe('http://www.server.org:1234/base?base=param#/new/path?one=1#hhh');
+ });
+
+
+ it('should prefix path with forward-slash', function() {
+ url = new LocationHashbangUrl('http://host.com/base#path', '');
+ expect(url.path()).toBe('/path');
+ expect(url.absUrl()).toBe('http://host.com/base#/path');
+
+ url.path('wrong');
+ expect(url.path()).toBe('/wrong');
+ expect(url.absUrl()).toBe('http://host.com/base#/wrong');
+ });
+
+
+ it('should set path to forward-slash when empty', function() {
+ url = new LocationHashbangUrl('http://server/base#!', '!');
+ url.path('aaa');
+
+ expect(url.path()).toBe('/aaa');
+ expect(url.absUrl()).toBe('http://server/base#!/aaa');
+ });
- it('should accept hash object and update only given properties', function() {
- $location.update("http://host:123/p/a/t/h.html?query=value#path?key=value&flag&key2=");
- $location.update({host: 'new', port: 24});
- expect($location.host).toEqual('new');
- expect($location.port).toEqual(24);
- expect($location.protocol).toEqual('http');
- expect($location.href).toEqual("http://new:24/p/a/t/h.html?query=value#path?key=value&flag&key2=");
+ it('should not preserve old properties when parsing new url', function() {
+ url.$$parse('http://www.server.org:1234/base#!/');
+
+ expect(url.path()).toBe('/');
+ expect(url.search()).toEqual({});
+ expect(url.hash()).toBe('');
+ expect(url.absUrl()).toBe('http://www.server.org:1234/base#!/');
});
- it('should remove # if hash is empty', function() {
- $location.update('http://www.angularjs.org/index.php#');
- expect($location.href).toEqual('http://www.angularjs.org/index.php');
+ it('should throw error when invalid url given', function() {
+ expect(function() {
+ url.$$parse('http://server.org/path#/path');
+ }).toThrow('Invalid url "http://server.org/path#/path", missing hash prefix "!" !');
});
- it('should clear hash when updating to hash-less URL', function() {
- $location.update('http://server');
- expect($location.href).toBe('http://server');
- expect($location.hash).toBe('');
+ describe('encoding', function() {
+
+ it('should encode special characters', function() {
+ url.path('/a <>#');
+ url.search({'i j': '<>#'});
+ url.hash('<>#');
+
+ expect(url.path()).toBe('/a <>#');
+ expect(url.search()).toEqual({'i j': '<>#'});
+ expect(url.hash()).toBe('<>#');
+ expect(url.absUrl()).toBe('http://www.server.org:1234/base#!/a%20%3C%3E%23?i%20j=%3C%3E%23#%3C%3E%23');
+ });
+
+
+ it('should not encode !$:@', function() {
+ url.path('/!$:@');
+ url.search('');
+ url.hash('!$:@');
+
+ expect(url.absUrl()).toBe('http://www.server.org:1234/base#!/!$:@#!$:@');
+ });
+
+
+ it('should decode special characters', function() {
+ url = new LocationHashbangUrl('http://host.com/a#/%20%3C%3E%23?i%20j=%3C%3E%23#x%20%3C%3E%23', '');
+ expect(url.path()).toBe('/ <>#');
+ expect(url.search()).toEqual({'i j': '<>#'});
+ expect(url.hash()).toBe('x <>#');
+ });
});
});
- describe('updateHash()', function() {
+ var $browser, $location, scope;
+
+ function init(url, html5Mode, basePath, hashPrefix, supportHistory) {
+ scope = angular.scope(null, {
+ $locationConfig: {html5Mode: html5Mode, hashPrefix: hashPrefix},
+ $sniffer: {history: supportHistory}});
+
+ $browser = scope.$service('$browser');
+ $browser.url(url);
+ $browser.$$baseHref = basePath;
+ $location = scope.$service('$location');
+ }
+
+ function dealocRootElement() {
+ dealoc(scope.$service('$document'));
+ }
+
+
+ describe('wiring', function() {
+
+ beforeEach(function() {
+ init('http://new.com/a/b#!', false, '/a/b', '!', true);
+ });
+
- it('should accept single string argument to update path', function() {
- $location.updateHash('path');
- expect($location.hash).toEqual('path');
- expect($location.hashPath).toEqual('path');
+ it('should update $location when browser url changes', function() {
+ spyOn($location, '$$parse').andCallThrough();
+ $browser.url('http://new.com/a/b#!/aaa');
+ $browser.poll();
+ expect($location.absUrl()).toBe('http://new.com/a/b#!/aaa');
+ expect($location.path()).toBe('/aaa');
+ expect($location.$$parse).toHaveBeenCalledOnce();
});
- it('should reset hashSearch when updating with a single string', function() {
- $location.updateHash({foo:'bar'}); //set some initial state for hashSearch
+ it('should update browser when $location changes', function() {
+ var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
+ $location.path('/new/path');
+ expect($browserUrl).not.toHaveBeenCalled();
+ scope.$apply();
- $location.updateHash('path');
- expect($location.hashPath).toEqual('path');
- expect($location.hashSearch).toEqual({});
+ expect($browserUrl).toHaveBeenCalledOnce();
+ expect($browser.url()).toBe('http://new.com/a/b#!/new/path');
});
- it('should accept single object argument to update search', function() {
- $location.updateHash({a: 'b'});
- expect($location.hash).toEqual('?a=b');
- expect($location.hashSearch).toEqual({a: 'b'});
+ it('should update browser only once per $apply cycle', function() {
+ var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
+ $location.path('/new/path');
+
+ scope.$watch(function() {
+ $location.search('a=b');
+ });
+
+ scope.$apply();
+ expect($browserUrl).toHaveBeenCalledOnce();
+ expect($browser.url()).toBe('http://new.com/a/b#!/new/path?a=b');
});
- it('should accept path string and search object arguments to update both', function() {
- $location.updateHash('path', {a: 'b'});
- expect($location.hash).toEqual('path?a=b');
- expect($location.hashSearch).toEqual({a: 'b'});
- expect($location.hashPath).toEqual('path');
+ it('should replace browser url when url was replaced at least once', function() {
+ var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
+ $location.path('/n/url').replace();
+ scope.$apply();
+
+ expect($browserUrl).toHaveBeenCalledOnce();
+ expect($browserUrl.mostRecentCall.args).toEqual(['http://new.com/a/b#!/n/url', true]);
});
- it('should update href and hash when updating to empty string', function() {
- $location.updateHash('');
- expect($location.href).toBe('http://server');
- expect($location.hash).toBe('');
+ it('should update the browser if changed from within a watcher', function() {
+ scope.$watch(function() { return true; }, function() {
+ $location.path('/changed');
+ });
scope.$digest();
+ expect($browser.url()).toBe('http://new.com/a/b#!/changed');
+ });
+ });
+
+
+ // html5 history is disabled
+ describe('disabled history', function() {
+
+ it('should use hashbang url with hash prefix', function() {
+ init('http://domain.com/base/index.html#!/a/b', false, '/base/index.html', '!');
+ expect($browser.url()).toBe('http://domain.com/base/index.html#!/a/b');
+ $location.path('/new');
+ $location.search({a: true});
+ scope.$apply();
+ expect($browser.url()).toBe('http://domain.com/base/index.html#!/new?a');
+ });
+
+
+ it('should use hashbang url without hash prefix', function() {
+ init('http://domain.com/base/index.html#/a/b', false, '/base/index.html', '');
+ expect($browser.url()).toBe('http://domain.com/base/index.html#/a/b');
+ $location.path('/new');
+ $location.search({a: true});
+ scope.$apply();
+ expect($browser.url()).toBe('http://domain.com/base/index.html#/new?a');
+ });
+ });
+
+
+ // html5 history enabled, but not supported by browser
+ describe('history on old browser', function() {
+
+ afterEach(dealocRootElement);
+
+ it('should use hashbang url with hash prefix', function() {
+ init('http://domain.com/base/index.html#!!/a/b', true, '/base/index.html', '!!', false);
+ expect($browser.url()).toBe('http://domain.com/base/index.html#!!/a/b');
+ $location.path('/new');
+ $location.search({a: true});
+ scope.$apply();
+ expect($browser.url()).toBe('http://domain.com/base/index.html#!!/new?a');
+ });
+
- expect($location.href).toBe('http://server');
- expect($location.hash).toBe('');
+ it('should redirect to hashbang url when new url given', function() {
+ init('http://domain.com/base/new-path/index.html', true, '/base/index.html', '!');
+ expect($browser.url()).toBe('http://domain.com/base/index.html#!/new-path/index.html');
+ });
+ });
+
+
+ // html5 history enabled and supported by browser
+ describe('history on new browser', function() {
+
+ afterEach(dealocRootElement);
+
+ it('should use new url', function() {
+ init('http://domain.com/base/old/index.html#a', true, '/base/index.html', '', true);
+ expect($browser.url()).toBe('http://domain.com/base/old/index.html#a');
+ $location.path('/new');
+ $location.search({a: true});
+ scope.$apply();
+ expect($browser.url()).toBe('http://domain.com/base/new?a#a');
+ });
+
+
+ it('should rewrite when hashbang url given', function() {
+ init('http://domain.com/base/index.html#!/a/b', true, '/base/index.html', '!', true);
+ expect($browser.url()).toBe('http://domain.com/base/a/b');
+ $location.path('/new');
+ $location.hash('abc');
+ scope.$apply();
+ expect($browser.url()).toBe('http://domain.com/base/new#abc');
+ expect($location.path()).toBe('/new');
+ });
+
+
+ it('should rewrite when hashbang url given (without hash prefix)', function() {
+ init('http://domain.com/base/index.html#/a/b', true, '/base/index.html', '', true);
+ expect($browser.url()).toBe('http://domain.com/base/a/b');
+ expect($location.path()).toBe('/a/b');
});
});
@@ -255,21 +467,21 @@ describe('$location', function() {
it('should parse basic url', function() {
var match = URL_MATCH.exec('http://www.angularjs.org/path?search#hash?x=x');
- expect(match[1]).toEqual('http');
- expect(match[3]).toEqual('www.angularjs.org');
- expect(match[6]).toEqual('/path');
- expect(match[8]).toEqual('search');
- expect(match[10]).toEqual('hash?x=x');
+ expect(match[1]).toBe('http');
+ expect(match[3]).toBe('www.angularjs.org');
+ expect(match[6]).toBe('/path');
+ expect(match[8]).toBe('search');
+ expect(match[10]).toBe('hash?x=x');
});
it('should parse file://', function(){
var match = URL_MATCH.exec('file:///Users/Shared/misko/work/angular.js/scenario/widgets.html');
- expect(match[1]).toEqual('file');
- expect(match[3]).toEqual('');
+ expect(match[1]).toBe('file');
+ expect(match[3]).toBe('');
expect(match[5]).toBeFalsy();
- expect(match[6]).toEqual('/Users/Shared/misko/work/angular.js/scenario/widgets.html');
+ expect(match[6]).toBe('/Users/Shared/misko/work/angular.js/scenario/widgets.html');
expect(match[8]).toBeFalsy();
});
@@ -277,30 +489,170 @@ describe('$location', function() {
it('should parse url with "-" in host', function(){
var match = URL_MATCH.exec('http://a-b1.c-d.09/path');
- expect(match[1]).toEqual('http');
- expect(match[3]).toEqual('a-b1.c-d.09');
+ expect(match[1]).toBe('http');
+ expect(match[3]).toBe('a-b1.c-d.09');
expect(match[5]).toBeFalsy();
- expect(match[6]).toEqual('/path');
+ expect(match[6]).toBe('/path');
expect(match[8]).toBeFalsy();
});
it('should parse host without "/" at the end', function() {
var match = URL_MATCH.exec('http://host.org');
- expect(match[3]).toEqual('host.org');
+ expect(match[3]).toBe('host.org');
match = URL_MATCH.exec('http://host.org#');
- expect(match[3]).toEqual('host.org');
+ expect(match[3]).toBe('host.org');
match = URL_MATCH.exec('http://host.org?');
- expect(match[3]).toEqual('host.org');
+ expect(match[3]).toBe('host.org');
});
it('should match with just "/" path', function() {
var match = URL_MATCH.exec('http://server/#?book=moby');
- expect(match[10]).toEqual('?book=moby');
+ expect(match[10]).toBe('?book=moby');
+ });
+ });
+
+
+ describe('PATH_MATCH', function() {
+
+ it('should parse just path', function() {
+ var match = PATH_MATCH.exec('/path');
+ expect(match[1]).toBe('/path');
+ });
+
+
+ it('should parse path with search', function() {
+ var match = PATH_MATCH.exec('/ppp/a?a=b&c');
+ expect(match[1]).toBe('/ppp/a');
+ expect(match[3]).toBe('a=b&c');
+ });
+
+
+ it('should parse path with hash', function() {
+ var match = PATH_MATCH.exec('/ppp/a#abc?');
+ expect(match[1]).toBe('/ppp/a');
+ expect(match[5]).toBe('abc?');
+ });
+
+
+ it('should parse path with both search and hash', function() {
+ var match = PATH_MATCH.exec('/ppp/a?a=b&c#abc/d?');
+ expect(match[3]).toBe('a=b&c');
+ });
+ });
+
+
+ describe('link rewriting', function() {
+
+ var root, link, extLink, $browser, originalBrowser, lastEventPreventDefault;
+
+ function init(linkHref, html5Mode, supportHist, attrs) {
+ var jqRoot = jqLite('<div></div>');
+ attrs = attrs ? ' ' + attrs + ' ' : '';
+ link = jqLite('<a href="' + linkHref + '"' + attrs + '>link</a>')[0];
+ root = jqRoot.append(link)[0];
+
+ jqLite(document.body).append(jqRoot);
+
+ var scope = angular.scope(null, {
+ $document: jqRoot,
+ $sniffer: {history: supportHist},
+ $locationConfig: {html5Mode: html5Mode, hashPrefix: '!'}
+ });
+
+ $browser = scope.$service('$browser');
+ $browser.url('http://host.com/base');
+ $browser.$$baseHref = '/base/index.html';
+ var $location = scope.$service('$location');
+ originalBrowser = $browser.url();
+
+ // we have to prevent the default operation, as we need to test absolute links (http://...)
+ // and navigating to these links would kill jstd
+ jqRoot.bind('click', function(e) {
+ lastEventPreventDefault = e.isDefaultPrevented();
+ e.preventDefault();
+ });
+ }
+
+ function triggerAndExpectRewriteTo(url) {
+ browserTrigger(link, 'click');
+ expect(lastEventPreventDefault).toBe(true);
+ expect($browser.url()).toBe(url);
+ }
+
+ function triggerAndExpectNoRewrite() {
+ browserTrigger(link, 'click');
+ expect(lastEventPreventDefault).toBe(false);
+ expect($browser.url()).toBe(originalBrowser);
+ }
+
+ afterEach(function() {
+ dealoc(root);
+ dealoc(document.body);
+ });
+
+
+ it('should rewrite rel link to new url when history enabled on new browser', function() {
+ init('link?a#b', true, true);
+ triggerAndExpectRewriteTo('http://host.com/base/link?a#b');
+ });
+
+
+ it('should rewrite abs link to new url when history enabled on new browser', function() {
+ init('/base/link?a#b', true, true);
+ triggerAndExpectRewriteTo('http://host.com/base/link?a#b');
+ });
+
+
+ it('should rewrite rel link to hashbang url when history enabled on old browser', function() {
+ init('link?a#b', true, false);
+ triggerAndExpectRewriteTo('http://host.com/base/index.html#!/link?a#b');
+ });
+
+
+ it('should rewrite abs link to hashbang url when history enabled on old browser', function() {
+ init('/base/link?a#b', true, false);
+ triggerAndExpectRewriteTo('http://host.com/base/index.html#!/link?a#b');
+ });
+
+
+ it('should not rewrite when history disabled', function() {
+ init('#new', false);
+ triggerAndExpectNoRewrite();
+ });
+
+
+ it('should not rewrite ng:ext-link', function() {
+ init('#new', true, true, 'ng:ext-link');
+ triggerAndExpectNoRewrite();
+ });
+
+
+ it('should not rewrite full url links do different domain', function() {
+ init('http://www.dot.abc/a?b=c', true);
+ triggerAndExpectNoRewrite();
+ });
+
+
+ it('should not rewrite links with target="_blank"', function() {
+ init('/a?b=c', true, true, 'target="_blank"');
+ triggerAndExpectNoRewrite();
+ });
+
+
+ it('should not rewrite links with target specified', function() {
+ init('/a?b=c', true, true, 'target="some-frame"');
+ triggerAndExpectNoRewrite();
+ });
+
+
+ it('should rewrite full url links to same domain and base path', function() {
+ init('http://host.com/base/new', true);
+ triggerAndExpectRewriteTo('http://host.com/base/index.html#!/new');
});
});
});