diff options
| author | Vojta Jina | 2011-06-29 18:30:39 +0200 | 
|---|---|---|
| committer | Vojta Jina | 2011-09-08 23:00:49 +0200 | 
| commit | 5ba227c7cd3ddfcd3bffc3fd15daf8d6ec9b8713 (patch) | |
| tree | 6cdcd3dec9b9b3c4d2c5e290e414f9019e72e10e /test/service/locationSpec.js | |
| parent | f37f0ea16edd4b487ef8812ff69a78d9a287fa60 (diff) | |
| download | angular.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.js | 722 | 
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');      });    });  }); | 
