2015-08-13 19 views
7

Ho un "orologio" di direttiva angolare e Sto provando a scrivere un test unitario per vedere se l'orologio effettivamente $ intervallo avanza a un orario futuro (es .: 2 minuti guardando element.text()). Ho un test di passaggio del tempo corrente, ora voglio testare se mostrerà un orario futuro tramite $interval.flush. Mi sembra che lo $interval.flush non stia davvero aumentando l'orologio.

Posso chiedere due risposte:

  • Come posso unit test se $interval incendi?
  • Perché $interval.flush non sembra far avanzare lo Date()?

Sto seguendo le linee guida da questi posti:

Un post correlati suggerito utilizzando Jasmine schernisce, che non credo è più necessario.

Un problema simile:

HTML

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

DIRETTIVA

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(); 
     }) 
    } 
    }; 
}]); 

UNIT TEST

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 
    }); 
    }); 

}); 

TERMINALE

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 rivela, il var è di 2 minuti incrementato, ma che il elem.text() rimane il tempo corrente.

+0

Hai funzionato? – Winnemucca

+0

Sì e no, posso testare la funzione updateClock() per vedere se funziona come previsto, ma non vale la pena scavare in realtà nell'esecuzione di un test X minuti solo per vedere se l'orologio riflette X min in futuro. Ho effettuato il refactoring in modo che updateClock riceva una nuova data invece di generarne una. Pertanto, posso spionare updateClock per vedere se si attiva nell'intervallo specificato e per vedere se updateClock aggiorna il testo se lo passo una variabile di data futura. In un certo senso, "Date" è fuori dal campo di applicazione, è il software del computer, presumiamo che abbiano fatto la propria due diligence. – efwjames

risposta

4

NOTA Prima di iniziare:

Hai un errore nel codice direttiva. Quando si chiama $ interval, si passa l'oggetto function come primo parametro. Nessuna parentesi.

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

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

vedere la differenza sulla plunker

In secondo luogo, chiamando $ interval.flush provoca intervallo di andare avanti per il numero di millisecondi, ma non ha effetto sul clock interno Javascript. Poiché stai utilizzando la Data per aggiornare l'ora sull'orologio, ricevi sempre l'ora corrente.Chiamare $ interval.flush può far sì che l'intervallo aggiorni l'orologio un numero di volte, ma lo imposta sempre sull'ora corrente.

+0

Grazie. Ora vedo che non è come se avessi un orologio virtuale, Date() esiste in tempo reale, quindi a meno che 'gulp test' non aspetti un intero minuto, non posso richiamare il futuro. L'orologio di simulazione di Jasmine è pensato per fare questo o dovrei semplicemente accertarmi che l'intervallo $ venga chiamato come test. – efwjames

+0

@liquified Dovrete aspettare i due minuti completi. Ma ci sono alcuni trucchi. Gli intervalli per aggiornare l'orologio nel tuo codice angolare per non essere chiamato quando esegui Jasmine. Lo hai fatto manualmente. È inoltre necessario impostare un timeout per eseguire la funzione "expect" nel test, comunicare a Jasmine di non generare un errore di timeout. E, infine, è necessario apportare una modifica al proprio karma.config per includere "browserNoActivityTimeout: 122000". Ho incluso due file nel mio plunk: test.js e karma.config.js. Vedi i commenti del codice. http://plnkr.co/edit/yEcoExCfdx6NSZRNDlX1 –

0

Penso che potrebbe essere necessario utilizzare $scope.$apply() dopo l'intervallo $ per assicurarsi che l'Angolare ne sia a conoscenza.

Problemi correlati