diff options
| author | Igor Minar | 2011-02-15 01:12:45 -0500 | 
|---|---|---|
| committer | Igor Minar | 2011-02-15 11:01:53 -0500 | 
| commit | 1777110958f76ee4be5760e36c96702223385918 (patch) | |
| tree | 5aa03b246507e66877e5eac69e58e004e244d7a5 /test | |
| parent | d2089a16335276eecb8d81eb17332c2dff2cf1a2 (diff) | |
| download | angular.js-1777110958f76ee4be5760e36c96702223385918.tar.bz2 | |
split up services into individual files
- split up services into files under src/service
- split up specs into files under test/service
- rewrite all specs so that they don't depend on one global forEach
- get rid of obsolete code and tests in ng:switch
- rename mock $log spec from "$log" to "$log mock"
Diffstat (limited to 'test')
| -rw-r--r-- | test/angular-mocksSpec.js | 2 | ||||
| -rw-r--r-- | test/service/cookieStoreSpec.js | 39 | ||||
| -rw-r--r-- | test/service/cookiesSpec.js | 98 | ||||
| -rw-r--r-- | test/service/deferSpec.js | 69 | ||||
| -rw-r--r-- | test/service/documentSpec.js | 17 | ||||
| -rw-r--r-- | test/service/exceptionHandlerSpec.js | 23 | ||||
| -rw-r--r-- | test/service/hoverSpec.js | 1 | ||||
| -rw-r--r-- | test/service/invalidWidgetsSpec.js | 39 | ||||
| -rw-r--r-- | test/service/locationSpec.js | 299 | ||||
| -rw-r--r-- | test/service/logSpec.js | 100 | ||||
| -rw-r--r-- | test/service/resourceSpec.js | 1 | ||||
| -rw-r--r-- | test/service/routeSpec.js | 228 | ||||
| -rw-r--r-- | test/service/updateViewSpec.js | 61 | ||||
| -rw-r--r-- | test/service/windowSpec.js | 17 | ||||
| -rw-r--r-- | test/service/xhr.bulkSpec.js | 69 | ||||
| -rw-r--r-- | test/service/xhr.cacheSpec.js | 128 | ||||
| -rw-r--r-- | test/service/xhr.errorSpec.js | 36 | ||||
| -rw-r--r-- | test/service/xhrSpec.js | 47 | ||||
| -rw-r--r-- | test/servicesSpec.js | 1081 | ||||
| -rw-r--r-- | test/widgetsSpec.js | 15 | 
20 files changed, 1273 insertions, 1097 deletions
| diff --git a/test/angular-mocksSpec.js b/test/angular-mocksSpec.js index fabc47ea..f49c53b1 100644 --- a/test/angular-mocksSpec.js +++ b/test/angular-mocksSpec.js @@ -120,7 +120,7 @@ describe('TzDate', function() {    });  }); -describe('$log', function() { +describe('$log mock', function() {    var $log;    beforeEach(function() {      $log = MockLogFactory(); diff --git a/test/service/cookieStoreSpec.js b/test/service/cookieStoreSpec.js new file mode 100644 index 00000000..0a493470 --- /dev/null +++ b/test/service/cookieStoreSpec.js @@ -0,0 +1,39 @@ +describe('$cookieStore', function() { +  var scope, $browser, $cookieStore; + +  beforeEach(function() { +    scope = angular.scope(); +    $cookieStore = scope.$service('$cookieStore'); +    $browser = scope.$service('$browser'); +  }); + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  it('should serialize objects to json', function() { +    $cookieStore.put('objectCookie', {id: 123, name: 'blah'}); +    scope.$eval(); //force eval in test +    expect($browser.cookies()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'}); +  }); + + +  it('should deserialize json to object', function() { +    $browser.cookies('objectCookie', '{"id":123,"name":"blah"}'); +    $browser.poll(); +    expect($cookieStore.get('objectCookie')).toEqual({id: 123, name: 'blah'}); +  }); + + +  it('should delete objects from the store when remove is called', function() { +    $cookieStore.put('gonner', { "I'll":"Be Back"}); +    scope.$eval(); //force eval in test +    $browser.poll(); +    expect($browser.cookies()).toEqual({'gonner': '{"I\'ll":"Be Back"}'}); + +    $cookieStore.remove('gonner'); +    scope.$eval(); +    expect($browser.cookies()).toEqual({}); +  }); +}); diff --git a/test/service/cookiesSpec.js b/test/service/cookiesSpec.js new file mode 100644 index 00000000..11551393 --- /dev/null +++ b/test/service/cookiesSpec.js @@ -0,0 +1,98 @@ +describe('$cookies', function() { +  var scope, $browser; + +  beforeEach(function() { +    $browser = new MockBrowser(); +    $browser.cookieHash['preexisting'] = 'oldCookie'; +    scope = angular.scope(null, angular.service, {$browser: $browser}); +    scope.$cookies = scope.$service('$cookies'); +  }); + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  it('should provide access to existing cookies via object properties and keep them in sync', +      function(){ +    expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); + +    // access internal cookie storage of the browser mock directly to simulate behavior of +    // document.cookie +    $browser.cookieHash['brandNew'] = 'cookie'; +    $browser.poll(); + +    expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie'}); + +    $browser.cookieHash['brandNew'] = 'cookie2'; +    $browser.poll(); +    expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie2'}); + +    delete $browser.cookieHash['brandNew']; +    $browser.poll(); +    expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); +  }); + + +  it('should create or update a cookie when a value is assigned to a property', function() { +    scope.$cookies.oatmealCookie = 'nom nom'; +    scope.$eval(); + +    expect($browser.cookies()). +      toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'}); + +    scope.$cookies.oatmealCookie = 'gone'; +    scope.$eval(); + +    expect($browser.cookies()). +      toEqual({'preexisting': 'oldCookie', 'oatmealCookie': 'gone'}); +  }); + + +  it('should drop or reset any cookie that was set to a non-string value', function() { +    scope.$cookies.nonString = [1, 2, 3]; +    scope.$cookies.nullVal = null; +    scope.$cookies.undefVal = undefined; +    scope.$cookies.preexisting = function(){}; +    scope.$eval(); +    expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'}); +    expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); +  }); + + +  it('should remove a cookie when a $cookies property is deleted', function() { +    scope.$cookies.oatmealCookie = 'nom nom'; +    scope.$eval(); +    $browser.poll(); +    expect($browser.cookies()). +      toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'}); + +    delete scope.$cookies.oatmealCookie; +    scope.$eval(); + +    expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'}); +  }); + + +  it('should drop or reset cookies that browser refused to store', function() { +    var i, longVal; + +    for (i=0; i<5000; i++) { +      longVal += '*'; +    } + +    //drop if no previous value +    scope.$cookies.longCookie = longVal; +    scope.$eval(); +    expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); + + +    //reset if previous value existed +    scope.$cookies.longCookie = 'shortVal'; +    scope.$eval(); +    expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'}); +    scope.$cookies.longCookie = longVal; +    scope.$eval(); +    expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'}); +  }); +}); diff --git a/test/service/deferSpec.js b/test/service/deferSpec.js new file mode 100644 index 00000000..932c3661 --- /dev/null +++ b/test/service/deferSpec.js @@ -0,0 +1,69 @@ +describe('$defer', function() { +  var scope, $browser, $defer, $exceptionHandler; + +  beforeEach(function(){ +    scope = angular.scope({}, angular.service, +                          {'$exceptionHandler': jasmine.createSpy('$exceptionHandler')}); +    $browser = scope.$service('$browser'); +    $defer = scope.$service('$defer'); +    $exceptionHandler = scope.$service('$exceptionHandler'); +  }); + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  it('should delegate functions to $browser.defer', function() { +    var counter = 0; +    $defer(function() { counter++; }); + +    expect(counter).toBe(0); + +    $browser.defer.flush(); +    expect(counter).toBe(1); + +    $browser.defer.flush(); //does nothing +    expect(counter).toBe(1); + +    expect($exceptionHandler).not.toHaveBeenCalled(); +  }); + + +  it('should delegate exception to the $exceptionHandler service', function() { +    $defer(function() {throw "Test Error";}); +    expect($exceptionHandler).not.toHaveBeenCalled(); + +    $browser.defer.flush(); +    expect($exceptionHandler).toHaveBeenCalledWith("Test Error"); +  }); + + +  it('should call eval after each callback is executed', function() { +    var eval = this.spyOn(scope, '$eval').andCallThrough(); + +    $defer(function() {}); +    expect(eval).wasNotCalled(); + +    $browser.defer.flush(); +    expect(eval).wasCalled(); + +    eval.reset(); //reset the spy; + +    $defer(function() {}); +    $defer(function() {}); +    $browser.defer.flush(); +    expect(eval.callCount).toBe(2); +  }); + + +  it('should call eval even if an exception is thrown in callback', function() { +    var eval = this.spyOn(scope, '$eval').andCallThrough(); + +    $defer(function() {throw "Test Error";}); +    expect(eval).wasNotCalled(); + +    $browser.defer.flush(); +    expect(eval).wasCalled(); +  }); +}); diff --git a/test/service/documentSpec.js b/test/service/documentSpec.js new file mode 100644 index 00000000..bd92023d --- /dev/null +++ b/test/service/documentSpec.js @@ -0,0 +1,17 @@ +describe('$document', function() { +  var scope; + +  beforeEach(function(){ +    scope = angular.scope(); +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  it("should inject $document", function(){ +    expect(scope.$service('$document')).toEqual(jqLite(document)); +  }); +}); diff --git a/test/service/exceptionHandlerSpec.js b/test/service/exceptionHandlerSpec.js new file mode 100644 index 00000000..59349065 --- /dev/null +++ b/test/service/exceptionHandlerSpec.js @@ -0,0 +1,23 @@ +describe('$exceptionHandler', function() { +  var scope; + +  beforeEach(function(){ +    scope = angular.scope(); +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  it('should log errors', function(){ +    var scope = createScope({}, {$exceptionHandler: $exceptionHandlerFactory}, +                                {$log: $logMock}), +        $log = scope.$service('$log'), +        $exceptionHandler = scope.$service('$exceptionHandler'); + +    $exceptionHandler('myError'); +    expect($log.error.logs.shift()).toEqual(['myError']); +  }); +}); diff --git a/test/service/hoverSpec.js b/test/service/hoverSpec.js new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/service/hoverSpec.js @@ -0,0 +1 @@ + diff --git a/test/service/invalidWidgetsSpec.js b/test/service/invalidWidgetsSpec.js new file mode 100644 index 00000000..b6b2da61 --- /dev/null +++ b/test/service/invalidWidgetsSpec.js @@ -0,0 +1,39 @@ +describe('$invalidWidgets', function() { +  var scope; + +  beforeEach(function(){ +    scope = angular.scope(); +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  it("should count number of invalid widgets", function(){ +    scope = compile('<input name="price" ng:required ng:validate="number"></input>'); +    jqLite(document.body).append(scope.$element); +    scope.$init(); +    var $invalidWidgets = scope.$service('$invalidWidgets'); +    expect($invalidWidgets.length).toEqual(1); + +    scope.price = 123; +    scope.$eval(); +    expect($invalidWidgets.length).toEqual(0); + +    scope.$element.remove(); +    scope.price = 'abc'; +    scope.$eval(); +    expect($invalidWidgets.length).toEqual(0); + +    jqLite(document.body).append(scope.$element); +    scope.price = 'abcd'; //force revalidation, maybe this should be done automatically? +    scope.$eval(); +    expect($invalidWidgets.length).toEqual(1); + +    jqLite(document.body).html(''); +    scope.$eval(); +    expect($invalidWidgets.length).toEqual(0); +  }); +}); diff --git a/test/service/locationSpec.js b/test/service/locationSpec.js new file mode 100644 index 00000000..050875b1 --- /dev/null +++ b/test/service/locationSpec.js @@ -0,0 +1,299 @@ +describe('$location', function() { +  var scope, $location, $browser; + +  beforeEach(function(){ +    scope = angular.scope(); +    $location = scope.$service('$location'); +    $browser = scope.$service('$browser'); +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  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('should update location when browser url changed', function() { +    var origUrl = $location.href; +    expect(origUrl).toEqual($browser.getUrl()); + +    var newUrl = 'http://somenew/url#foo'; +    $browser.setUrl(newUrl); +    $browser.poll(); +    expect($location.href).toEqual(newUrl); +  }); + + +  it('should update browser at the end of $eval', function() { +    var origBrowserUrl = $browser.getUrl(); +    $location.update('http://www.angularjs.org/'); +    $location.update({path: '/a/b'}); +    expect($location.href).toEqual('http://www.angularjs.org/a/b'); +    expect($browser.getUrl()).toEqual(origBrowserUrl); +    scope.$eval(); +    expect($browser.getUrl()).toEqual('http://www.angularjs.org/a/b'); +  }); + + +  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('should update hash on hashPath or hashSearch update', function() { +    $location.update('http://server/#path?a=b'); +    scope.$eval(); +    $location.update({hashPath: '', hashSearch: {}}); + +    expect($location.hash).toEqual(''); +  }); + + +  it('should update hashPath and hashSearch on $location.hash change upon eval', function(){ +    $location.update('http://server/#path?a=b'); +    scope.$eval(); + +    $location.hash = ''; +    scope.$eval(); + +    expect($location.href).toEqual('http://server/'); +    expect($location.hashPath).toEqual(''); +    expect($location.hashSearch).toEqual({}); +  }); + + +  it('should update hash on $location.hashPath or $location.hashSearch change upon eval', +      function() { +    $location.update('http://server/#path?a=b'); +    scope.$eval(); +    $location.hashPath = ''; +    $location.hashSearch = {}; + +    scope.$eval(); + +    expect($location.href).toEqual('http://server/'); +    expect($location.hash).toEqual(''); +  }); + + +  it('should sync $location upon eval before watches are fired', function(){ +    scope.$location = scope.$service('$location'); //publish to the scope for $watch + +    var log = ''; +    scope.$watch('$location.hash', function(){ +      log += this.$location.hashPath + ';'; +    }); +    expect(log).toEqual(';'); + +    log = ''; +    scope.$location.hash = '/abc'; +    scope.$eval(); +    expect(scope.$location.hash).toEqual('/abc'); +    expect(log).toEqual('/abc;'); +  }); + + +  describe('sync', function() { + +    it('should update hash with escaped hashPath', function() { +      $location.hashPath = 'foo=bar'; +      scope.$eval(); +      expect($location.hash).toBe('foo%3Dbar'); +    }); + + +    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'; + +      scope.$eval(); + +      expect($location).toEqualData({href: 'https://hrefhost:23/hrefpath', +                                     protocol: 'https', +                                     host: 'hrefhost', +                                     port: '23', +                                     path: '/hrefpath', +                                     search: {}, +                                     hash: '', +                                     hashPath: '', +                                     hashSearch: {} +                                    }); +    }); + + +    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'; + +      scope.$eval(); + +      expect($location).toEqualData({href: 'http://host:333/path#hash', +                                     protocol: 'http', +                                     host: 'host', +                                     port: '333', +                                     path: '/path', +                                     search: {}, +                                     hash: 'hash', +                                     hashPath: 'hash', +                                     hashSearch: {} +                                    }); +    }); +  }); + + +  describe('update()', function() { + +    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 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 clear hash when updating to hash-less URL', function() { +      $location.update('http://server'); +      expect($location.href).toBe('http://server'); +      expect($location.hash).toBe(''); +    }); +  }); + + +  describe('updateHash()', function() { + +    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 reset hashSearch when updating with a single string', function() { +      $location.updateHash({foo:'bar'}); //set some initial state for hashSearch + +      $location.updateHash('path'); +      expect($location.hashPath).toEqual('path'); +      expect($location.hashSearch).toEqual({}); +    }); + + +    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 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 update href and hash when updating to empty string', function() { +      $location.updateHash(''); +      expect($location.href).toBe('http://server'); +      expect($location.hash).toBe(''); + +      scope.$eval(); + +      expect($location.href).toBe('http://server'); +      expect($location.hash).toBe(''); +    }); +  }); + + +  describe('URL_MATCH', 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'); +    }); + + +    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[5]).toBeFalsy(); +      expect(match[6]).toEqual('/Users/Shared/misko/work/angular.js/scenario/widgets.html'); +      expect(match[8]).toBeFalsy(); +    }); + + +    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[5]).toBeFalsy(); +      expect(match[6]).toEqual('/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'); + +      match = URL_MATCH.exec('http://host.org#'); +      expect(match[3]).toEqual('host.org'); + +      match = URL_MATCH.exec('http://host.org?'); +      expect(match[3]).toEqual('host.org'); +    }); + + +    it('should match with just "/" path', function() { +      var match = URL_MATCH.exec('http://server/#?book=moby'); + +      expect(match[10]).toEqual('?book=moby'); +    }); +  }); +}); diff --git a/test/service/logSpec.js b/test/service/logSpec.js new file mode 100644 index 00000000..5d8fa0db --- /dev/null +++ b/test/service/logSpec.js @@ -0,0 +1,100 @@ +describe('$log', function() { +  var scope; + +  beforeEach(function(){ +    scope = angular.scope(); +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  it('should use console if present', function(){ +    var logger = ""; +    function log(){ logger+= 'log;'; } +    function warn(){ logger+= 'warn;'; } +    function info(){ logger+= 'info;'; } +    function error(){ logger+= 'error;'; } +    var scope = createScope({}, {$log: $logFactory}, +                                {$exceptionHandler: rethrow, +                                 $window: {console: {log: log, +                                                     warn: warn, +                                                     info: info, +                                                     error: error}}}), +        $log = scope.$service('$log'); + +    $log.log(); +    $log.warn(); +    $log.info(); +    $log.error(); +    expect(logger).toEqual('log;warn;info;error;'); +  }); + + +  it('should use console.log() if other not present', function(){ +    var logger = ""; +    function log(){ logger+= 'log;'; } +    var scope = createScope({}, {$log: $logFactory}, +                                {$window: {console:{log:log}}, +                                 $exceptionHandler: rethrow}); +    var $log = scope.$service('$log'); +    $log.log(); +    $log.warn(); +    $log.info(); +    $log.error(); +    expect(logger).toEqual('log;log;log;log;'); +  }); + + +  it('should use noop if no console', function(){ +    var scope = createScope({}, {$log: $logFactory}, +                                {$window: {}, +                                 $exceptionHandler: rethrow}), +        $log = scope.$service('$log'); +    $log.log(); +    $log.warn(); +    $log.info(); +    $log.error(); +  }); + + +  describe('$log.error', function(){ +    var e, $log, errorArgs; + +    beforeEach(function(){ +      e = new Error(''); +      e.message = undefined; +      e.sourceURL = undefined; +      e.line = undefined; +      e.stack = undefined; + +      $log = $logFactory({console:{error:function(){ +        errorArgs = arguments; +      }}}); +    }); + + +    it('should pass error if does not have trace', function(){ +      $log.error('abc', e); +      expect(errorArgs).toEqual(['abc', e]); +    }); + + +    it('should print stack', function(){ +      e.stack = 'stack'; +      $log.error('abc', e); +      expect(errorArgs).toEqual(['abc', 'stack']); +    }); + + +    it('should print line', function(){ +      e.message = 'message'; +      e.sourceURL = 'sourceURL'; +      e.line = '123'; +      $log.error('abc', e); +      expect(errorArgs).toEqual(['abc', 'message\nsourceURL:123']); +    }); +  }); +}); diff --git a/test/service/resourceSpec.js b/test/service/resourceSpec.js new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/service/resourceSpec.js @@ -0,0 +1 @@ + diff --git a/test/service/routeSpec.js b/test/service/routeSpec.js new file mode 100644 index 00000000..95258cc8 --- /dev/null +++ b/test/service/routeSpec.js @@ -0,0 +1,228 @@ +describe('$route', function() { +  var scope; + +  beforeEach(function(){ +    scope = angular.scope(); +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  it('should route and fire change event', function(){ +    var log = '', +        $location, $route; + +    function BookChapter() { +      this.log = '<init>'; +    } +    scope = compile('<div></div>').$init(); +    $location = scope.$service('$location'); +    $route = scope.$service('$route'); +    $route.when('/Book/:book/Chapter/:chapter', {controller: BookChapter, template:'Chapter.html'}); +    $route.when('/Blank'); +    $route.onChange(function(){ +      log += 'onChange();'; +    }); +    $location.update('http://server#/Book/Moby/Chapter/Intro?p=123'); +    scope.$eval(); +    expect(log).toEqual('onChange();'); +    expect($route.current.params).toEqual({book:'Moby', chapter:'Intro', p:'123'}); +    expect($route.current.scope.log).toEqual('<init>'); +    var lastId = $route.current.scope.$id; + +    log = ''; +    $location.update('http://server#/Blank?ignore'); +    scope.$eval(); +    expect(log).toEqual('onChange();'); +    expect($route.current.params).toEqual({ignore:true}); +    expect($route.current.scope.$id).not.toEqual(lastId); + +    log = ''; +    $location.update('http://server#/NONE'); +    scope.$eval(); +    expect(log).toEqual('onChange();'); +    expect($route.current).toEqual(null); + +    $route.when('/NONE', {template:'instant update'}); +    scope.$eval(); +    expect($route.current.template).toEqual('instant update'); +  }); + + +  it('should return fn registered with onChange()', function() { +    var scope = angular.scope(), +        $route = scope.$service('$route'), +        fn = function() {}; + +    expect($route.onChange(fn)).toBe(fn); +  }); + + +  it('should allow routes to be defined with just templates without controllers', function() { +    var scope = angular.scope(), +        $location = scope.$service('$location'), +        $route = scope.$service('$route'), +        onChangeSpy = jasmine.createSpy('onChange'); + +    $route.when('/foo', {template: 'foo.html'}); +    $route.onChange(onChangeSpy); +    expect($route.current).toBeNull(); +    expect(onChangeSpy).not.toHaveBeenCalled(); + +    $location.updateHash('/foo'); +    scope.$eval(); + +    expect($route.current.template).toEqual('foo.html'); +    expect($route.current.controller).toBeUndefined(); +    expect(onChangeSpy).toHaveBeenCalled(); +  }); + + +  it('should handle unknown routes with "otherwise" route definition', function() { +    var scope = angular.scope(), +        $location = scope.$service('$location'), +        $route = scope.$service('$route'), +        onChangeSpy = jasmine.createSpy('onChange'); + +    function NotFoundCtrl() {this.notFoundProp = 'not found!'} + +    $route.when('/foo', {template: 'foo.html'}); +    $route.otherwise({template: '404.html', controller: NotFoundCtrl}); +    $route.onChange(onChangeSpy); +    expect($route.current).toBeNull(); +    expect(onChangeSpy).not.toHaveBeenCalled(); + +    $location.updateHash('/unknownRoute'); +    scope.$eval(); + +    expect($route.current.template).toBe('404.html'); +    expect($route.current.controller).toBe(NotFoundCtrl); +    expect($route.current.scope.notFoundProp).toBe('not found!'); +    expect(onChangeSpy).toHaveBeenCalled(); + +    onChangeSpy.reset(); +    $location.updateHash('/foo'); +    scope.$eval(); + +    expect($route.current.template).toEqual('foo.html'); +    expect($route.current.controller).toBeUndefined(); +    expect($route.current.scope.notFoundProp).toBeUndefined(); +    expect(onChangeSpy).toHaveBeenCalled(); +  }); + + +  describe('redirection', function() { + +    it('should support redirection via redirectTo property by updating $location', function() { +      var scope = angular.scope(), +          $location = scope.$service('$location'), +          $browser = scope.$service('$browser'), +          $route = scope.$service('$route'), +          onChangeSpy = jasmine.createSpy('onChange'); + +      $route.when('', {redirectTo: '/foo'}); +      $route.when('/foo', {template: 'foo.html'}); +      $route.when('/bar', {template: 'bar.html'}); +      $route.when('/baz', {redirectTo: '/bar'}); +      $route.otherwise({template: '404.html'}); +      $route.onChange(onChangeSpy); +      expect($route.current).toBeNull(); +      expect(onChangeSpy).not.toHaveBeenCalled(); + +      scope.$eval(); //triggers initial route change - match the redirect route +      $browser.defer.flush(); //triger route change - match the route we redirected to + +      expect($location.hash).toBe('/foo'); +      expect($route.current.template).toBe('foo.html'); +      expect(onChangeSpy.callCount).toBe(1); + +      onChangeSpy.reset(); +      $location.updateHash(''); +      scope.$eval(); //match the redirect route + update $browser +      $browser.defer.flush(); //match the route we redirected to + +      expect($location.hash).toBe('/foo'); +      expect($route.current.template).toBe('foo.html'); +      expect(onChangeSpy.callCount).toBe(1); + +      onChangeSpy.reset(); +      $location.updateHash('/baz'); +      scope.$eval(); //match the redirect route + update $browser +      $browser.defer.flush(); //match the route we redirected to + +      expect($location.hash).toBe('/bar'); +      expect($route.current.template).toBe('bar.html'); +      expect(onChangeSpy.callCount).toBe(1); +    }); + + +    it('should interpolate route variables in the redirected hashPath from the original hashPath', +        function() { +      var scope = angular.scope(), +          $location = scope.$service('$location'), +          $browser = scope.$service('$browser'), +          $route = scope.$service('$route'); + +      $route.when('/foo/:id/foo/:subid/:extraId', {redirectTo: '/bar/:id/:subid/23'}); +      $route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'}); +      scope.$eval(); + +      $location.updateHash('/foo/id1/foo/subid3/gah'); +      scope.$eval(); //triggers initial route change - match the redirect route +      $browser.defer.flush(); //triger route change - match the route we redirected to + +      expect($location.hash).toBe('/bar/id1/subid3/23?extraId=gah'); +      expect($route.current.template).toBe('bar.html'); +    }); + + +    it('should interpolate route variables in the redirected hashPath from the original hashSearch', +        function() { +      var scope = angular.scope(), +          $location = scope.$service('$location'), +          $browser = scope.$service('$browser'), +          $route = scope.$service('$route'); + +      $route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'}); +      $route.when('/foo/:id/:extra', {redirectTo: '/bar/:id/:subid/99'}); +      scope.$eval(); + +      $location.hash = '/foo/id3/eId?subid=sid1&appended=true'; +      scope.$eval(); //triggers initial route change - match the redirect route +      $browser.defer.flush(); //triger route change - match the route we redirected to + +      expect($location.hash).toBe('/bar/id3/sid1/99?appended=true&extra=eId'); +      expect($route.current.template).toBe('bar.html'); +    }); + + +    it('should allow custom redirectTo function to be used', function() { +      var scope = angular.scope(), +          $location = scope.$service('$location'), +          $browser = scope.$service('$browser'), +          $route = scope.$service('$route'); + +      $route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'}); +      $route.when('/foo/:id', +                  {redirectTo: customRedirectFn}); +      scope.$eval(); + +      $location.hash = '/foo/id3?subid=sid1&appended=true'; +      scope.$eval(); //triggers initial route change - match the redirect route +      $browser.defer.flush(); //triger route change - match the route we redirected to + +      expect($location.hash).toBe('custom'); + +      function customRedirectFn(routePathParams, hash, hashPath, hashSearch) { +        expect(routePathParams).toEqual({id: 'id3'}); +        expect(hash).toEqual($location.hash); +        expect(hashPath).toEqual($location.hashPath); +        expect(hashSearch).toEqual($location.hashSearch); +        return 'custom'; +      } +    }); +  }); +}); diff --git a/test/service/updateViewSpec.js b/test/service/updateViewSpec.js new file mode 100644 index 00000000..beca355e --- /dev/null +++ b/test/service/updateViewSpec.js @@ -0,0 +1,61 @@ +describe('$updateView', function() { +  var scope, browser, evalCount, $updateView; + +  beforeEach(function(){ +    browser = new MockBrowser(); +    // Pretend that you are real Browser so that we see the delays +    browser.isMock = false; +    browser.defer = jasmine.createSpy('defer'); + +    scope = angular.scope(null, null, {$browser:browser}); +    $updateView = scope.$service('$updateView'); +    scope.$onEval(function(){ evalCount++; }); +    evalCount = 0; +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  it('should eval root scope after a delay', function(){ +    $updateView(); +    expect(evalCount).toEqual(0); +    expect(browser.defer).toHaveBeenCalled(); +    expect(browser.defer.mostRecentCall.args[1]).toEqual(25); +    browser.defer.mostRecentCall.args[0](); +    expect(evalCount).toEqual(1); +  }); + + +  it('should allow changing of delay time', function(){ +    var oldValue = angular.service('$updateView').delay; +    angular.service('$updateView').delay = 50; +    $updateView(); +    expect(evalCount).toEqual(0); +    expect(browser.defer).toHaveBeenCalled(); +    expect(browser.defer.mostRecentCall.args[1]).toEqual(50); +    angular.service('$updateView').delay = oldValue; +  }); + + +  it('should ignore multiple requests for update', function(){ +    $updateView(); +    $updateView(); +    expect(evalCount).toEqual(0); +    expect(browser.defer).toHaveBeenCalled(); +    expect(browser.defer.callCount).toEqual(1); +    browser.defer.mostRecentCall.args[0](); +    expect(evalCount).toEqual(1); +  }); + + +  it('should update immediatelly in test/mock mode', function(){ +    scope = angular.scope(); +    scope.$onEval(function(){ evalCount++; }); +    expect(evalCount).toEqual(0); +    scope.$service('$updateView')(); +    expect(evalCount).toEqual(1); +  }); +}); diff --git a/test/service/windowSpec.js b/test/service/windowSpec.js new file mode 100644 index 00000000..e968f560 --- /dev/null +++ b/test/service/windowSpec.js @@ -0,0 +1,17 @@ +describe('$window', function() { +  var scope; + +  beforeEach(function(){ +    scope = angular.scope(); +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  it("should inject $window", function(){ +    expect(scope.$service('$window')).toBe(window); +  }); +}); diff --git a/test/service/xhr.bulkSpec.js b/test/service/xhr.bulkSpec.js new file mode 100644 index 00000000..89429a91 --- /dev/null +++ b/test/service/xhr.bulkSpec.js @@ -0,0 +1,69 @@ +describe('$xhr.bulk', function() { +  var scope, $browser, $browserXhr, $log, $xhrBulk, $xhrError, log; + +  beforeEach(function(){ +    scope = angular.scope({}, angular.service, { +      '$xhr.error': $xhrError = jasmine.createSpy('$xhr.error'), +      '$log': $log = {} +    }); +    $browser = scope.$service('$browser'); +    $browserXhr = $browser.xhr; +    $xhrBulk = scope.$service('$xhr.bulk'); +    log = ''; +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  function callback(code, response) { +    expect(code).toEqual(200); +    log = log + toJson(response) + ';'; +  } + + +  it('should collect requests', function(){ +    $xhrBulk.urls["/"] = {match:/.*/}; +    $xhrBulk('GET', '/req1', null, callback); +    $xhrBulk('POST', '/req2', {post:'data'}, callback); + +    $browserXhr.expectPOST('/', { +      requests:[{method:'GET',  url:'/req1', data: null}, +                {method:'POST', url:'/req2', data:{post:'data'} }] +    }).respond([ +      {status:200, response:'first'}, +      {status:200, response:'second'} +    ]); +    $xhrBulk.flush(function(){ log += 'DONE';}); +    $browserXhr.flush(); +    expect(log).toEqual('"first";"second";DONE'); +  }); + + +  it('should handle non 200 status code by forwarding to error handler', function(){ +    $xhrBulk.urls['/'] = {match:/.*/}; +    $xhrBulk('GET', '/req1', null, callback); +    $xhrBulk('POST', '/req2', {post:'data'}, callback); + +    $browserXhr.expectPOST('/', { +      requests:[{method:'GET',  url:'/req1', data: null}, +                {method:'POST', url:'/req2', data:{post:'data'} }] +    }).respond([ +      {status:404, response:'NotFound'}, +      {status:200, response:'second'} +    ]); +    $xhrBulk.flush(function(){ log += 'DONE';}); +    $browserXhr.flush(); + +    expect($xhrError).wasCalled(); +    var cb = $xhrError.mostRecentCall.args[0].callback; +    expect(typeof cb).toEqual($function); +    expect($xhrError).wasCalledWith( +        {url:'/req1', method:'GET', data:null, callback:cb}, +        {status:404, response:'NotFound'}); + +    expect(log).toEqual('"second";DONE'); +  }); +}); diff --git a/test/service/xhr.cacheSpec.js b/test/service/xhr.cacheSpec.js new file mode 100644 index 00000000..82b33b72 --- /dev/null +++ b/test/service/xhr.cacheSpec.js @@ -0,0 +1,128 @@ +describe('$xhr.cache', function() { +  var scope, $browser, $browserXhr, cache, log; + +  beforeEach(function(){ +    scope = angular.scope(); +    $browser = scope.$service('$browser'); +    $browserXhr = $browser.xhr; +    cache = scope.$service('$xhr.cache'); +    log = ''; +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  function callback(code, response) { +    expect(code).toEqual(200); +    log = log + toJson(response) + ';'; +  } + + +  it('should cache requests', function(){ +    $browserXhr.expectGET('/url').respond('first'); +    cache('GET', '/url', null, callback); +    $browserXhr.flush(); + +    $browserXhr.expectGET('/url').respond('ERROR'); +    cache('GET', '/url', null, callback); +    $browser.defer.flush(); +    expect(log).toEqual('"first";"first";'); + +    cache('GET', '/url', null, callback, false); +    $browser.defer.flush(); +    expect(log).toEqual('"first";"first";"first";'); +  }); + + +  it('should first return cache request, then return server request', function(){ +    $browserXhr.expectGET('/url').respond('first'); +    cache('GET', '/url', null, callback, true); +    $browserXhr.flush(); + +    $browserXhr.expectGET('/url').respond('ERROR'); +    cache('GET', '/url', null, callback, true); +    $browser.defer.flush(); +    expect(log).toEqual('"first";"first";'); + +    $browserXhr.flush(); +    expect(log).toEqual('"first";"first";"ERROR";'); +  }); + + +  it('should serve requests from cache', function(){ +    cache.data.url = {value:'123'}; +    cache('GET', 'url', null, callback); +    $browser.defer.flush(); +    expect(log).toEqual('"123";'); + +    cache('GET', 'url', null, callback, false); +    $browser.defer.flush(); +    expect(log).toEqual('"123";"123";'); +  }); + + +  it('should keep track of in flight requests and request only once', function(){ +    scope.$service('$xhr.bulk').urls['/bulk'] = { +      match:function(url){ +        return url == '/url'; +      } +    }; +    $browserXhr.expectPOST('/bulk', { +      requests:[{method:'GET',  url:'/url', data: null}] +    }).respond([ +      {status:200, response:'123'} +    ]); +    cache('GET', '/url', null, callback); +    cache('GET', '/url', null, callback); +    cache.delegate.flush(); +    $browserXhr.flush(); +    expect(log).toEqual('"123";"123";'); +  }); + + +  it('should clear cache on non GET', function(){ +    $browserXhr.expectPOST('abc', {}).respond({}); +    cache.data.url = {value:123}; +    cache('POST', 'abc', {}); +    expect(cache.data.url).toBeUndefined(); +  }); + + +  it('should call callback asynchronously for both cache hit and cache miss', function() { +    $browserXhr.expectGET('/url').respond('+'); +    cache('GET', '/url', null, callback); +    expect(log).toEqual(''); //callback hasn't executed + +    $browserXhr.flush(); +    expect(log).toEqual('"+";'); //callback has executed + +    cache('GET', '/url', null, callback); +    expect(log).toEqual('"+";'); //callback hasn't executed + +    $browser.defer.flush(); +    expect(log).toEqual('"+";"+";'); //callback has executed +  }); + + +  it('should call eval after callbacks for both cache hit and cache miss execute', function() { +    var eval = this.spyOn(scope, '$eval').andCallThrough(); + +    $browserXhr.expectGET('/url').respond('+'); +    cache('GET', '/url', null, callback); +    expect(eval).wasNotCalled(); + +    $browserXhr.flush(); +    expect(eval).wasCalled(); + +    eval.reset(); //reset the spy + +    cache('GET', '/url', null, callback); +    expect(eval).wasNotCalled(); + +    $browser.defer.flush(); +    expect(eval).wasCalled(); +  }); +}); diff --git a/test/service/xhr.errorSpec.js b/test/service/xhr.errorSpec.js new file mode 100644 index 00000000..da1b102e --- /dev/null +++ b/test/service/xhr.errorSpec.js @@ -0,0 +1,36 @@ +describe('$xhr.error', function() { +  var scope, $browser, $browserXhr, $xhr, $xhrError, log; + +  beforeEach(function(){ +    scope = angular.scope({}, angular.service, { +      '$xhr.error': $xhrError = jasmine.createSpy('$xhr.error') +    }); +    $browser = scope.$service('$browser'); +    $browserXhr = $browser.xhr; +    $xhr = scope.$service('$xhr'); +    log = ''; +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  function callback(code, response) { +    expect(code).toEqual(200); +    log = log + toJson(response) + ';'; +  } + + +  it('should handle non 200 status codes by forwarding to error handler', function(){ +    $browserXhr.expectPOST('/req', 'MyData').respond(500, 'MyError'); +    $xhr('POST', '/req', 'MyData', callback); +    $browserXhr.flush(); +    var cb = $xhrError.mostRecentCall.args[0].callback; +    expect(typeof cb).toEqual($function); +    expect($xhrError).wasCalledWith( +        {url:'/req', method:'POST', data:'MyData', callback:cb}, +        {status:500, body:'MyError'}); +  }); +}); diff --git a/test/service/xhrSpec.js b/test/service/xhrSpec.js new file mode 100644 index 00000000..35861a92 --- /dev/null +++ b/test/service/xhrSpec.js @@ -0,0 +1,47 @@ +describe('$xhr', function() { +  var scope, $browser, $browserXhr, $log, $xhr, log; + +  beforeEach(function(){ +    scope = angular.scope({}, angular.service, { '$log': $log = {} }); +    $browser = scope.$service('$browser'); +    $browserXhr = $browser.xhr; +    $xhr = scope.$service('$xhr'); +    log = ''; +  }); + + +  afterEach(function(){ +    dealoc(scope); +  }); + + +  function callback(code, response) { +    expect(code).toEqual(200); +    log = log + toJson(response) + ';'; +  } + + +  it('should forward the request to $browser and decode JSON', function(){ +    $browserXhr.expectGET('/reqGET').respond('first'); +    $browserXhr.expectGET('/reqGETjson').respond('["second"]'); +    $browserXhr.expectPOST('/reqPOST', {post:'data'}).respond('third'); + +    $xhr('GET', '/reqGET', null, callback); +    $xhr('GET', '/reqGETjson', null, callback); +    $xhr('POST', '/reqPOST', {post:'data'}, callback); + +    $browserXhr.flush(); + +    expect(log).toEqual('"third";["second"];"first";'); +  }); + + +  it('should handle exceptions in callback', function(){ +    $log.error = jasmine.createSpy('$log.error'); +    $browserXhr.expectGET('/reqGET').respond('first'); +    $xhr('GET', '/reqGET', null, function(){ throw "MyException"; }); +    $browserXhr.flush(); + +    expect($log.error).wasCalledWith("MyException"); +  }); +}); diff --git a/test/servicesSpec.js b/test/servicesSpec.js deleted file mode 100644 index 0186684e..00000000 --- a/test/servicesSpec.js +++ /dev/null @@ -1,1081 +0,0 @@ -describe("service", function(){ -  var scope, $xhrError, $log, mockServices, $browser, $browserXhr, $xhrBulk, $xhr; - -  beforeEach(function(){ -    $xhrError = jasmine.createSpy('$xhr.error'); -    $log = {}; -    scope = createScope({}, angularService, { -      '$xhr.error': $xhrError, -      '$log': $log -    }); -    $browser = scope.$service('$browser'); -    $browserXhr = $browser.xhr; -    $xhrBulk = scope.$service('$xhr.bulk'); -    $xhr = scope.$service('$xhr'); -  }); - -  afterEach(function(){ -    dealoc(scope); -  }); - - - -  it("should inject $window", function(){ -    expect(scope.$service('$window')).toEqual(window); -  }); - -  describe("$log", function(){ -    it('should use console if present', function(){ -      var logger = ""; -      function log(){ logger+= 'log;'; } -      function warn(){ logger+= 'warn;'; } -      function info(){ logger+= 'info;'; } -      function error(){ logger+= 'error;'; } -      var scope = createScope({}, {$log: $logFactory}, -                                  {$exceptionHandler: rethrow, -                                   $window: {console: {log: log, -                                                       warn: warn, -                                                       info: info, -                                                       error: error}}}), -          $log = scope.$service('$log'); - -      $log.log(); -      $log.warn(); -      $log.info(); -      $log.error(); -      expect(logger).toEqual('log;warn;info;error;'); -    }); - -    it('should use console.log() if other not present', function(){ -      var logger = ""; -      function log(){ logger+= 'log;'; } -      var scope = createScope({}, {$log: $logFactory}, -                                  {$window: {console:{log:log}}, -                                   $exceptionHandler: rethrow}); -      var $log = scope.$service('$log'); -      $log.log(); -      $log.warn(); -      $log.info(); -      $log.error(); -      expect(logger).toEqual('log;log;log;log;'); -    }); - -    it('should use noop if no console', function(){ -      var scope = createScope({}, {$log: $logFactory}, -                                  {$window: {}, -                                   $exceptionHandler: rethrow}), -          $log = scope.$service('$log'); -      $log.log(); -      $log.warn(); -      $log.info(); -      $log.error(); -    }); - -    describe('error', function(){ -      var e, $log, errorArgs; -      beforeEach(function(){ -        e = new Error(''); -        e.message = undefined; -        e.sourceURL = undefined; -        e.line = undefined; -        e.stack = undefined; - -        $log = $logFactory({console:{error:function(){ -          errorArgs = arguments; -        }}}); -      }); - -      it('should pass error if does not have trace', function(){ -        $log.error('abc', e); -        expect(errorArgs).toEqual(['abc', e]); -      }); - -      it('should print stack', function(){ -        e.stack = 'stack'; -        $log.error('abc', e); -        expect(errorArgs).toEqual(['abc', 'stack']); -      }); - -      it('should print line', function(){ -        e.message = 'message'; -        e.sourceURL = 'sourceURL'; -        e.line = '123'; -        $log.error('abc', e); -        expect(errorArgs).toEqual(['abc', 'message\nsourceURL:123']); -      }); - -    }); - -  }); - -  describe("$exceptionHandler", function(){ -    it('should log errors', function(){ -      var scope = createScope({}, {$exceptionHandler: $exceptionHandlerFactory}, -                                  {$log: $logMock}), -          $log = scope.$service('$log'), -          $exceptionHandler = scope.$service('$exceptionHandler'); - -      $exceptionHandler('myError'); -      expect($log.error.logs.shift()).toEqual(['myError']); -    }); -  }); - -  describe("$location", function(){ -    var $location; - -    beforeEach(function() { -      $location = scope.$service('$location'); -    }); - - -    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('should update location when browser url changed', function() { -      var origUrl = $location.href; -      expect(origUrl).toEqual($browser.getUrl()); - -      var newUrl = 'http://somenew/url#foo'; -      $browser.setUrl(newUrl); -      $browser.poll(); -      expect($location.href).toEqual(newUrl); -    }); - - -    it('should update browser at the end of $eval', function() { -      var origBrowserUrl = $browser.getUrl(); -      $location.update('http://www.angularjs.org/'); -      $location.update({path: '/a/b'}); -      expect($location.href).toEqual('http://www.angularjs.org/a/b'); -      expect($browser.getUrl()).toEqual(origBrowserUrl); -      scope.$eval(); -      expect($browser.getUrl()).toEqual('http://www.angularjs.org/a/b'); -    }); - - -    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('should update hash on hashPath or hashSearch update', function() { -      $location.update('http://server/#path?a=b'); -      scope.$eval(); -      $location.update({hashPath: '', hashSearch: {}}); - -      expect($location.hash).toEqual(''); -    }); - - -    it('should update hashPath and hashSearch on $location.hash change upon eval', function(){ -      $location.update('http://server/#path?a=b'); -      scope.$eval(); - -      $location.hash = ''; -      scope.$eval(); - -      expect($location.href).toEqual('http://server/'); -      expect($location.hashPath).toEqual(''); -      expect($location.hashSearch).toEqual({}); -    }); - - -    it('should update hash on $location.hashPath or $location.hashSearch change upon eval', -        function() { -      $location.update('http://server/#path?a=b'); -      scope.$eval(); -      $location.hashPath = ''; -      $location.hashSearch = {}; - -      scope.$eval(); - -      expect($location.href).toEqual('http://server/'); -      expect($location.hash).toEqual(''); -    }); - - -    it('should sync $location upon eval before watches are fired', function(){ -      scope.$location = scope.$service('$location'); //publish to the scope for $watch - -      var log = ''; -      scope.$watch('$location.hash', function(){ -        log += this.$location.hashPath + ';'; -      }); -      expect(log).toEqual(';'); - -      log = ''; -      scope.$location.hash = '/abc'; -      scope.$eval(); -      expect(scope.$location.hash).toEqual('/abc'); -      expect(log).toEqual('/abc;'); -    }); - - -    describe('sync', function() { -      it('should update hash with escaped hashPath', function() { -        $location.hashPath = 'foo=bar'; -        scope.$eval(); -        expect($location.hash).toBe('foo%3Dbar'); -      }); - - -      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'; - -        scope.$eval(); - -        expect($location).toEqualData({href: 'https://hrefhost:23/hrefpath', -                                       protocol: 'https', -                                       host: 'hrefhost', -                                       port: '23', -                                       path: '/hrefpath', -                                       search: {}, -                                       hash: '', -                                       hashPath: '', -                                       hashSearch: {} -                                      }); -      }); - - -      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'; - -        scope.$eval(); - -        expect($location).toEqualData({href: 'http://host:333/path#hash', -                                       protocol: 'http', -                                       host: 'host', -                                       port: '333', -                                       path: '/path', -                                       search: {}, -                                       hash: 'hash', -                                       hashPath: 'hash', -                                       hashSearch: {} -                                      }); -      }); -    }); - -    describe('update()', function() { -      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 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 clear hash when updating to hash-less URL', function() { -        $location.update('http://server'); -        expect($location.href).toBe('http://server'); -        expect($location.hash).toBe(''); -      }); -    }); - - -    describe('updateHash()', function() { -      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 reset hashSearch when updating with a single string', function() { -        $location.updateHash({foo:'bar'}); //set some initial state for hashSearch - -        $location.updateHash('path'); -        expect($location.hashPath).toEqual('path'); -        expect($location.hashSearch).toEqual({}); -      }); - -      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 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 update href and hash when updating to empty string', function() { -        $location.updateHash(''); -        expect($location.href).toBe('http://server'); -        expect($location.hash).toBe(''); - -        scope.$eval(); - -        expect($location.href).toBe('http://server'); -        expect($location.hash).toBe(''); -      }); -    }); -  }); - -  describe("$invalidWidgets", function(){ -    it("should count number of invalid widgets", function(){ -      scope = compile('<input name="price" ng:required ng:validate="number"></input>'); -      jqLite(document.body).append(scope.$element); -      scope.$init(); -      var $invalidWidgets = scope.$service('$invalidWidgets'); -      expect($invalidWidgets.length).toEqual(1); - -      scope.price = 123; -      scope.$eval(); -      expect($invalidWidgets.length).toEqual(0); - -      scope.$element.remove(); -      scope.price = 'abc'; -      scope.$eval(); -      expect($invalidWidgets.length).toEqual(0); - -      jqLite(document.body).append(scope.$element); -      scope.price = 'abcd'; //force revalidation, maybe this should be done automatically? -      scope.$eval(); -      expect($invalidWidgets.length).toEqual(1); - -      jqLite(document.body).html(''); -      scope.$eval(); -      expect($invalidWidgets.length).toEqual(0); -    }); -  }); - - -  describe("$route", function(){ -    it('should route and fire change event', function(){ -      var log = '', -          $location, $route; - -      function BookChapter() { -        this.log = '<init>'; -      } -      scope = compile('<div></div>').$init(); -      $location = scope.$service('$location'); -      $route = scope.$service('$route'); -      $route.when('/Book/:book/Chapter/:chapter', {controller: BookChapter, template:'Chapter.html'}); -      $route.when('/Blank'); -      $route.onChange(function(){ -        log += 'onChange();'; -      }); -      $location.update('http://server#/Book/Moby/Chapter/Intro?p=123'); -      scope.$eval(); -      expect(log).toEqual('onChange();'); -      expect($route.current.params).toEqual({book:'Moby', chapter:'Intro', p:'123'}); -      expect($route.current.scope.log).toEqual('<init>'); -      var lastId = $route.current.scope.$id; - -      log = ''; -      $location.update('http://server#/Blank?ignore'); -      scope.$eval(); -      expect(log).toEqual('onChange();'); -      expect($route.current.params).toEqual({ignore:true}); -      expect($route.current.scope.$id).not.toEqual(lastId); - -      log = ''; -      $location.update('http://server#/NONE'); -      scope.$eval(); -      expect(log).toEqual('onChange();'); -      expect($route.current).toEqual(null); - -      $route.when('/NONE', {template:'instant update'}); -      scope.$eval(); -      expect($route.current.template).toEqual('instant update'); -    }); - -    it('should return fn registered with onChange()', function() { -      var scope = angular.scope(), -          $route = scope.$service('$route'), -          fn = function() {}; - -      expect($route.onChange(fn)).toBe(fn); -    }); - -    it('should allow routes to be defined with just templates without controllers', function() { -      var scope = angular.scope(), -          $location = scope.$service('$location'), -          $route = scope.$service('$route'), -          onChangeSpy = jasmine.createSpy('onChange'); - -      $route.when('/foo', {template: 'foo.html'}); -      $route.onChange(onChangeSpy); -      expect($route.current).toBeNull(); -      expect(onChangeSpy).not.toHaveBeenCalled(); - -      $location.updateHash('/foo'); -      scope.$eval(); - -      expect($route.current.template).toEqual('foo.html'); -      expect($route.current.controller).toBeUndefined(); -      expect(onChangeSpy).toHaveBeenCalled(); -    }); - -    it('should handle unknown routes with "otherwise" route definition', function() { -      var scope = angular.scope(), -          $location = scope.$service('$location'), -          $route = scope.$service('$route'), -          onChangeSpy = jasmine.createSpy('onChange'); - -      function NotFoundCtrl() {this.notFoundProp = 'not found!'} - -      $route.when('/foo', {template: 'foo.html'}); -      $route.otherwise({template: '404.html', controller: NotFoundCtrl}); -      $route.onChange(onChangeSpy); -      expect($route.current).toBeNull(); -      expect(onChangeSpy).not.toHaveBeenCalled(); - -      $location.updateHash('/unknownRoute'); -      scope.$eval(); - -      expect($route.current.template).toBe('404.html'); -      expect($route.current.controller).toBe(NotFoundCtrl); -      expect($route.current.scope.notFoundProp).toBe('not found!'); -      expect(onChangeSpy).toHaveBeenCalled(); - -      onChangeSpy.reset(); -      $location.updateHash('/foo'); -      scope.$eval(); - -      expect($route.current.template).toEqual('foo.html'); -      expect($route.current.controller).toBeUndefined(); -      expect($route.current.scope.notFoundProp).toBeUndefined(); -      expect(onChangeSpy).toHaveBeenCalled(); -    }); -  }); - - -  describe('redirection', function() { - -    it('should support redirection via redirectTo property by updating $location', function() { -      var scope = angular.scope(), -          $location = scope.$service('$location'), -          $browser = scope.$service('$browser'), -          $route = scope.$service('$route'), -          onChangeSpy = jasmine.createSpy('onChange'); - -      $route.when('', {redirectTo: '/foo'}); -      $route.when('/foo', {template: 'foo.html'}); -      $route.when('/bar', {template: 'bar.html'}); -      $route.when('/baz', {redirectTo: '/bar'}); -      $route.otherwise({template: '404.html'}); -      $route.onChange(onChangeSpy); -      expect($route.current).toBeNull(); -      expect(onChangeSpy).not.toHaveBeenCalled(); - -      scope.$eval(); //triggers initial route change - match the redirect route -      $browser.defer.flush(); //triger route change - match the route we redirected to - -      expect($location.hash).toBe('/foo'); -      expect($route.current.template).toBe('foo.html'); -      expect(onChangeSpy.callCount).toBe(1); - -      onChangeSpy.reset(); -      $location.updateHash(''); -      scope.$eval(); //match the redirect route + update $browser -      $browser.defer.flush(); //match the route we redirected to - -      expect($location.hash).toBe('/foo'); -      expect($route.current.template).toBe('foo.html'); -      expect(onChangeSpy.callCount).toBe(1); - -      onChangeSpy.reset(); -      $location.updateHash('/baz'); -      scope.$eval(); //match the redirect route + update $browser -      $browser.defer.flush(); //match the route we redirected to - -      expect($location.hash).toBe('/bar'); -      expect($route.current.template).toBe('bar.html'); -      expect(onChangeSpy.callCount).toBe(1); -    }); - -    it('should interpolate route variables in the redirected hashPath from the original hashPath', -        function() { -      var scope = angular.scope(), -          $location = scope.$service('$location'), -          $browser = scope.$service('$browser'), -          $route = scope.$service('$route'); - -      $route.when('/foo/:id/foo/:subid/:extraId', {redirectTo: '/bar/:id/:subid/23'}); -      $route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'}); -      scope.$eval(); - -      $location.updateHash('/foo/id1/foo/subid3/gah'); -      scope.$eval(); //triggers initial route change - match the redirect route -      $browser.defer.flush(); //triger route change - match the route we redirected to - -      expect($location.hash).toBe('/bar/id1/subid3/23?extraId=gah'); -      expect($route.current.template).toBe('bar.html'); -    }); - -    it('should interpolate route variables in the redirected hashPath from the original hashSearch', -        function() { -      var scope = angular.scope(), -          $location = scope.$service('$location'), -          $browser = scope.$service('$browser'), -          $route = scope.$service('$route'); - -      $route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'}); -      $route.when('/foo/:id/:extra', {redirectTo: '/bar/:id/:subid/99'}); -      scope.$eval(); - -      $location.hash = '/foo/id3/eId?subid=sid1&appended=true'; -      scope.$eval(); //triggers initial route change - match the redirect route -      $browser.defer.flush(); //triger route change - match the route we redirected to - -      expect($location.hash).toBe('/bar/id3/sid1/99?appended=true&extra=eId'); -      expect($route.current.template).toBe('bar.html'); -    }); - -    it('should allow custom redirectTo function to be used', function() { -      var scope = angular.scope(), -          $location = scope.$service('$location'), -          $browser = scope.$service('$browser'), -          $route = scope.$service('$route'); - -      $route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'}); -      $route.when('/foo/:id', -                  {redirectTo: customRedirectFn}); -      scope.$eval(); - -      $location.hash = '/foo/id3?subid=sid1&appended=true'; -      scope.$eval(); //triggers initial route change - match the redirect route -      $browser.defer.flush(); //triger route change - match the route we redirected to - -      expect($location.hash).toBe('custom'); - -      function customRedirectFn(routePathParams, hash, hashPath, hashSearch) { -        expect(routePathParams).toEqual({id: 'id3'}); -        expect(hash).toEqual($location.hash); -        expect(hashPath).toEqual($location.hashPath); -        expect(hashSearch).toEqual($location.hashSearch); -        return 'custom'; -      } -    }); -  }); - - -  describe('$defer', function() { -    var $defer, $exceptionHandler; - -    beforeEach(function(){ -      scope = createScope({}, angularService, { -        '$exceptionHandler': jasmine.createSpy('$exceptionHandler') -      }); - -      $browser = scope.$service('$browser'); -      $defer = scope.$service('$defer'); -      $exceptionHandler = scope.$service('$exceptionHandler'); -    }); - - -    it('should delegate functions to $browser.defer', function() { -      var counter = 0; -      $defer(function() { counter++; }); - -      expect(counter).toBe(0); - -      $browser.defer.flush(); -      expect(counter).toBe(1); - -      $browser.defer.flush(); //does nothing -      expect(counter).toBe(1); - -      expect($exceptionHandler).not.toHaveBeenCalled(); -    }); - - -    it('should delegate exception to the $exceptionHandler service', function() { -      $defer(function() {throw "Test Error";}); -      expect($exceptionHandler).not.toHaveBeenCalled(); - -      $browser.defer.flush(); -      expect($exceptionHandler).toHaveBeenCalledWith("Test Error"); -    }); - - -    it('should call eval after each callback is executed', function() { -      var eval = this.spyOn(scope, '$eval').andCallThrough(); - -      $defer(function() {}); -      expect(eval).wasNotCalled(); - -      $browser.defer.flush(); -      expect(eval).wasCalled(); - -      eval.reset(); //reset the spy; - -      $defer(function() {}); -      $defer(function() {}); -      $browser.defer.flush(); -      expect(eval.callCount).toBe(2); -    }); - - -    it('should call eval even if an exception is thrown in callback', function() { -      var eval = this.spyOn(scope, '$eval').andCallThrough(); - -      $defer(function() {throw "Test Error";}); -      expect(eval).wasNotCalled(); - -      $browser.defer.flush(); -      expect(eval).wasCalled(); -    }); -  }); - - -  describe('$xhr', function(){ -    var log; -    function callback(code, response) { -      expect(code).toEqual(200); -      log = log + toJson(response) + ';'; -    } - -    beforeEach(function(){ -      log = ''; -    }); - -    it('should forward the request to $browser and decode JSON', function(){ -      $browserXhr.expectGET('/reqGET').respond('first'); -      $browserXhr.expectGET('/reqGETjson').respond('["second"]'); -      $browserXhr.expectPOST('/reqPOST', {post:'data'}).respond('third'); - -      $xhr('GET', '/reqGET', null, callback); -      $xhr('GET', '/reqGETjson', null, callback); -      $xhr('POST', '/reqPOST', {post:'data'}, callback); - -      $browserXhr.flush(); - -      expect(log).toEqual('"third";["second"];"first";'); -    }); - -    it('should handle non 200 status codes by forwarding to error handler', function(){ -      $browserXhr.expectPOST('/req', 'MyData').respond(500, 'MyError'); -      $xhr('POST', '/req', 'MyData', callback); -      $browserXhr.flush(); -      var cb = $xhrError.mostRecentCall.args[0].callback; -      expect(typeof cb).toEqual($function); -      expect($xhrError).wasCalledWith( -          {url:'/req', method:'POST', data:'MyData', callback:cb}, -          {status:500, body:'MyError'}); -    }); - -    it('should handle exceptions in callback', function(){ -      $log.error = jasmine.createSpy('$log.error'); -      $browserXhr.expectGET('/reqGET').respond('first'); -      $xhr('GET', '/reqGET', null, function(){ throw "MyException"; }); -      $browserXhr.flush(); - -      expect($log.error).wasCalledWith("MyException"); -    }); - -    describe('bulk', function(){ -      it('should collect requests', function(){ -        $xhrBulk.urls["/"] = {match:/.*/}; -        $xhrBulk('GET', '/req1', null, callback); -        $xhrBulk('POST', '/req2', {post:'data'}, callback); - -        $browserXhr.expectPOST('/', { -          requests:[{method:'GET',  url:'/req1', data: null}, -                    {method:'POST', url:'/req2', data:{post:'data'} }] -        }).respond([ -          {status:200, response:'first'}, -          {status:200, response:'second'} -        ]); -        $xhrBulk.flush(function(){ log += 'DONE';}); -        $browserXhr.flush(); -        expect(log).toEqual('"first";"second";DONE'); -      }); - -      it('should handle non 200 status code by forwarding to error handler', function(){ -        $xhrBulk.urls['/'] = {match:/.*/}; -        $xhrBulk('GET', '/req1', null, callback); -        $xhrBulk('POST', '/req2', {post:'data'}, callback); - -        $browserXhr.expectPOST('/', { -          requests:[{method:'GET',  url:'/req1', data: null}, -                    {method:'POST', url:'/req2', data:{post:'data'} }] -        }).respond([ -          {status:404, response:'NotFound'}, -          {status:200, response:'second'} -        ]); -        $xhrBulk.flush(function(){ log += 'DONE';}); -        $browserXhr.flush(); - -        expect($xhrError).wasCalled(); -        var cb = $xhrError.mostRecentCall.args[0].callback; -        expect(typeof cb).toEqual($function); -        expect($xhrError).wasCalledWith( -            {url:'/req1', method:'GET', data:null, callback:cb}, -            {status:404, response:'NotFound'}); - -        expect(log).toEqual('"second";DONE'); -      }); -    }); - -    describe('cache', function(){ -      var cache; -      beforeEach(function(){ cache = scope.$service('$xhr.cache'); }); - -      it('should cache requests', function(){ -        $browserXhr.expectGET('/url').respond('first'); -        cache('GET', '/url', null, callback); -        $browserXhr.flush(); - -        $browserXhr.expectGET('/url').respond('ERROR'); -        cache('GET', '/url', null, callback); -        $browser.defer.flush(); -        expect(log).toEqual('"first";"first";'); - -        cache('GET', '/url', null, callback, false); -        $browser.defer.flush(); -        expect(log).toEqual('"first";"first";"first";'); -      }); - -      it('should first return cache request, then return server request', function(){ -        $browserXhr.expectGET('/url').respond('first'); -        cache('GET', '/url', null, callback, true); -        $browserXhr.flush(); - -        $browserXhr.expectGET('/url').respond('ERROR'); -        cache('GET', '/url', null, callback, true); -        $browser.defer.flush(); -        expect(log).toEqual('"first";"first";'); - -        $browserXhr.flush(); -        expect(log).toEqual('"first";"first";"ERROR";'); -      }); - -      it('should serve requests from cache', function(){ -        cache.data.url = {value:'123'}; -        cache('GET', 'url', null, callback); -        $browser.defer.flush(); -        expect(log).toEqual('"123";'); - -        cache('GET', 'url', null, callback, false); -        $browser.defer.flush(); -        expect(log).toEqual('"123";"123";'); -      }); - -      it('should keep track of in flight requests and request only once', function(){ -        scope.$service('$xhr.bulk').urls['/bulk'] = { -          match:function(url){ -            return url == '/url'; -          } -        }; -        $browserXhr.expectPOST('/bulk', { -          requests:[{method:'GET',  url:'/url', data: null}] -        }).respond([ -          {status:200, response:'123'} -        ]); -        cache('GET', '/url', null, callback); -        cache('GET', '/url', null, callback); -        cache.delegate.flush(); -        $browserXhr.flush(); -        expect(log).toEqual('"123";"123";'); -      }); - -      it('should clear cache on non GET', function(){ -        $browserXhr.expectPOST('abc', {}).respond({}); -        cache.data.url = {value:123}; -        cache('POST', 'abc', {}); -        expect(cache.data.url).toBeUndefined(); -      }); - -      it('should call callback asynchronously for both cache hit and cache miss', function() { -        $browserXhr.expectGET('/url').respond('+'); -        cache('GET', '/url', null, callback); -        expect(log).toEqual(''); //callback hasn't executed - -        $browserXhr.flush(); -        expect(log).toEqual('"+";'); //callback has executed - -        cache('GET', '/url', null, callback); -        expect(log).toEqual('"+";'); //callback hasn't executed - -        $browser.defer.flush(); -        expect(log).toEqual('"+";"+";'); //callback has executed -      }); - -      it('should call eval after callbacks for both cache hit and cache miss execute', function() { -        var eval = this.spyOn(scope, '$eval').andCallThrough(); - -        $browserXhr.expectGET('/url').respond('+'); -        cache('GET', '/url', null, callback); -        expect(eval).wasNotCalled(); - -        $browserXhr.flush(); -        expect(eval).wasCalled(); - -        eval.reset(); //reset the spy - -        cache('GET', '/url', null, callback); -        expect(eval).wasNotCalled(); - -        $browser.defer.flush(); -        expect(eval).wasCalled(); -      }); -    }); - -  }); - - -  describe('$cookies', function() { - -    var scope, $browser; - -    beforeEach(function() { -      $browser = new MockBrowser(); -      $browser.cookieHash['preexisting'] = 'oldCookie'; -      scope = createScope(null, angularService, {$browser: $browser}); -      scope.$cookies = scope.$service('$cookies'); -    }); - - -    it('should provide access to existing cookies via object properties and keep them in sync', -        function(){ -      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); - -      // access internal cookie storage of the browser mock directly to simulate behavior of -      // document.cookie -      $browser.cookieHash['brandNew'] = 'cookie'; -      $browser.poll(); - -      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie'}); - -      $browser.cookieHash['brandNew'] = 'cookie2'; -      $browser.poll(); -      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie2'}); - -      delete $browser.cookieHash['brandNew']; -      $browser.poll(); -      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); -    }); - - -    it('should create or update a cookie when a value is assigned to a property', function() { -      scope.$cookies.oatmealCookie = 'nom nom'; -      scope.$eval(); - -      expect($browser.cookies()). -        toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'}); - -      scope.$cookies.oatmealCookie = 'gone'; -      scope.$eval(); - -      expect($browser.cookies()). -        toEqual({'preexisting': 'oldCookie', 'oatmealCookie': 'gone'}); -    }); - - -    it('should drop or reset any cookie that was set to a non-string value', function() { -      scope.$cookies.nonString = [1, 2, 3]; -      scope.$cookies.nullVal = null; -      scope.$cookies.undefVal = undefined; -      scope.$cookies.preexisting = function(){}; -      scope.$eval(); -      expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'}); -      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); -    }); - - -    it('should remove a cookie when a $cookies property is deleted', function() { -      scope.$cookies.oatmealCookie = 'nom nom'; -      scope.$eval(); -      $browser.poll(); -      expect($browser.cookies()). -        toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'}); - -      delete scope.$cookies.oatmealCookie; -      scope.$eval(); - -      expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'}); -    }); - - -    it('should drop or reset cookies that browser refused to store', function() { -      var i, longVal; - -      for (i=0; i<5000; i++) { -        longVal += '*'; -      } - -      //drop if no previous value -      scope.$cookies.longCookie = longVal; -      scope.$eval(); -      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); - - -      //reset if previous value existed -      scope.$cookies.longCookie = 'shortVal'; -      scope.$eval(); -      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'}); -      scope.$cookies.longCookie = longVal; -      scope.$eval(); -      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'}); -    }); -  }); - - -  describe('$cookieStore', function() { - -    it('should serialize objects to json', function() { -      scope.$service('$cookieStore').put('objectCookie', {id: 123, name: 'blah'}); -      scope.$eval(); //force eval in test -      expect($browser.cookies()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'}); -    }); - - -    it('should deserialize json to object', function() { -      $browser.cookies('objectCookie', '{"id":123,"name":"blah"}'); -      $browser.poll(); -      expect(scope.$service('$cookieStore').get('objectCookie')).toEqual({id: 123, name: 'blah'}); -    }); - - -    it('should delete objects from the store when remove is called', function() { -      scope.$service('$cookieStore').put('gonner', { "I'll":"Be Back"}); -      scope.$eval(); //force eval in test -      expect($browser.cookies()).toEqual({'gonner': '{"I\'ll":"Be Back"}'}); -    }); - -  }); - - -  describe('URL_MATCH', 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'); -    }); - -    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[5]).toBeFalsy(); -      expect(match[6]).toEqual('/Users/Shared/misko/work/angular.js/scenario/widgets.html'); -      expect(match[8]).toBeFalsy(); -    }); - -    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[5]).toBeFalsy(); -      expect(match[6]).toEqual('/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'); - -      match = URL_MATCH.exec('http://host.org#'); -      expect(match[3]).toEqual('host.org'); - -      match = URL_MATCH.exec('http://host.org?'); -      expect(match[3]).toEqual('host.org'); -    }); - -    it('should match with just "/" path', function() { -      var match = URL_MATCH.exec('http://server/#?book=moby'); - -      expect(match[10]).toEqual('?book=moby'); -    }); -  }); - -  describe('$updateView', function(){ -    var scope, browser, evalCount, $updateView; - -    beforeEach(function(){ -      browser = new MockBrowser(); -      // Pretend that you are real Browser so that we see the delays -      browser.isMock = false; -      browser.defer = jasmine.createSpy('defer'); - -      scope = angular.scope(null, null, {$browser:browser}); -      $updateView = scope.$service('$updateView'); -      scope.$onEval(function(){ evalCount++; }); -      evalCount = 0; -    }); - -    it('should eval root scope after a delay', function(){ -      $updateView(); -      expect(evalCount).toEqual(0); -      expect(browser.defer).toHaveBeenCalled(); -      expect(browser.defer.mostRecentCall.args[1]).toEqual(25); -      browser.defer.mostRecentCall.args[0](); -      expect(evalCount).toEqual(1); -    }); - -    it('should allow changing of delay time', function(){ -      var oldValue = angular.service('$updateView').delay; -      angular.service('$updateView').delay = 50; -      $updateView(); -      expect(evalCount).toEqual(0); -      expect(browser.defer).toHaveBeenCalled(); -      expect(browser.defer.mostRecentCall.args[1]).toEqual(50); -      angular.service('$updateView').delay = oldValue; -    }); - -    it('should ignore multiple requests for update', function(){ -      $updateView(); -      $updateView(); -      expect(evalCount).toEqual(0); -      expect(browser.defer).toHaveBeenCalled(); -      expect(browser.defer.callCount).toEqual(1); -      browser.defer.mostRecentCall.args[0](); -      expect(evalCount).toEqual(1); -    }); - -    it('should update immediatelly in test/mock mode', function(){ -      scope = angular.scope(); -      scope.$onEval(function(){ evalCount++; }); -      expect(evalCount).toEqual(0); -      scope.$service('$updateView')(); -      expect(evalCount).toEqual(1); -    }); -  }); -}); diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js index 12fe7b64..9aa3b95d 100644 --- a/test/widgetsSpec.js +++ b/test/widgetsSpec.js @@ -601,23 +601,8 @@ describe("widget", function(){        expect(element.text()).toEqual('one');      }); -    it("should match urls", function(){ -      var scope = angular.compile('<ng:switch on="url" using="route:params"><div ng:switch-when="/Book/:name">{{params.name}}</div></ng:switch>'); -      scope.url = '/Book/Moby'; -      scope.$init(); -      expect(scope.$element.text()).toEqual('Moby'); -      dealoc(scope); -    }); - -    it("should match sandwich ids", function(){ -      var scope = {}; -      var match = angular.widget('NG:SWITCH').route.call(scope, '/a/123/b', '/a/:id'); -      expect(match).toBeFalsy(); -    }); -      it('should call change on switch', function(){        var scope = angular.compile('<ng:switch on="url" change="name=\'works\'"><div ng:switch-when="a">{{name}}</div></ng:switch>'); -      var cleared = false;        scope.url = 'a';        scope.$init();        expect(scope.name).toEqual(undefined); | 
