Protractor: chore(core):クライアント側のリダイレクトのためのより良いエラーメッセージを追加します

作成日 2015年10月28日  ·  49コメント  ·  ソース: angular/protractor

テストがリンクまたはbrowser.getまたはbrowser.refresh外部のリダイレクトを引き起こす何かをクリックすると、次にwaitForAngularが呼び出されたときに、ユーザーはおそらくこのエラーメッセージに遭遇します( Angularがロードされるのを待たなかったので)、これはあまり役に立ちません。

何が問題になっているのか、および潜在的な回避策についてユーザーに通知する必要があります(たとえば、 browser.getまたはbrowser.refreshを使用してブートストラップを修正します)。

debuggability

最も参考になるコメント

@sjelinこの問題を軽減するために何ができるかについてもう少し説明していただけますか?

私の使用例:ユーザー名/パスワードを入力してログインボタンを押すテストがあり、ログインに成功すると別のページにリダイレクトされます。

全てのコメント49件

@sjelinこの問題を軽減するために何ができるかについてもう少し説明していただけますか?

私の使用例:ユーザー名/パスワードを入力してログインボタンを押すテストがあり、ログインに成功すると別のページにリダイレクトされます。

両方のページが角度のあるページである場合は、新しいページが読み込まれた後にbrowser.refresh追加するだけで、問題を解決できます。

将来的にこれを改善する機能に取り組んでいます

私はこの問題に1週間苦労しています。 POSTを実行している場合、 browser.refresh()は機能しません。

覚えておくとよいでしょう、ありがとう。 今のところ、クライアント側のリダイレクトが発生してから数百ミリ秒待機するだけで、問題を軽減できる可能性があります。 これにより、Protractorがエラーメッセージをスローしなくなりますが、Protractorが適切にブートストラップできないため、他の予期しない問題が発生する可能性があります(特に、プラグインまたはモックモジュールを使用している場合)。

実際、私はこのようなものを回避策として使用しており、リダイレクトがあることがわかっています。

(function (expectedUrl, timeout) {
    var loaded = false;

    browser.wait(function () {
        browser.executeScript(function () {
            return {
                url: window.location.href,
                haveAngular: !!window.angular
            };
        }).then(function (obj) {
            loaded = (obj.url == expectedUrl && obj.haveAngular);
        });

        return loaded;
    }, timeout);
})(expectedUrl, timeout);

@tassoevan 、それは完璧です! それは私がwaitForAngularに期待することです-Angularが利用可能になるのを待ちます。

分度器が起動すると、常にbaseUrlに移動し、次にテストページに移動します。 それはあなたが話しているリダイレクトと見なされますか?

@patrickliechtyとはつまり、リンク( <a href='google.com'> )をクリックすると、ブラウザがgoogle.cmに移動します。

@hankduanがなくなった@juliemrは、これに対する長期的な修正に取り組んでいる人はもういますか?

@sjelin 、この問題は分度器3.1.1にまだ存在しますか?

より良い修正のために+1。 確実に回避する方法がわからないまま、今日これに遭遇しました。 ありがとう!

同じ問題を抱えています!!! 信頼できる修正をしてくれた@tassoevanに感謝します

修正のために+1。

仕様外でelement()。getText()を実行すると(browser.get()が発生せずに)、このエラーが発生しました-仕様外の特定のdivの出力へのショートカットを作成しようとしていました。 それを関数に変えて、すべてが順調でした。

\ node_modules \ protractor \ example \ conf.jsに対して実行すると、このエラーが発生します。確かに、サンプルconf.jsは常に機能するはずですか?

Angularなしで分度器を使用している人のために、回避策はありますか?

@ Overdrivrbrowser.ignoreSynchronization = true;を設定できます。 分度器にAngularを待たないように指示します。

browser.ignoreSynchronization = trueは、ウィンドウを切り替えるときに機能します。

OKですが、ブラウザを設定する必要があります。ignoreSynchronization= false;

このエラーが発生し、このgithubの問題へのリンクが含まれています。

これが私が持っているものです:

/**
 * Waits for MR job to complete.
 * <strong i="7">@param</strong> {string} url The GET URL to kick off the map reduce job.
 * <strong i="8">@return</strong> {!webdriver.promise.Promise}
 */
function waitForMapReduceJobToComplete(url) {
  browser.ignoreSynchronization = true;
  browser.get(url);
  $('a[href*="/mapreduce"]').click();
  browser.wait(()=> {
    console.log('wait');
    return $('#auto-refresh').isPresent();
  });
  browser.controlFlow().execute(function() {
    console.log('after wait, before click');
  });
  browser.wait(()=> {
    console.log('isDisplayed');
    return $('#auto-refresh').isDisplayed();
  });
  $('#auto-refresh').click();
  browser.controlFlow().execute(function() {
    console.log('after click');
  });

  browser.wait(() => {
    return $('.status-box').isPresent().then((isPresent)=> {
      if(isPresent) {
        return hasClass($('.status-box'), 'status-done')
            .then((containsClass) => {
              if(!containsClass) {
                return browser.refresh().then(() => false);
              }
              return true;
            });
      }
      return browser.sleep(constants.BROWSER_WAIT_MS)
          .then(() => false);
    })
  });

  return browser.controlFlow().execute(function() {
    browser.ignoreSynchronization = false;
  });
}
  fit('mapreduce job is idempotent', function() {
    var subBuildingUrl = '/xyz/#all';
    var mapReduceJob = '/import/xyz/';
    helpers.waitForMapReduceJobToComplete(mapReduceJob);

    browser.get(subBuildingUrl);
    var tableView = new TableView();
    var originalCount = 0;
    tableView.count().then((cnt)=>{
      originalCount = cnt;
    });

    tableView.deleteRowNumber(1);
    browser.sleep(5000);
    browser.controlFlow().execute(function() {
      expect(tableView.count()).toBeLessThan(originalCount);
    });

    helpers.waitForMapReduceJobToComplete(mapReduceJob);
    browser.get(subBuildingUrl);
    browser.controlFlow().execute(function() {
      tableView = new TableView();
      expect(tableView.count()).toEqual(originalCount);
    });
  });

//アレンジ
テストはAngularアプリで開始されます。
AngularアプリではなくURLでmapreduceジョブを開始します
Angularアプリに戻って行数を記録します

//行為
1つのレコードを削除します
削除が発生したことを確認します

// 主張する
AngularアプリではなくURLでmapreduceジョブを開始します
mapreduceジョブがデータを再作成することを確認する前に2回目に_失敗します(削除前の同じ行数)。

関連するログの詳細は次のとおりです。

wait
after wait, before click
isDisplayed
isDisplayed
after click
[17:48:09] W/element - more than one element found for locator By(css selector, .status-box) - the first result will be used
[17:48:24] W/element - more than one element found for locator By(css selector, .status-box) - the first result will be used
[17:48:40] W/element - more than one element found for locator By(css selector, .status-box) - the first result will be used
[17:48:55] W/element - more than one element found for locator By(css selector, .status-box) - the first result will be used
wait
F

Failures:
  Message:
    Failed: Error while waiting for Protractor to sync with the page: "window.angular is 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"
  Stack:

'wait'ログのwaitForMapReduceJobToCompleteを介して、2回目は常に失敗します。

解決策はここに「文書化」されています: https

browser.wait内で、i​​gnoreSynchronizationをリセットする必要があります。 私はignoreSynchronizationがすでにtrueであったすべてのbrowser.waitsに対してこれを行いました。

  browser.wait(()=> {
    browser.ignoreSynchronization = true;
    return $('#auto-refresh').isPresent();
  });

私のテストは今合格です。

browser.ExpectedConditionsを使用して待機するための解決策はありますか?

このコードを使用すると、パッチはどのようになりますか?

browser.wait(EC.visibilityOf(element), timeout, message);?

ありがとう!

@azacharこれは

browser.wait(() => {
  browser.ignoreSynchronization = true;
  return EC.visibilityOf(element);
}, timeout, message);

何が起こっているのかわかりません。このブロックの何らかの理由で、強制的に設定するまでignoreSynchronizationはまだfalseです。 #2787でこれをフォローアップしました。

更新: ignoreSynchronizationを設定/リセットすると、競合状態が発生します。それを制御フローに配置することをお勧めします。 #4061を参照してください。

私はこれをignoreSynchronizationでこのようなもので取得しています...

afterAll(function(){
    adminPage.header.logout();
    // FIXME: WTF why isn't even this working 100% of the time
    setTimeout(function(){
      expect(loginPage.isVisible()).toBeTruthy();
    }, 1000 )
  })

loginPage読み込みには1秒かかるようで、このsetTimeoutは役に立ちません。 browser.waitは少し役立つようですが、それでも失敗します。

@tassoevanこんにちは、あなたの説明のようにそのbrowser.wait()を構成する方法と、それを構成する場所を教えてください

(function (expectedUrl, timeout) {
    var loaded = false;

    browser.wait(function () {
        browser.executeScript(function () {
            return {
                url: window.location.href,
                haveAngular: !!window.angular
            };
        }).then(function (obj) {
            loaded = (obj.url == expectedUrl && obj.haveAngular);
        });

        return loaded;
    }, timeout);
})(expectedUrl, timeout);

角度(2)で-仕様がbrowser.get( '/');で始まることを確認してください。

import { browser, element, by } from 'protractor';

it('should display message saying app works', () => {
    browser.get('/');

    let title = element(by.id('title')).getText();
    expect<any>(title).toEqual('cool');
});

@tassoevanの優れた回避策を確認し、リダイレクトテストを機能させた後、TypeScriptとAngular2のソリューションを共有すると思いました。 この関数を抽象ページクラスに配置しましたが、 browserオブジェクトに適していると思います。

/**
  Wait for the page to make it to the next URL before continuing.
  A supplement to browser.waitForAngular() because protractor will continue control
  flow before navigation starts.

  Inputs:
    necessaryUrlFragment: a portion of the url that signifies you have successfully navigated
    timeout: the number of ms to wait before throwing an error. Defaults to the browsers default
      page timeout.
 */
waitForRedirect(necessaryUrlFragment: string, timeout: number = browser.getPageTimeout) {
  // Before we tell the browser to wait, assume it has not navigated
  let hasRedirected = false;

  // Passing a function to browser.wait() tells protractor to call that function repeatedly.
  // This function returns the closure variable hasRedirected, which will be set to true once the
  // necessaryUrlFragment has been found in the url
  browser.wait(() => {
    browser.getCurrentUrl()
      // Check to see if necessaryUrlFragment is in the current url
      .then(url => url.includes(necessaryUrlFragment))
      // Update our navigation status
      .then(hasNavigated => {
        hasRedirected = hasNavigated;
      });

    // Return our navigation status every time protractor asks for it - even if navigation is
    // not complete
    return hasRedirected;
  }, timeout);
}

これが私がテストでそれをどのように使用したかの例です:

it('Should be able load the preferences page', () => {
  page.navigateToMarketing();
  page.clickButton('Manage Preferences');
  page.waitForRedirect('preferences/preferences');
  expect(page.getPageTitle()).toBe('MY PREFERENCES');
});

私のログインページは非Angularjsページです。 アプリケーションにログインすると、Angularjsページが作成されます。 そこで、以下のようにスペックファイルを作成しました。

describe( 'アプリケーションにログイン'、function(){
var userID = element(by.name( 'username'));
var password = element(by.name( 'password'));
var logInButton = element(by.id( 'Submit'));

function loginToApplication(stringSSOID、stringPassword){
userID.sendKeys(stringSSOID);
password.sendKeys(stringPassword);
logInButton.click();

}

beforeEach(function(){
browser.ignoreSynchronisation = true;
browser.get( ''); //アプリケーションのログインページに移動します
});

it( 'アプリケーションにログインしています'、function(){
loginToApplication( '77777'、 'test')
browser.ignoreSynchronisation = false
expect(browser.getTitle())。toEqual( 'Software');
});
});

以下のエラーメッセージが表示されます。
失敗:分度器がページと同期するのを待っている間にエラーが発生しました: "window.an
gularは未定義です。 これは、これが角度のないページであるか、
テストにはクライアント側のナビゲーションが含まれているため、Protに干渉する可能性があります
講師のブートストラップ。 詳細については、 http://git.io/v4gXMを参照してください。」

こんにちはhttp://www.protractortest.org/#/timeouts#how-to-disable-waiting-for-angularをご覧ください
基本的に、Angular以外のページを使用してログインする方法はいくつかありますが、最初にドキュメントでこの1つのショーを試してください。
宜しくお願いします
キャメル

すでに長い議論だと思いますが、これは誰かを助けるかもしれません。

このようなエラーメッセージは、Angularコンポーネントで未処理のエラーが発生したために、ページが予期せずリロードされた場合にも発生する可能性があります。 ブラウザコンソールが永続化されない可能性があるという事実と、テストの実行速度が原因で、何が起こっているのかを理解するのは非常に簡単ではありませんでした。

したがって、前述のケース自体は「クライアント側のナビゲーション」ではないため、エラーメッセージに関する限り、何かが行われる可能性があります:)

こんにちは@ArnaudPel

あなたの追加情報のためのTnx。 必要に応じて、ドキュメントでこれを説明するPRを追加できますか?

現在、ログインページにアクセスすると、このエラーが発生します(一般的な問題)。

Failed: Error while waiting for Protractor to sync with the page: "window.angular is 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"

ignoreSyncトリックを実行しても、役に立たないようです。

browser.ignoreSynchronization = true;
// do work here with browser.driver 
browser.ignoreSynchronization = false;

リンクはこのスレッドに到達しますが、次に何をすべきかは正確には明確ではありません。

分度器バージョンでテスト済み:5.2.1、5.1.1、5.1.0、5.0.0

@benjaminapetersen - waitForAngularEnabled代わりにignoreSynchronization waitForAngularEnabledを使用してみてください。 Protractor v5.1.2のAPIリファレンスページを見ていて、 ignoreSynchronizationが含まれていませんが、 CHANGELOGを調べても、そのプロパティが正式に非推奨になったのは

waitForAngularEnabled試しましたが、

exports.config = {
    rootElement: 'app',
    baseUrl: 'http://localhost:1384/#/',
    framework: 'jasmine',
    seleniumAddress: 'http://localhost:4444/wd/hub',
    specs: ['./tests/e2e/*.js'],
    multiCapabilities: [{
      'browserName': 'firefox',
      //'browserName': 'chrome',
    }, 
  ],
  jasmineNodeOpts: {
    showColors: true
  },
}

//example test: 

describe('Overall navigation', function () {
  it('test link', function () {
     browser.get('http://localhost:1384/#/registrerprodukt');
  });
});

@thompsnmありがとう! waitForAngularEnabledも非推奨のよう

非推奨のdocタグがwaitForAngularEnabledではなくignoreSynchronizationプロパティにある@benjaminapetersen

waitForAngularEnabledも私には機能しません。 Protractor 5にアップグレードする前に、IgnoreSynchronizationで機能しました。非Angular iframeに切り替える必要がありますが、今はできません。 お知らせ下さい。 ありがとう

@ eel93 rootElement: 'app'にコメントするか、 rootElement: '*[ng-app]'置き換えてみてください。
分度器の最新バージョンをインストールし、Angular 1.6.1アプリの仕様をいくつか作成しましたが、これまでのところ問題なく動作しているようです。 アプリにログインしようとしたときにこのエラーメッセージが表示されましたが、現在は次の方法を使用しています。

onPrepare: function () {
    browser.driver.manage().timeouts().setScriptTimeout(60000);

    browser.driver.get('http://app.local.dev'+ '/login');
    browser.driver.findElement(by.id('user_login')).sendKeys('d','e','m', 'o');
    browser.driver.findElement(by.id('user_pass')).sendKeys('d','e','m', 'o');
    browser.driver.findElement(by.id('submit')).click();

    // Login takes some time, so wait until it's done.
    return browser.driver.wait(function() {
        return browser.driver.getCurrentUrl().then(function(url) {
            return /students\/agenda/.test(url);
        });
    }, 30000);
}

注:htmlタグにng-app設定しています

rootElement: '*[ng-app]' ? ページでノードを検索するだけで機能しますか? これは前に見たことがありません。

問題を解決しました。 🥇根本原因:開発者コンソールの副作用

私はこの問題を抱えていました、そして私のための修正は私のpackage.jsonで分度器「^ 5.3.2」に変更することでした。

通常のログインページがあり、Angularページにリダイレクトします。

ですから、AngularとAngular e2eは初めてなので、どのように、なぜ機能するのか正確にはわかりませんが、 browser.waitForAngularEnabled(false); 2回使用すると機能するようになりました。

logIn() {
    const email = 'test';
    const password = 'test';

    browser.waitForAngularEnabled(false);
    browser.get('/login');

    element(by.id('username')).sendKeys(email);
    element(by.id('password')).sendKeys(password);
    element(by.css('[type="submit"]')).click();

    return browser.wait(function() {
        browser.waitForAngularEnabled(false);
        return browser.getCurrentUrl().then(function(url) {
            browser.waitForAngularEnabled(true);
            return /dashboard/.test(url);
        });
    }, 5000);
}

それが役に立てば幸い。

テストに合格した後にエラーが発生しない限り、この最後の解決策はほとんど機能します。
エラー:ECONNREFUSED接続ECONNREFUSED 127.0.0.1:4444差出人:タスク:WebDriver.getCurrentUrl()

仕様外でelement()。getText()を実行すると(browser.get()が発生せずに)、このエラーが発生しました-仕様外の特定のdivの出力へのショートカットを作成しようとしていました。 それを関数に変えて、すべてが順調でした。

これは何に対しても機能します。「it」の外で複数の「element()。anyfunction()」を使用することはできません。
難しい方法でそれを見つけました...

分度器で1つのWebページから別のWebページに切り替えるときにエラーが発生しました:

失敗:Protractorがページと同期するのを待っている間にエラーが発生しました:「angularJSのテスト可能性と角度のテスト可能性の両方が定義されていません。これは、これが非角度のページであるか、テストにクライアント側のナビゲーションが含まれているため、Protractorの干渉が発生する可能性があります。ブートストラップ。詳細については、 http://git.io/v4gXMを参照して

コードは:
var url = browser.params.login.Url;
browser.get(url + '/#!/ app / manage-users');

CTビルドで突然このエラーが発生し始めました。 このエラーはFirefoxヘッドレスでのみ発生し、Linux上のChromeヘッドレスで正常に機能することに気付きました。 Firefox v69から最新のもの(現時点ではv72.0.2)にアップグレードして、この問題を修正しました。

browser.ignoreSynchronizationは非推奨になり、使用しないでください。 元の投稿から示唆されているように、 browser.getを使用すると問題が解決するようです。

あなたは無効にして有効にできるような方法でそれを使用したい場合はwaitForAngularEnabled意のままに、あなたが使用する必要がbrowser.get設定した後、 waitForAngularEnabled(true) 。 例えば:

// do things on your Angular application

waitForAngularEnabled(false)

// do things on non-angular page

waitForAngularEnabled(true)
browser.get('/home') // this is a page from your Angular application

browser.getは、Angularページが読み込まれるまでブロックします。

私は現在このエラーに遭遇しています:

_例外が発生しました:エラー:分度器がページと同期するのを待っている間にエラーが発生しました: "angularJSのテスト可能性と角度のテスト可能性の両方が定義されていません。これは、これが非角度のページであるか、テストにクライアント側のナビゲーションが含まれていることが原因である可能性があります。分度器のブートストラップを妨げる可能性があります。詳細については、 http://git.io/v4gXMを参照してください "_

ただし、VSCodeデバッガーまたはchromeinspectorデバッグのいずれかを使用してデバッグしようとする場合のみ(どちらの場合もhttps://www.protractortest.org/#/debuggingの手順に従ってください)。

これがVSCodeのlaunch.json設定です。

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "E2E Test",
            "skipFiles": [
                "<node_internals>/**"
            ],
            "program": "${workspaceFolder}\\node_modules\\protractor\\bin\\protractor",
            "args": ["${workspaceFolder}\\e2e\\protractor.conf.js"],
            "outFiles": [
                "${workspaceFolder}/e2e/**/*.js",
                "${workspaceFolder}/src/**/*.js"
            ]
        }
    ]
}

多分それは私が間違って設定したものです。 適切にデバッグすることができずにこれらを書き込もうとすることはめちゃくちゃ難しいです。

このページは役に立ちましたか?
0 / 5 - 0 評価