2014-03-28 16 views
8

ich diese Störung erhalte, wenn ich den folgenden Test:Typeerror: kann nicht lesen Eigenschaft ‚defaultPrevented‘ undefinierter

it('should call pauseAnimationInterval if in focus', inject(function(SearchBoxData, intervalManager, $timeout){ 
    SearchBoxData.init_array = []; 
    SearchBoxData.inFocus = true; 
    SearchBoxData.init(intervalManager); 
    console.log(intervalManager.pauseTimeout); 
    console.log(intervalManager.pauseTimeoutTime); 
    console.log($timeout); 
    $timeout.flush(intervalManager.pauseTimeoutTime+1); 
    expect(rootScope.$broadcast).toHaveBeenCalledWith('onPauseInterval', intervalManager.loopIndex); 
})); 

Es bricht auf $timeout.flush(intervalManager.pauseTimeoutTime+1); Die $ Timeout Methode wird in der intervalManager.pauseAnimationInterval() genannt, die im Inneren ist SearchBoxData.init(intervalManager) :

intervalManager.pauseAnimationInterval = function(){ 

    intervalManager.safeCancel(intervalManager.continueInterval); 
    intervalManager.safeCancel(intervalManager.initInterval); 
    intervalManager.initInterval = null; 
    intervalManager.continueInterval = null; 

    intervalManager.pauseTimeout = $timeout(function() { 
    if(intervalManager.inFocus === true){ 
     intervalManager.loopIndex += 1; 
     if(intervalManager.loopIndex >= intervalManager.maxLoopIndex){ 
     intervalManager.loopIndex = 0; 
     } 
     $rootScope.$broadcast("onPauseInterval", intervalManager.loopIndex); 
     intervalManager.continueAnimationInterval(); 
    }else{ 
     // Important condition: retry after the timeout if no focus 
     // main reason of glitch 
     intervalManager.pauseAnimationInterval(); 
    } 
    }, intervalManager.pauseTimeoutTime); 

}; 

Ich bekam diesen Fehler vorher nicht, ich bin nicht sicher, was ich falsch gemacht habe.

Update: Hier ist ein Stacktrace mit unminified Version von AngularJS:

at /Users/foo/projects/bar/vendor/assets/javascripts/angular.js:9268:88 
at Scope.$eval (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:11986:28) 
at Scope.$digest (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:11812:31) 
at Scope.$apply (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:12092:24) 
at Object.fn (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:13627:36) 
at Function.self.defer.flush (/Users/foo/projects/bar/spec/javascripts/lib/angular/angular-mocks.js:126:32) 
at Function.$delegate.flush (/Users/foo/projects/bar/spec/javascripts/lib/angular/angular-mocks.js:1689:20) 
at null.<anonymous> (/Users/foo/projects/bar/spec/javascripts/unit/services/searchboxdata_service_spec.js:71:16) 

Update 2: Ich habe es zurück auf die Injektion des SearchBoxData Fabrik zurückgeführt. Ich bin mir nicht sicher, was daran falsch ist. Das einfache Injizieren verursacht den Fehler, wenn ich eine $ timeout-Instanz erzeuge und die flush-Methode verwende.

Update 3: Ich bemerkte, dass dies passiert, wenn ich $ location oder $ route in eine der Abhängigkeiten injizieren (indirekte, passiert es mit einigen grundlegenden Service, den ich überall verwende).

Update 4: Hier ist ein Plünderer, um es zu reproduzieren! http://plnkr.co/edit/7XweXI?p=info

+0

Traurig über diese Antwort, offensichtlich nicht genug Aufmerksamkeit schenken. Werde später nochmal schauen;) – bluehallu

+0

Hast du eine Geige oder einen Plünderer für diesen versagenden Test? – dmahapatro

+0

@dmahapatro Ich schaffte einen Plünderer, der den Fehler reproduziert. Siehe meine Bearbeitung. –

Antwort

25

Umfangsereignisse, die $ broadcast() 'd oder $ emit()' sind, sind synchron und geben das Ereignisobjekt zurück, wenn sie fertig sind.

Einige Dinge in Angular hängen vom zurückgegebenen Ereignisobjekt ab, z. B. ngRoute.

Also, was Sie tun können, um dies zu beheben, ist einfach hinzufügen andCallThrough(), wenn Sie Ihren Spion erstellen, so dass es die ursprüngliche Funktion aufruft und einen Rückgabewert ergibt.

Alternativ können Sie andCallFake() verwenden, um eine falsche Funktion zu verwenden, die alles zurückgeben kann, was Sie möchten, wenn Sie das echte $ broadcast nicht verwenden möchten.

Beispiel:

beforeEach(function(){ 
    module('MyApp'); 
    inject(function($injector){ 
    rootScope = $injector.get('$rootScope'); 
    spyOn(rootScope,'$broadcast').andCallThrough(); // will prevent the reference error 
    }) 
}); 
+1

Vielen Dank @chronicsalsa, dieses Problem verfolgte mich seit Tagen. –

+0

Guter Fang. Ich hätte das ohne den fraglichen Plünderer nicht bekommen. :) Wie wir wissen, ist ein gut angegebenes Problem zur Hälfte gelöst. ;) – dmahapatro

+8

Beachten Sie, dass in Jasmine 2.0 und höher die Syntax 'and.callThrough();' –

Verwandte Themen