2015-10-26 17 views
6

Sto testando la mia applicazione angolare con Goniometro. Una volta che l'utente ha effettuato il login alla mia app, ho impostato un timeout $ per fare un po 'di lavoro in un'ora (quindi se l'utente ha effettuato l'accesso alle 13:00, il timeout $ verrà eseguito alle 14:00). Continuo a ricevere questi fallimenti:

"Timed out waiting for Protractor to synchronize with the page after 20 seconds. Please see https://github.com/angular/protractor/blob/master/docs/faq.md. The following tasks were pending: - $timeout: function onTimeoutDone(){....." 

che ho letto questa pagina timeout: https://github.com/angular/protractor/blob/master/docs/timeouts.md così ho capito goniometro aspetta fino la pagina è completamente caricata che significa che sta aspettando il $ timeout per completare ...

Come posso fare in modo che il goniometro NON aspetti quel timeout $? Non voglio usare:

browser.ignoreSynchronization = true; 

Perché allora i miei test avrà esito negativo per altri motivi (altri componenti angolari ha ancora bisogno di tempo per caricare ...)

+1

Hai provato a svuotare quel timeout tramite il test subito dopo averlo impostato? – MBielski

risposta

3

La soluzione sarà attiva per irrigare timeout (as @MBielski mentioned it in comments), ma il metodo di flush originale è disponibile solo in anuglar-mocks. Per utilizzare direttamente le angock-mock dovrai includerlo nella pagina come tag <script> e dovrai anche occuparti di tutte le sostituzioni che crea, producendo molti effetti collaterali. Sono stato in grado di ricreare lo svuotamento senza l'utilizzo di angock-mock ascoltando i timeout creati e quindi reimpostandoli su richiesta.

Ad esempio, se si dispone di un timeout nella vostra applicazione angolare:

$timeout(function() { 
    alert('Hello World'); 
}, 10000); // say hello in 10 sec 

Il test sarà simile:

it('should reset timeouts', function() { 

    browser.addMockModule('e2eFlushTimeouts', function() { 

     angular 
     .module('e2eFlushTimeouts', []) 
     .run(function ($browser) { 

      // store all created timeouts 
      var timeouts = []; 

      // listen to all timeouts created by overriding 
      // a method responsible for that 
      var originalDefer = $browser.defer; 

      $browser.defer = function (fn, delay) { 
       // originally it returns timeout id 
       var timeoutId = originalDefer.apply($browser, arguments); 
       // store it to be able to remove it later 
       timeouts.push({ id: timeoutId, delay: delay }); 
       // preserve original behavior 
       return timeoutId; 
      }; 

      // compatibility with original method 
      $browser.defer.cancel = originalDefer.cancel; 

      // create a global method to flush timeouts greater than @delay 
      // call it using browser.executeScript() 
      window.e2eFlushTimeouts = function (delay) { 
       timeouts.forEach(function (timeout) { 
        if (timeout.delay >= delay) { 
         $browser.defer.cancel(timeout.id); 
        } 
       }); 
      }; 

     }); 

    }); 


    browser.get('example.com'); 

    // do test stuff 

    browser.executeScript(function() { 
     // flush everything that has a delay more that 6 sec 
     window.e2eFlushTimeouts(6000); 
    }); 

    expect(something).toBe(true); 
}); 

E 'un pò sperimentale, non sono sicuro se funzionerà per il tuo caso. Questo codice può anche essere semplificato spostando browser.addMockModule in un modulo node.js separato. Inoltre potrebbero esserci problemi se si desidera rimuovere brevi timeout (come 100ms), può annullare i processi Angular attualmente in esecuzione, quindi il test si interromperà.

+0

bella soluzione. Tuttavia, se ho capito bene, questa soluzione annulla tutti i timeout, quindi non posso testare un'affermazione mentre il timeout sta andando. – BiAiB

+0

@BiAiB, i timeout vengono annullati solo quando si chiama la parte 'browser.executeScript (...)', credo che si possano fare asserzioni prima e poi uccidere i timeout, se necessario. Forse anche la parte 'browser.executeScript (...)' in 'afterEach' funzionerà. –

0

La soluzione è utilizzare gli intercettatori e modificare la richiesta http che sta ricevendo il timeout e impostare il timeout personalizzato su alcuni millisecondi (desiderati) su quella richiesta http in modo che dopo qualche tempo la richiesta HTTP venga chiusa (a causa del nuovo timeout) e quindi è possibile testare una risposta immediata.

Questo sta funzionando bene e promettendo.

Problemi correlati