JavaのセレンJavascriptExecutorとアクセスAngularJS変数

アンドリュー・アン:

ここではdiv要素がクリックされたときに、変数を設定しますAngularJS NG-click属性を持つdivがあります。

<div id="id"
     ng-click="foo.bar = true;">
     Set bar variable on foo object to true
</div>

ここではdiv要素をクリックしてセレンを使用して、いくつかのJavaコードがあります。

By upload = By.id("id");
driver.findElement(uploadCensus).click();

私は、Javaコード、永遠のためのAngularJSのハングを実行すると。私のdivはので、ここでクリックされたときに、フィギュアfoo.barが設定されていないが、直接変数を設定し、いくつかのコードです。

By upload = By.id("id");
((JavascriptExecutor) driver)
    .executeScript("foo.bar = true;",   
    driver.findElement(upload));

スタックトレース

不明なエラー:fooが定義されていない(セッション情報:クロム= 56.0.2924.87)(ドライバ情報:chromedriver = 2.25.426923(0390b88869384d6eb0d5d09729679f934aab9eed)、プラットフォーム=のWindows NT 6.1.7601 SP1 x86_64で)(警告:サーバは任意のスタックトレースを提供していませんでした情報)コマンドの期間またはタイムアウト:51ミリ秒のビルド情報:バージョン:「2.53.0」、リビジョン:「35ae25b」、時間:「2016年3月15日夜5時00分58秒」システム情報:ホスト:「WV-VC104- 027' 、IP: '{IP}'、os.name: 'Windows 7の'、os.arch: 'AMD64'、os.version: '6.1'、のjava.version: '1.8.0_151' ドライバー情報:ORG。 openqa.selenium.chrome.ChromeDriver機能[{applicationCacheEnabled =偽、回転自在=偽、mobileEmulationEnabled =偽、networkConnectionEnabled =偽、クロム= {chromedriverVersion = 2.25.426923(0390b88869384d6eb0d5d09729679f934aab9eed)userDataDir = C:\ユーザー{ユーザー} \のAppData \ローカル\一時\ scoped_dir5600_4225}、takesHeapSnapshot =真、pageLoadStrategy =通常、databaseEnabled = falseを、handlesAlerts =真、hasTouchScreen = falseの場合、バージョン= 56.0.2924.87、プラットフォーム= XP、browserConnectionEnabled = FALSE、nativeEvents =真、acceptSslCerts =真、=真locationContextEnabled、webStorageEnabled =真、browserName =クロム、takesScreenshot =真、javascriptEnabled =真、cssSelectorsEnabled = TRUE}]セッションID:a7734312eff62fe452a53895b221a58djavascriptEnabled = TRUE、cssSelectorsEnabled = TRUE}]セッションID:a7734312eff62fe452a53895b221a58djavascriptEnabled = TRUE、cssSelectorsEnabled = TRUE}]セッションID:a7734312eff62fe452a53895b221a58d

私は、設定しようとするとfoo.bar、それがグローバルに定義されていないとAngularJSのソースコード内のどこかに埋もれているので、私は、変数への参照を取得することはできません。私は、変数のインデックスと外観をunminifyしようとしたが、私はそれを見つけるように見えることはできません。私は手動で設定したいfoo.barを通じて変数をJavascriptExecutorしかし、変数への参照を取得することはできません。どのように私は、変数を設定し、その後見つけるだろうか?

それがこれをトリガするために間違った方法のように思える場合はng-click、私がアイデアを開いています。私は分度器がこれを処理する方法を持っていると確信していますが、このAngularJSアプリケーションは、エンタープライズ環境で展開し、数ヶ月のための技術を承認するビジネス面を取得しようとしています。私はセレンで立ち往生しています。助けて...

Nvrsu:

ご質問のためだけの答えは、直接[いけない:)あなたのケースのためにそれを使用します]

角度の変数を単離したあなたはそれにスコープとセット変数を取得する必要がscope.So。

angular.element("#id").scope().foo.bar = true;

しかし、あなたのケースのためにそれを使用してはいけません。あなたはシステムレベルでアプリケーションをテストしているとして、ユーザーが行うのと同じようにそれらをテストする必要があります。

推奨回答:Javaでの角度testablity待ち

分度器を扱うことができるものは何でも、あなたのJavaのテストも行うことができます。どちらも、セレンバインディングオーバーラッパーです。あなたがテストを同じブラウザで最終的にすべてのSeleneseのコードが実行されます。

waitForAngularMethodあなたは、あなたのテストに不足していることが最も避けられない方法です。良いことは、あなたがexpilcit待ち時間内JavaScriptExecutorを使用したJavaScriptの同じ種類を実行することができます。

あなたはjavascriptの恋人している場合は、参照することができwaitForangularの分度器でメソッドの実装を。これは、コールバックを使用して単純な検証チェックと待ち時間です。

waitforangularの予想condrionを作成するためのJavaコード

String waitForAngularJs ="Your javascript goes here"; // as it is lengthy read it from file and store here.
ExpectedCondition<Boolean> waitForAngular= new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver driver) {
                return ((JavascriptExecutor) driver).executeAsyncScript(waitForAngularJs).equals(true);
            }
};

 WebDriverWait wait = new WebDriverWait(driver, 60);
 wait.until(waitForAngular);

角度Javascriptを待ちます(あなたのJava実行時に変更しかし、私はそれをチェックしませんでした。):

この方法は、二つの属性、ルートロケータフックやコールバックを必要とします。私は、あるルートロケータを持つ単純な目的球の真のリターンとフックとしてセットコールバックを持っています[ng-app]

var testCallback = function() {
  return true;
 };

    // Wait for angular1 testability first and run waitForAngular2 as a callback
    var waitForAngular1 = function(callback) {

      if (window.angular) {
        var hooks = window.angular.element('[ng-app]');
        if (!hooks){
          callback();  // not an angular1 app
        }
        else{
          if (hooks.$$testability) {
            hooks.$$testability.whenStable(callback);
          } else if (hooks.$injector) {
            hooks.$injector.get('$browser')
                .notifyWhenNoOutstandingRequests(callback);
          } else if (!rootSelector) {
            throw new Error(
                'Could not automatically find injector on page: "' +
                window.location.toString() + '".  Consider using config.rootEl');
          } else {
            throw new Error(
                'root element (' + rootSelector + ') has no injector.' +
                ' this may mean it is not inside ng-app.');
          }
        }
      }
      else {callback();}  // not an angular1 app
    };

    // Wait for Angular2 testability and then run test callback
    var waitForAngular2 = function() {
      if (window.getAngularTestability) {
        if (rootSelector) {
          var testability = null;
          var el = document.querySelector(rootSelector);
          try{
            testability = window.getAngularTestability(el);
          }
          catch(e){}
          if (testability) {
            testability.whenStable(testCallback);
            return;
          }
        }

        // Didn't specify root element or testability could not be found
        // by rootSelector. This may happen in a hybrid app, which could have
        // more than one root.
        var testabilities = window.getAllAngularTestabilities();
        var count = testabilities.length;

        // No angular2 testability, this happens when
        // going to a hybrid page and going back to a pure angular1 page
        if (count === 0) {
          testCallback();
          return;
        }

        var decrement = function() {
          count--;
          if (count === 0) {
            testCallback();
          }
        };
        testabilities.forEach(function(testability) {
          testability.whenStable(decrement);
        });

      }
      else {testCallback();}  // not an angular2 app
    };

    if (!(window.angular) && !(window.getAngularTestability)) {
      // no testability hook
      throw new Error(
          'both angularJS testability and angular testability are undefined.' +
          '  This could be either ' +
          'because this is a non-angular page or because your test involves ' +
          'client-side navigation, which can interfere with Protractor\'s ' +
          'bootstrapping.  See http://git.io/v4gXM for details');
    } else {waitForAngular1(waitForAngular2);}  // Wait for angular1 and angular2
// Testability hooks sequentially

なぜ我々は、角度とロジックの背後にあるのを待つ必要が

私たちは、角使用するHTMLテンプレートので、これを必要とする理由、双方向のデータは、AJAXリクエストを結合してルーティングします。だから、ページナビゲーションの後、我々は完全にこのすべての操作(リクエスト&約束を)待たなければなりません。あなたの場合のように、予想通りそれ以外のHTMLが応答しません。

角度testablityをチェック

すなわち、角度のtestablityをチェックします。この角度itselfsための方法を提供します。

要素に基づいて確認するには、

 window.getAngularTestability(el).whenStable(callback); //Here el is element to be valiated.

すべてtestablitiesを確認するには、

 window.getAllAngularTestabilities();
   testabilities.forEach(function(testability) {
        testability.whenStable(callback);
});

完全に要求を保留中のすべてのHTTPを待ち

角度testablityをチェックする前に、私たちは必ず次の行に保留中のHTTPリクエストが存在しないことができます。

angular.element(document).injector().get('$http').pendingRequest.length

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=193020&siteId=1