isLoadingBarInjected = (doc) -> injected = false divs = angular.element(doc).find('div') for i in divs if angular.element(i).attr('id') is 'loading-bar' injected = true break return injected flush = null describe 'loadingBarInterceptor Service', -> $http = $httpBackend = $document = $timeout = result = loadingBar = $animate = null response = {message:'OK'} endpoint = '/service' beforeEach -> module 'ngAnimateMock', 'chieffancypants.loadingBar', (cfpLoadingBarProvider) -> loadingBar = cfpLoadingBarProvider return result = null inject (_$http_, _$httpBackend_, _$document_, _$timeout_, _$animate_) -> $http = _$http_ $httpBackend = _$httpBackend_ $document = _$document_ $timeout = _$timeout_ $animate = _$animate_ # Angular 1.4 removed triggerCalbacks(), so try them both: flush = () -> $animate.flush && $animate.flush() $animate.triggerCallbacks && $animate.triggerCallbacks() beforeEach -> this.addMatchers toBeBetween: (high, low) -> if low > high temp = low low = high high = temp return this.actual > low && this.actual < high afterEach -> $httpBackend.verifyNoOutstandingRequest() $timeout.verifyNoPendingTasks() it 'should not increment if the response is cached in a cacheFactory', inject (cfpLoadingBar, $cacheFactory) -> cache = $cacheFactory('loading-bar') $httpBackend.expectGET(endpoint).respond response $http.get(endpoint, cache: cache).then (data) -> result = data expect(cfpLoadingBar.status()).toBe 0 $timeout.flush() $timeout.flush() $httpBackend.flush(1) expect(cfpLoadingBar.status()).toBe 1 cfpLoadingBar.complete() # set as complete $timeout.flush() flush() $http.get(endpoint, cache: cache).then (data) -> result = data # no need to flush $httpBackend since the response is cached expect(cfpLoadingBar.status()).toBe 0 $httpBackend.verifyNoOutstandingRequest() $timeout.flush() # loading bar is animated, so flush timeout it 'should not increment if the response is cached using $http.defaults.cache', inject (cfpLoadingBar, $cacheFactory) -> $http.defaults.cache = $cacheFactory('loading-bar') $httpBackend.expectGET(endpoint).respond response $http.get(endpoint).then (data) -> result = data expect(cfpLoadingBar.status()).toBe 0 $timeout.flush() $timeout.flush() $httpBackend.flush(1) expect(cfpLoadingBar.status()).toBe 1 cfpLoadingBar.complete() # set as complete $timeout.flush() flush() $http.get(endpoint).then (data) -> result = data # no need to flush $httpBackend since the response is cached expect(cfpLoadingBar.status()).toBe 0 $httpBackend.verifyNoOutstandingRequest() $timeout.flush() # loading bar is animated, so flush timeout it 'should not increment if the response is cached', inject (cfpLoadingBar) -> $httpBackend.expectGET(endpoint).respond response $http.get(endpoint, cache: true).then (data) -> result = data expect(cfpLoadingBar.status()).toBe 0 $timeout.flush() $timeout.flush() $httpBackend.flush(1) expect(cfpLoadingBar.status()).toBe 1 cfpLoadingBar.complete() # set as complete $timeout.flush() flush() $http.get(endpoint, cache: true).then (data) -> result = data # no need to flush $httpBackend since the response is cached expect(cfpLoadingBar.status()).toBe 0 $httpBackend.verifyNoOutstandingRequest() $timeout.flush() # loading bar is animated, so flush timeout it 'should use default cache when $http.defaults.cache is true', inject (cfpLoadingBar, $cacheFactory) -> # $http.defaults.cache = $cacheFactory('loading-bar') $http.defaults.cache = true $httpBackend.expectGET(endpoint).respond response $http.get(endpoint).then (data) -> result = data expect(cfpLoadingBar.status()).toBe 0 $timeout.flush() $timeout.flush() $httpBackend.flush(1) expect(cfpLoadingBar.status()).toBe 1 cfpLoadingBar.complete() # set as complete $timeout.flush() flush() $http.get(endpoint).then (data) -> result = data # no need to flush $httpBackend since the response is cached expect(cfpLoadingBar.status()).toBe 0 $httpBackend.verifyNoOutstandingRequest() $timeout.flush() # loading bar is animated, so flush timeout it 'should not cache when the request is a POST', inject (cfpLoadingBar) -> $httpBackend.expectPOST(endpoint).respond response $http.post(endpoint, {message: 'post'}).then (data) -> result = data expect(cfpLoadingBar.status()).toBe 0 $timeout.flush() $timeout.flush() $httpBackend.flush(1) expect(cfpLoadingBar.status()).toBe 1 $timeout.flush() flush() $httpBackend.expectPOST(endpoint).respond response $http.post(endpoint, {message: 'post'}).then (data) -> result = data expect(cfpLoadingBar.status()).toBe 0 $timeout.flush() $timeout.flush() $httpBackend.flush() expect(cfpLoadingBar.status()).toBe 1 $timeout.flush() it 'should increment the loading bar when not all requests have been recieved', inject (cfpLoadingBar) -> $httpBackend.expectGET(endpoint).respond response $httpBackend.expectGET(endpoint).respond response $http.get(endpoint).then (data) -> result = data $http.get(endpoint).then (data) -> result = data expect(cfpLoadingBar.status()).toBe 0 $timeout.flush() $timeout.flush() $httpBackend.flush(1) expect(cfpLoadingBar.status()).toBe 0.5 $httpBackend.flush() expect(cfpLoadingBar.status()).toBe 1 $timeout.flush() # loading bar is animated, so flush timeout it 'should count http errors as responses so the loading bar can complete', inject (cfpLoadingBar) -> # $httpBackend.expectGET(endpoint).respond response $httpBackend.expectGET(endpoint).respond 401 $httpBackend.expectGET(endpoint).respond 401 $http.get(endpoint) $http.get(endpoint) expect(cfpLoadingBar.status()).toBe 0 $timeout.flush() $timeout.flush() $httpBackend.flush(1) expect(cfpLoadingBar.status()).toBe 0.5 $httpBackend.flush() expect(cfpLoadingBar.status()).toBe 1 $timeout.flush() it 'should insert the loadingbar into the DOM when a request is sent', inject (cfpLoadingBar) -> $httpBackend.expectGET(endpoint).respond response $httpBackend.expectGET(endpoint).respond response $http.get(endpoint) $http.get(endpoint) $httpBackend.flush(1) $timeout.flush() # flush the latencyThreshold timeout expect(isLoadingBarInjected($document.find(cfpLoadingBar.parentSelector))).toBe true $httpBackend.flush() $timeout.flush() it 'should insert the loadingbar as the last children of the parent container', inject (cfpLoadingBar) -> $httpBackend.expectGET(endpoint).respond response $httpBackend.expectGET(endpoint).respond response $http.get(endpoint) $http.get(endpoint) $httpBackend.flush(1) $timeout.flush() # flush the latencyThreshold timeout parent = $document.find(cfpLoadingBar.parentSelector)[0] children = parent.childNodes expect(children[children.length - 1].id).toBe 'loading-bar-spinner' expect(children[children.length - 2].id).toBe 'loading-bar' $httpBackend.flush() $timeout.flush() it 'should remove the loading bar when all requests have been received', inject (cfpLoadingBar) -> $httpBackend.expectGET(endpoint).respond response $httpBackend.expectGET(endpoint).respond response $http.get(endpoint) $http.get(endpoint) $httpBackend.flush(1) $timeout.flush() # flush the latencyThreshold timeout expect(isLoadingBarInjected($document.find(cfpLoadingBar.parentSelector))).toBe true $httpBackend.flush() $timeout.flush() expect(isLoadingBarInjected($document.find(cfpLoadingBar.parentSelector))).toBe false it 'should get and set status', inject (cfpLoadingBar) -> cfpLoadingBar.start() $timeout.flush() cfpLoadingBar.set(0.4) expect(cfpLoadingBar.status()).toBe 0.4 cfpLoadingBar.set(0.9) expect(cfpLoadingBar.status()).toBe 0.9 cfpLoadingBar.complete() $timeout.flush() it 'should increment things randomly', inject (cfpLoadingBar) -> cfpLoadingBar.start() $timeout.flush() # increments between 3 - 6% cfpLoadingBar.set(0.1) lbar = angular.element(document.getElementById('loading-bar')) width = lbar.children().css('width').slice(0, -1) $timeout.flush() width2 = lbar.children().css('width').slice(0, -1) expect(width2).toBeGreaterThan width expect(width2 - width).toBeBetween(3, 6) cfpLoadingBar.set(0.2) lbar = angular.element(document.getElementById('loading-bar')) width = lbar.children().css('width').slice(0, -1) $timeout.flush() width2 = lbar.children().css('width').slice(0, -1) expect(width2).toBeGreaterThan width expect(width2 - width).toBeBetween(3, 6) # increments between 0 - 3% cfpLoadingBar.set(0.25) lbar = angular.element(document.getElementById('loading-bar')) width = lbar.children().css('width').slice(0, -1) $timeout.flush() width2 = lbar.children().css('width').slice(0, -1) expect(width2).toBeGreaterThan width expect(width2 - width).toBeBetween(0, 3) cfpLoadingBar.set(0.5) lbar = angular.element(document.getElementById('loading-bar')) width = lbar.children().css('width').slice(0, -1) $timeout.flush() width2 = lbar.children().css('width').slice(0, -1) expect(width2).toBeGreaterThan width expect(width2 - width).toBeBetween(0, 3) # increments between 0 - 2% cfpLoadingBar.set(0.65) lbar = angular.element(document.getElementById('loading-bar')) width = lbar.children().css('width').slice(0, -1) $timeout.flush() width2 = lbar.children().css('width').slice(0, -1) expect(width2).toBeGreaterThan width expect(width2 - width).toBeBetween(0, 2) cfpLoadingBar.set(0.75) lbar = angular.element(document.getElementById('loading-bar')) width = lbar.children().css('width').slice(0, -1) $timeout.flush() width2 = lbar.children().css('width').slice(0, -1) expect(width2).toBeGreaterThan width expect(width2 - width).toBeBetween(0, 2) # increments 0.5% cfpLoadingBar.set(0.9) lbar = angular.element(document.getElementById('loading-bar')) width = lbar.children().css('width').slice(0, -1) $timeout.flush() width2 = lbar.children().css('width').slice(0, -1) expect(width2).toBeGreaterThan width expect(width2 - width).toBe 0.5 cfpLoadingBar.set(0.97) lbar = angular.element(document.getElementById('loading-bar')) width = lbar.children().css('width').slice(0, -1) $timeout.flush() width2 = lbar.children().css('width').slice(0, -1) expect(width2).toBeGreaterThan width expect(width2 - width).toBe 0.5 # stops incrementing: cfpLoadingBar.set(0.99) lbar = angular.element(document.getElementById('loading-bar')) width = lbar.children().css('width').slice(0, -1) $timeout.flush() width2 = lbar.children().css('width').slice(0, -1) expect(width2).toBe width cfpLoadingBar.complete() $timeout.flush() it 'should not set the status if the loading bar has not yet been started', inject (cfpLoadingBar) -> cfpLoadingBar.set(0.5) expect(cfpLoadingBar.status()).toBe 0 cfpLoadingBar.set(0.3) expect(cfpLoadingBar.status()).toBe 0 cfpLoadingBar.start() cfpLoadingBar.set(0.3) expect(cfpLoadingBar.status()).toBe 0.3 cfpLoadingBar.complete() $timeout.flush() it 'should broadcast started and completed events', inject (cfpLoadingBar, $rootScope) -> startedEventCalled = false completedEventCalled = false $rootScope.$on 'cfpLoadingBar:started', (event) -> startedEventCalled = true $rootScope.$on 'cfpLoadingBar:completed', (event) -> completedEventCalled = true expect(startedEventCalled).toBe false expect(completedEventCalled).toBe false cfpLoadingBar.start() expect(startedEventCalled).toBe true cfpLoadingBar.complete() expect(completedEventCalled).toBe true $timeout.flush() it 'should debounce the calls to start()', inject (cfpLoadingBar, $rootScope) -> startedEventCalled = 0 $rootScope.$on 'cfpLoadingBar:started', (event) -> startedEventCalled += 1 cfpLoadingBar.start() expect(startedEventCalled).toBe 1 cfpLoadingBar.start() expect(startedEventCalled).toBe 1 # Should still be one, as complete was never called: cfpLoadingBar.complete() $timeout.flush() flush() cfpLoadingBar.start() expect(startedEventCalled).toBe 2 cfpLoadingBar.complete() $timeout.flush() it 'should ignore requests when ignoreLoadingBar is true', inject (cfpLoadingBar) -> $httpBackend.expectGET(endpoint).respond response $http.get(endpoint, {ignoreLoadingBar: true}) $httpBackend.flush() injected = isLoadingBarInjected $document.find(cfpLoadingBar.parentSelector) expect(injected).toBe false $timeout.flush() it 'should ignore responses when ignoreLoadingBar is true (#70)', inject (cfpLoadingBar) -> $httpBackend.expectGET(endpoint).respond response $httpBackend.expectGET('/service2').respond response $http.get(endpoint, {ignoreLoadingBar: true}) $http.get('/service2') expect(cfpLoadingBar.status()).toBe 0 $httpBackend.flush(1) # flush only the ignored request expect(cfpLoadingBar.status()).toBe 0 $timeout.flush() $httpBackend.flush() expect(cfpLoadingBar.status()).toBe 1 $timeout.flush() # loading bar is animated, so flush timeout it 'should ignore errors when ignoreLoadingBar is true (#70)', inject (cfpLoadingBar) -> $httpBackend.expectGET(endpoint).respond 400 $httpBackend.expectGET('/service2').respond 400 $http.get(endpoint, {ignoreLoadingBar: true}) $http.get('/service2') expect(cfpLoadingBar.status()).toBe 0 $httpBackend.flush(1) # flush only the ignored request expect(cfpLoadingBar.status()).toBe 0 $timeout.flush() $httpBackend.flush() expect(cfpLoadingBar.status()).toBe 1 $timeout.flush() # loading bar is animated, so flush timeout describe 'LoadingBar only', -> cfpLoadingBar = $document = $timeout = $animate = null beforeEach -> module 'cfp.loadingBar', 'ngAnimateMock' inject (_$http_, _$httpBackend_, _$document_, _$timeout_, _$animate_, _cfpLoadingBar_) -> $timeout = _$timeout_ $document = _$document_ $animate = _$animate_ cfpLoadingBar = _cfpLoadingBar_ it 'should be capable of being used alone', -> # just a simple quick test to make sure: cfpLoadingBar.start() $timeout.flush() # test setting progress cfpLoadingBar.set(0.4) expect(cfpLoadingBar.status()).toBe 0.4 # make sure it was injected into the DOM: expect(isLoadingBarInjected($document.find(cfpLoadingBar.parentSelector))).toBe true cfpLoadingBar.set(0.9) expect(cfpLoadingBar.status()).toBe 0.9 # test the complete call, which should remove it from the DOM cfpLoadingBar.complete() $timeout.flush() expect(isLoadingBarInjected($document.find(cfpLoadingBar.parentSelector))).toBe false it 'should start after multiple calls to complete()', -> cfpLoadingBar.start() $timeout.flush() expect(isLoadingBarInjected($document.find(cfpLoadingBar.parentSelector))).toBe true cfpLoadingBar.complete() cfpLoadingBar.complete() cfpLoadingBar.start() $timeout.flush() expect(isLoadingBarInjected($document.find(cfpLoadingBar.parentSelector))).toBe true cfpLoadingBar.complete() $timeout.flush() flush() expect(isLoadingBarInjected($document.find(cfpLoadingBar.parentSelector))).toBe false describe 'Interceptor tests', -> provider = $http = $httpBackend = $log = null endpoint = '/service' response = {message:'OK'} describe 'Success response', -> beforeEach -> module 'chieffancypants.loadingBar', ($httpProvider) -> provider = $httpProvider provider.interceptors.push -> response: (resp) -> return null return inject (_$http_, _$httpBackend_, _$log_) -> $http = _$http_ $httpBackend = _$httpBackend_ $log = _$log_ it 'should detect poorly implemented interceptors and warn accordingly', -> expect($log.error.logs.length).toBe 0 $httpBackend.expectGET(endpoint).respond 204 $http.get(endpoint) $httpBackend.flush() expect($log.error.logs.length).toBe 1 expect($log.error.logs).toContain ['Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50'] describe 'Error response', -> beforeEach -> module 'chieffancypants.loadingBar', ($httpProvider) -> provider = $httpProvider provider.interceptors.push ($q) -> responseError: (resp) -> delete resp.config $q.reject(resp); return inject (_$http_, _$httpBackend_, _$log_) -> $http = _$http_ $httpBackend = _$httpBackend_ $log = _$log_ it 'should detect poorly implemented interceptors and warn accordingly', -> expect($log.error.logs.length).toBe 0 $httpBackend.expectGET(endpoint).respond 500 $http.get(endpoint) $httpBackend.flush() expect($log.error.logs.length).toBe 1 expect($log.error.logs).toContain ['Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50']