aboutsummaryrefslogtreecommitdiffstats
path: root/test/ngMock/angular-mocksSpec.js
diff options
context:
space:
mode:
authorJulie2013-09-13 12:47:05 -0700
committerVojta Jina2013-10-07 13:45:40 -0700
commit2b5ce84fca7b41fca24707e163ec6af84bc12e83 (patch)
treed3fbcfd3c7e2e62fe60df6faa9823abda57b9bd7 /test/ngMock/angular-mocksSpec.js
parenta80e96cea184b392505f0a292785a5c66d45e165 (diff)
downloadangular.js-2b5ce84fca7b41fca24707e163ec6af84bc12e83.tar.bz2
feat($interval): add a service wrapping setInterval
The $interval service simplifies creating and testing recurring tasks. This service does not increment $browser's outstanding request count, which means that scenario tests and Protractor tests will not timeout when a site uses a polling function registered by $interval. Provides a workaround for #2402. For unit tests, repeated tasks can be controlled using ngMock$interval's tick(), tickNext(), and tickAll() functions.
Diffstat (limited to 'test/ngMock/angular-mocksSpec.js')
-rw-r--r--test/ngMock/angular-mocksSpec.js235
1 files changed, 235 insertions, 0 deletions
diff --git a/test/ngMock/angular-mocksSpec.js b/test/ngMock/angular-mocksSpec.js
index 1a4290e0..851f7803 100644
--- a/test/ngMock/angular-mocksSpec.js
+++ b/test/ngMock/angular-mocksSpec.js
@@ -283,6 +283,241 @@ describe('ngMock', function() {
});
+ describe('$interval', function() {
+ it('should run tasks repeatedly', inject(function($interval) {
+ var counter = 0;
+ $interval(function() { counter++; }, 1000);
+
+ expect(counter).toBe(0);
+
+ $interval.flush(1000);
+ expect(counter).toBe(1);
+
+ $interval.flush(1000);
+
+ expect(counter).toBe(2);
+ }));
+
+
+ it('should call $apply after each task is executed', inject(function($interval, $rootScope) {
+ var applySpy = spyOn($rootScope, '$apply').andCallThrough();
+
+ $interval(noop, 1000);
+ expect(applySpy).not.toHaveBeenCalled();
+
+ $interval.flush(1000);
+ expect(applySpy).toHaveBeenCalledOnce();
+
+ applySpy.reset();
+
+ $interval(noop, 1000);
+ $interval(noop, 1000);
+ $interval.flush(1000);
+ expect(applySpy.callCount).toBe(3);
+ }));
+
+
+ it('should NOT call $apply if invokeApply is set to false',
+ inject(function($interval, $rootScope) {
+ var applySpy = spyOn($rootScope, '$apply').andCallThrough();
+
+ $interval(noop, 1000, 0, false);
+ expect(applySpy).not.toHaveBeenCalled();
+
+ $interval.flush(2000);
+ expect(applySpy).not.toHaveBeenCalled();
+ }));
+
+
+ it('should allow you to specify the delay time', inject(function($interval) {
+ var counter = 0;
+ $interval(function() { counter++; }, 123);
+
+ expect(counter).toBe(0);
+
+ $interval.flush(122);
+ expect(counter).toBe(0);
+
+ $interval.flush(1);
+ expect(counter).toBe(1);
+ }));
+
+
+ it('should allow you to specify a number of iterations', inject(function($interval) {
+ var counter = 0;
+ $interval(function() {counter++}, 1000, 2);
+
+ $interval.flush(1000);
+ expect(counter).toBe(1);
+ $interval.flush(1000);
+ expect(counter).toBe(2);
+ $interval.flush(1000);
+ expect(counter).toBe(2);
+ }));
+
+
+ describe('flush', function() {
+ it('should move the clock forward by the specified time', inject(function($interval) {
+ var counterA = 0;
+ var counterB = 0;
+ $interval(function() { counterA++; }, 100);
+ $interval(function() { counterB++; }, 401);
+
+ $interval.flush(200);
+ expect(counterA).toEqual(2);
+
+ $interval.flush(201);
+ expect(counterA).toEqual(4);
+ expect(counterB).toEqual(1);
+ }));
+ });
+
+
+ it('should return a promise which will be updated with the count on each iteration',
+ inject(function($interval) {
+ var log = [],
+ promise = $interval(function() { log.push('tick'); }, 1000);
+
+ promise.then(function(value) { log.push('promise success: ' + value); },
+ function(err) { log.push('promise error: ' + err); },
+ function(note) { log.push('promise update: ' + note); });
+ expect(log).toEqual([]);
+
+ $interval.flush(1000);
+ expect(log).toEqual(['tick', 'promise update: 0']);
+
+ $interval.flush(1000);
+ expect(log).toEqual(['tick', 'promise update: 0', 'tick', 'promise update: 1']);
+ }));
+
+
+ it('should return a promise which will be resolved after the specified number of iterations',
+ inject(function($interval) {
+ var log = [],
+ promise = $interval(function() { log.push('tick'); }, 1000, 2);
+
+ promise.then(function(value) { log.push('promise success: ' + value); },
+ function(err) { log.push('promise error: ' + err); },
+ function(note) { log.push('promise update: ' + note); });
+ expect(log).toEqual([]);
+
+ $interval.flush(1000);
+ expect(log).toEqual(['tick', 'promise update: 0']);
+ $interval.flush(1000);
+
+ expect(log).toEqual([
+ 'tick', 'promise update: 0', 'tick', 'promise update: 1', 'promise success: 2']);
+
+ }));
+
+
+ describe('exception handling', function() {
+ beforeEach(module(function($exceptionHandlerProvider) {
+ $exceptionHandlerProvider.mode('log');
+ }));
+
+
+ it('should delegate exception to the $exceptionHandler service', inject(
+ function($interval, $exceptionHandler) {
+ $interval(function() { throw "Test Error"; }, 1000);
+ expect($exceptionHandler.errors).toEqual([]);
+
+ $interval.flush(1000);
+ expect($exceptionHandler.errors).toEqual(["Test Error"]);
+
+ $interval.flush(1000);
+ expect($exceptionHandler.errors).toEqual(["Test Error", "Test Error"]);
+ }));
+
+
+ it('should call $apply even if an exception is thrown in callback', inject(
+ function($interval, $rootScope) {
+ var applySpy = spyOn($rootScope, '$apply').andCallThrough();
+
+ $interval(function() { throw "Test Error"; }, 1000);
+ expect(applySpy).not.toHaveBeenCalled();
+
+ $interval.flush(1000);
+ expect(applySpy).toHaveBeenCalled();
+ }));
+
+
+ it('should still update the interval promise when an exception is thrown',
+ inject(function($interval) {
+ var log = [],
+ promise = $interval(function() { throw "Some Error"; }, 1000);
+
+ promise.then(function(value) { log.push('promise success: ' + value); },
+ function(err) { log.push('promise error: ' + err); },
+ function(note) { log.push('promise update: ' + note); });
+ $interval.flush(1000);
+
+ expect(log).toEqual(['promise update: 0']);
+ }));
+ });
+
+
+ describe('cancel', function() {
+ it('should cancel tasks', inject(function($interval) {
+ var task1 = jasmine.createSpy('task1', 1000),
+ task2 = jasmine.createSpy('task2', 1000),
+ task3 = jasmine.createSpy('task3', 1000),
+ promise1, promise3;
+
+ promise1 = $interval(task1, 200);
+ $interval(task2, 1000);
+ promise3 = $interval(task3, 333);
+
+ $interval.cancel(promise3);
+ $interval.cancel(promise1);
+ $interval.flush(1000);
+
+ expect(task1).not.toHaveBeenCalled();
+ expect(task2).toHaveBeenCalledOnce();
+ expect(task3).not.toHaveBeenCalled();
+ }));
+
+
+ it('should cancel the promise', inject(function($interval, $rootScope) {
+ var promise = $interval(noop, 1000),
+ log = [];
+ promise.then(function(value) { log.push('promise success: ' + value); },
+ function(err) { log.push('promise error: ' + err); },
+ function(note) { log.push('promise update: ' + note); });
+ expect(log).toEqual([]);
+
+ $interval.flush(1000);
+ $interval.cancel(promise);
+ $interval.flush(1000);
+ $rootScope.$apply(); // For resolving the promise -
+ // necessary since q uses $rootScope.evalAsync.
+
+ expect(log).toEqual(['promise update: 0', 'promise error: canceled']);
+ }));
+
+
+ it('should return true if a task was successfully canceled', inject(function($interval) {
+ var task1 = jasmine.createSpy('task1'),
+ task2 = jasmine.createSpy('task2'),
+ promise1, promise2;
+
+ promise1 = $interval(task1, 1000, 1);
+ $interval.flush(1000);
+ promise2 = $interval(task2, 1000, 1);
+
+ expect($interval.cancel(promise1)).toBe(false);
+ expect($interval.cancel(promise2)).toBe(true);
+ }));
+
+
+ it('should not throw a runtime exception when given an undefined promise',
+ inject(function($interval) {
+ expect($interval.cancel()).toBe(false);
+ }));
+ });
+ });
+
+
describe('defer', function() {
var browser, log;
beforeEach(inject(function($browser) {