2015-08-13 11 views
7

Mam dyrektywę kątową "zegar" i Próbuję napisać test jednostkowy, aby sprawdzić, czy zegar faktycznie interwał $ zbliża się do przyszłego czasu (tj .: 2 minuty, patrząc na element.text()). Mam test przejścia bieżącego czasu, teraz chcę przetestować, czy pokaże to w przyszłości za pośrednictwem $interval.flush. Wydaje mi się, że $interval.flush tak naprawdę nie posuwa się naprzód.

Czy mogę prosić o dwie odpowiedzi:

  • Jak przetestować urządzenia, jeśli $interval pożarów?
  • Dlaczego $interval.flush nie wydaje się przesuwać numeru Date()?

Obserwuję wytyczne z tych stanowisk:

A related po zasugerował użycie Jasmine kpi, które nie sądzę jest już konieczne.

Podobny problem:

HTML

<mydatething format="EEEE, MMMM d" interval="1000" timezone="notused"></mydatething> 

Dyrektywa

myApp.directive('mydatething', ['$interval', 'dateFilter', function ($interval, dateFilter) { 
    return { 
    restrict: "AE", 
    scope: { 
     format: '@', 
     interval: '@' 
    }, 
    template: '', // the template is the Date() output 
    link: function (scope, element, attrs) { 

     // scope expects format, interval and timezone 
     var clockid; 
     var clockinterval = scope.interval; 
     var dateformat = scope.format; 
     var clocktimezone = scope.timezone; 

     // DOM update function 
     function updateClock() { 
     element.text(dateFilter(new Date(), dateformat)); 
     } 

     // Instantiate clock 
     updateClock(); 
     clockid = $interval(updateClock, clockinterval); // fixed 

     // For cancelling 
     scope.$on('$destroy', function() { 
     $interval.cancel(clockid); 
     }); 

     // Separate listener for locale change, manually refresh clock format 
     scope.$on('$localeChangeSuccess', function() { 
     updateClock(); 
     }) 
    } 
    }; 
}]); 

TEST UNIT

describe("tsdate directive", function(){ 
    var elem, scope, $interval, dateFilter; 
    beforeEach(module('tsApp')); 
    beforeEach(inject(function(_$rootScope_, _$interval_, _$compile_, _dateFilter_){ 
    $compile = _$compile_; 
    dateFilter = _dateFilter_; 
    $interval = _$interval_; 
    $rootScope = _$rootScope_; 
    scope = $rootScope.$new(); 

    elem = angular.element('<mydatething format="h:mm a" interval="15000"></mydatething>'); 
    elem = $compile(elem)(scope); 
    scope.$digest(); 

    })); 
    describe('on clock start', function() { 
    it('to show the current date', function() { 
     var currentdate = dateFilter(new Date(), elem.isolateScope().format); 
     expect(elem.text()).toBe(currentdate); 
     // this passes 
    }); 
    it('that it updates the clock', function() { 
     var futurems = 120000; // 2 minutes 
     var futuredate = dateFilter(new Date().getTime() + futurems, elem.isolateScope().format) 
     $interval.flush(futurems); 
     expect(elem.text()).toBe(futuredate); 
    // this fails 
    }); 
    }); 

}); 

TERMINAL

PhantomJS 1.9.8 (Mac OS X) mydatething directive on clock start that it updates the clock FAILED 
    Expected '3:55' to be '3:57'. 

Console.log ujawnia The var jest 2 minuty zwiększany, ale że elem.text() pozostaje aktualny czas.

+0

Czy to działa? – Winnemucca

+0

Tak i nie, mogę przetestować funkcję updateClock(), aby sprawdzić, czy działa ona zgodnie z oczekiwaniami, ale nie warto było zagłębiać się w wykonanie testu X minut, aby sprawdzić, czy zegar będzie odzwierciedlał X min w przyszłości. Zostałem refaktoryzowany, aby updateClock otrzymał nową datę, zamiast ją wygenerować. W związku z tym mogę spyOn updateClock, aby zobaczyć, czy uruchamia się w określonym przedziale i aby sprawdzić, czy aktualizacja updateClock jest aktualizowana, jeśli przekażę mu przyszłej zmiennej daty. W pewnym sensie js "Data" jest poza zakresem, jest to oprogramowanie własne komputera, zakładamy, że zrobili oni swoją należytą staranność. – efwjames

Odpowiedz

4

UWAGA zanim zacznę:

masz błąd w kodzie dyrektywy. Podczas wywoływania interwału $ przekazujesz obiekt funkcji jako pierwszy parametr. Bez nawiasów.

// Do this 
clockid = $interval(updateClock, clockinterval); 

// Not this 
clockid = $interval(updateClock(), clockinterval); 

Zobacz różnicę na plunker

drugie, nazywając $ interval.flush powoduje przerwy do przodu przez liczbę milisekund, ale to nie ma wpływu na wewnętrzny zegar Javascript. Ponieważ używasz Data, aby aktualizować czas na zegarze, zawsze otrzymujesz aktualny czas.Wywołanie parametru $ interval.flush może spowodować, że interwał będzie aktualizował zegar kilka razy, ale zawsze ustawia go na bieżący czas.

+0

Dzięki. Widzę teraz, że nie jest tak, jakbym używał wirtualnego zegara, Date() istnieje w czasie rzeczywistym, więc jeśli "test łyknięcia" nie będzie czekać przez całą minutę, nie mogę przywołać przyszłości. Czy zegar Jasmine ma na to wpływ, czy powinienem po prostu sprawdzić, czy $ interwał jest nazywany testem. – efwjames

+0

@liquified Będziesz musiał poczekać przez pełne dwie minuty. Ale są pewne garsy. Odstępy czasu, aby zaktualizować zegar w twoim kancie, aby nie zadzwonić, gdy uruchomisz Jasmine. Zrobiłeś to ręcznie. Musisz również ustawić limit czasu, aby uruchomić funkcję "oczekiwać" w teście, powiedz Jasmine, aby nie powodowała błędu limitu czasu. I na koniec, musisz dokonać zmian w pliku karma.config, dodając "browserNoActivityTimeout: 122000". Dołączyłem dwa pliki w moim plunk: test.js i karma.config.js. Zobacz komentarze do kodu. http://plnkr.co/edit/yEcoExCfdx6NSZRNDlX1 –

0

Myślę, że być może trzeba będzie użyć $scope.$apply() po przedziale $, aby upewnić się, że Angular o tym wie.

Powiązane problemy