diff options
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); |
