2015-10-26 21 views
6

分度器で角張ったアプリケーションをテストしています。 ユーザーが自分のアプリケーションにログインすると、$ timeoutを設定して1時間以内に何らかのジョブを実行します(ユーザーが13:00にログインした場合、$ timeoutは14:00に実行されます)。 私はこれらの失敗を得続ける:

"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(){....." 

私はこのタイムアウトページを読んだ:https://github.com/angular/protractor/blob/master/docs/timeouts.md ので、私はページが、彼が完了するまでに$タイムアウトを待っていますを意味している完全にロードされるまで分度器を待つ理解...

分度器がその$タイムアウトを待たないようにするにはどうすればよいですか? 私が使用したくない:

browser.ignoreSynchronization = true; 

その後、私のテストは、他の理由で失敗しますので(他の角度成分がまだロードする時間を必要とする...)

+1

設定した直後にタイムアウトをテストしましたか? – MBielski

答えて

3

をソリューションは、アクティブフラッシュするだろうタイムアウト(as @MBielski mentioned it in comments)ですが、元のフラッシュメソッド自体はanuglar-mocksでのみ使用できます。角度モックを直接使用するには、ページ上に<script>というタグを付ける必要があります。また、作成したすべてのオーバーライドに対処しなければならず、多くの副作用が発生します。作成されたタイムアウトを聞いて、必要に応じてリセットすることで、角度モックを使わずにフラッシュを再作成することができました。例えば

あなたの角度アプリでタイムアウトしている場合、:

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

をテストでは、次のようになります。それはちょっと実験的だ

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

、私はそれがために働くかどうかわかりませんあなたの場合。このコードは、browser.addMockModuleを別のnode.jsモジュールに移動することで簡略化することもできます。また、(100msのような)短いタイムアウトを削除したい場合は、現在実行中のAngularプロセスをキャンセルすることができますので、テストは中断します。

+0

すてきな解決策。しかし、私が正しく理解していれば、このソリューションはすべてのタイムアウトをキャンセルするので、タイムアウトが発生している間はアサーションをテストできません。 – BiAiB

+0

@BiAiB、タイムアウトは 'browser.executeScript(...)'の部分を呼び出すとキャンセルされるだけです。アサーションを最初に作成し、必要に応じてタイムアウトを終了することができると思います。おそらく、 'afterEach'に' browser.executeScript(...) 'の部分を置くこともできます。 –

0

解決策は、インターセプタを使用してタイムアウトを取得するhttp要求を変更し、カスタムタイムアウトをミリ秒(ミリ秒)に設定して、httpリクエストが長時間実行された後で新しいタイムアウト)、その後、即時応答をテストすることができます。

これはうまく行き、有望です。

関連する問題