2013-04-18 5 views
7

Ho creato una direttiva che viene utilizzata per mostrare i messaggi di notifica a un utente. Per mostrare la notifica ho scritto questo:

$scope.$watch($messaging.isUpdated, function() { 
    $scope.messages = $messaging.getMessages(); 
    if ($scope.messages.length > 0) { 
     $timeout(function() { 
      for (var i = 0; i < $scope.messages.length; i++) { 
       if (i + 1 < $scope.messages.length) { 
        $messaging.removeMessage($scope.messages[i]); 
       } else { 
        $messaging.removeMessage($scope.messages[i]); 
       } 
      } 
     }, 5000); 
    } 
}); 

sto usando $ timeout per assicurarsi che i messaggi rimane sullo schermo per 5 secondi.

Ora voglio scrivere test End-To-End su di esso in modo da poter essere sicuro che la notifica sia mostrata. Il problema si verifica quando viene mostrata la notifica. Anche l'End-To-End è scaduto, proprio come il messaggio di notifica. Ciò rende impossibile verificare se viene mostrata la notifica corretta. .

Questo è il mio codice di prova:

it('submit update Center', function() { 
    input('center.Name').enter('New Name'); 
    input('center.Department').enter('New Department'); 
    input('center.Contact').enter('New contact'); 
    input('center.Street').enter('New street'); 
    input('center.City').enter('New city'); 
    input('center.Country').enter('New Country'); 
    element('button#center_button').click(); 

    expect(element('.feedback').count()).toBe(1); 
    expect(element('.feedback:first').attr('class')).toMatch(/success/); 

    expect(element('.error.tooltip').count()).toBe(0); 
}); 

vorrei evitare di utilizzare il setTimeout javascript() e la speranza non c'è un'altra soluzione (angolare) a questo problema.

+1

Si può fare di questo un test di unità, invece, beffardo fuori '$ timeout' e verificando che è stato chiamato con gli argomenti giusti? –

risposta

11

Cattive notizie, amico. È un problema noto in AngularJs. C'è una discussione here e un "in qualche modo correlato" issue qui.

Fortunatamente, è possibile risolvere questo facendo rotolare il proprio servizio di $timeout, chiamando setTimeout e chiamando $apply a mano (questo è un suggerimento dalla discussione che ho fatto riferimento). È davvero semplice, anche se è davvero brutto. Un semplice esempio:

app.service('myTimeout', function($rootScope) { 
    return function(fn, delay) { 
    return setTimeout(function() { 
     fn(); 
     $rootScope.$apply(); 
    }, delay); 
    }; 
}); 

Nota questo non è compatibile con angolare $timeout, ma è possibile estendere la funzionalità se avete bisogno.

0

piccola nota su se/else

$scope.$watch($messaging.isUpdated, function() { 
$scope.messages = $messaging.getMessages(); 
if ($scope.messages.length > 0) { 
    $timeout(function() { 
     for (var i = 0; i < $scope.messages.length; i++) { 
      if (i + 1 < $scope.messages.length) { 
       $messaging.removeMessage($scope.messages[i]); 
      } else { /**** unnecessay else here *****/ 
       $messaging.removeMessage($scope.messages[i]); 
      } 
     } 
    }, 5000); 
}});