Protractor: chore (core): Tambahkan pesan kesalahan yang lebih baik untuk pengalihan sisi klien

Dibuat pada 28 Okt 2015  ·  49Komentar  ·  Sumber: angular/protractor

Jika pengujian mengklik link atau sesuatu yang menyebabkan pengalihan di luar browser.get atau browser.refresh , maka lain kali waitForAngular dipanggil, pengguna mungkin akan melihat pesan kesalahan ini ( karena kami tidak menunggu Angular dimuat), yang tidak terlalu membantu.

Pengguna harus diberi tahu apa yang salah dan tentang potensi penyelesaian (mis. Menggunakan browser.get atau browser.refresh untuk memperbaiki bootstrap).

debuggability

Komentar yang paling membantu

@sjelin bisakah Anda menjelaskan sedikit lebih banyak tentang apa yang dapat dilakukan untuk mengurangi masalah ini?

Kasus penggunaan saya: Saya memiliki tes yang memasukkan nama pengguna / kata sandi dan menekan tombol masuk, yang mengarahkan ulang ke halaman lain saat berhasil masuk.

Semua 49 komentar

@sjelin bisakah Anda menjelaskan sedikit lebih banyak tentang apa yang dapat dilakukan untuk mengurangi masalah ini?

Kasus penggunaan saya: Saya memiliki tes yang memasukkan nama pengguna / kata sandi dan menekan tombol masuk, yang mengarahkan ulang ke halaman lain saat berhasil masuk.

Jika kedua halaman adalah halaman bersudut, Anda sebaiknya menambahkan browser.refresh setelah halaman baru dimuat untuk memperbaiki masalah

Kami sedang mengerjakan fitur untuk menjadikannya lebih baik di masa mendatang

Saya telah berjuang dengan masalah ini selama seminggu sekarang. browser.refresh() tidak berfungsi jika saya melakukan POST.

Itu bagus untuk diingat, terima kasih. Untuk saat ini, Anda mungkin dapat mengurangi masalah hanya dengan meminta pengujian Anda menunggu beberapa ratus milidetik setelah pengalihan sisi klien terjadi. Ini akan menghentikan Busur derajat dari melemparkan pesan kesalahan, meskipun itu tidak akan memungkinkan Busur derajat untuk bootstrap dengan benar sehingga dapat menyebabkan beberapa masalah tak terduga lainnya (terutama jika Anda menggunakan plugin atau modul tiruan).

Sebenarnya, saya menggunakan sesuatu seperti ini sebagai solusi yang saya tahu akan ada pengalihan:

(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 , itu sempurna! Itulah yang saya harapkan untuk dilakukan waitForAngular - tunggu sudut tersedia.

Ketika busur derajat mulai, itu selalu menuju ke baseUrl lalu halaman pengujian saya. Apakah itu dianggap sebagai pengalihan yang Anda bicarakan?

Tidak cukup @patrickliechty , maksud saya ketika Anda mengklik tautan (seperti <a href='google.com'> ) dan mengarahkan browser ke google.cm

@juliemr dengan @hankduan sudah pergi, apakah ada orang yang bekerja untuk perbaikan jangka panjang ini lagi?

@sjelin , apakah masalah ini masih ada di busur derajat 3.1.1. Saya bisa melihat yang satu itu

1 untuk perbaikan yang lebih baik. Mengalami hal ini hari ini tanpa tahu bagaimana mengatasinya dengan andal. Terima kasih!

Memiliki Masalah yang sama !!! terima kasih @tassoevan untuk perbaikan yang andal

1 untuk perbaikan.

Saya mendapat kesalahan ini dengan melakukan elemen (). GetText () di luar spesifikasi (tanpa browser.get () terjadi) - mencoba membuat pintasan untuk output div tertentu di luar spesifikasi. Mengubahnya menjadi sebuah fungsi dan semuanya baik-baik saja.

Saya mendapatkan kesalahan ini ketika menjalankan terhadap \ node_modules \ protractor \ example \ conf.js, tentunya contoh conf.js harus selalu berfungsi apa pun ??

Untuk orang yang menggunakan Busur derajat tanpa Sudut, apakah ada solusinya?

@Overdrivr Anda dapat menyetel browser.ignoreSynchronization = true; untuk memberitahu Busur derajat untuk tidak menunggu Angular.

browser.ignoreSynchronization = true berfungsi untuk saya ketika saya beralih jendela.

OK tapi kemudian U perlu menyetel browser.ignoreSynchronization = false;

Saya mendapatkan kesalahan ini dan itu berisi tautan ke masalah github ini.

Inilah yang saya miliki:

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

//Mengatur
Tes dimulai pada aplikasi sudut.
memulai pekerjaan mapreduce di URL bukan aplikasi sudut
kembali ke aplikasi sudut untuk mencatat jumlah baris

//Bertindak
menghapus 1 catatan
memverifikasi penghapusan terjadi

// Menegaskan
memulai pekerjaan mapreduce di URL bukan aplikasi sudut
_fails_ kedua kalinya sebelum kita dapat mengonfirmasi bahwa pekerjaan mapreduce membuat ulang data (jumlah baris yang sama sebelum penghapusan).

Berikut detail log yang relevan:

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:

Itu selalu gagal untuk kedua kalinya melalui waitForMapReduceJobToComplete di log 'tunggu'.

Solusinya "didokumentasikan" di sini: https://github.com/angular/protractor/issues/2787

Di dalam browser.wait Anda harus mengatur ulang ignoreSynchronization. Saya melakukan ini untuk semua browser. Menunggu di mana ignoreSynchronization sudah benar.

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

Tes saya berhasil sekarang.

Apakah Anda punya solusi untuk menunggu menggunakan browser.ExpectedConditions?

Bagaimana tampilan patch jika Anda akan menggunakan kode ini?

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

Terima kasih!

@azachar yang satu ini sepertinya berhasil:

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

Saya tidak tahu apa yang terjadi, untuk beberapa alasan di blok ini ignoreSynchronization masih salah sampai Anda memaksanya. Saya menindaklanjuti # 2787 dengan ini.

UPDATE: Ada kondisi balapan jika Anda mengatur / mengatur ulang ignoreSynchronization , lebih baik letakkan di aliran kontrol. Lihat # 4061.

Saya mendapatkan ini tanpa ignoreSynchronization dengan sesuatu seperti ini ....

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 sepertinya perlu beberapa saat untuk dimuat dan setTimeout ini tidak membantu. browser.wait tampaknya membantu sedikit tetapi masih gagal.

@tassoevan hi mengonfigurasi browser itu. menunggu () seperti deskripsi Anda dan di mana mengonfigurasinya

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

in angular (2) - Pastikan spesifikasi Anda dimulai dengan 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');
});

Setelah melihat @tassoevan 's solusi besar dan mendapatkan tes redirect saya bekerja, saya pikir saya akan berbagi saya naskah dan Angular2 solusi. Saya meletakkan fungsi ini pada kelas halaman abstrak saya, tapi saya pikir itu mungkin lebih cocok pada objek 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);
}

Inilah contoh bagaimana saya menggunakannya dalam ujian:

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

Halaman login saya adalah halaman js non-Angular. Setelah saya login ke halaman aplikasi Angular js dibuat. Jadi saya membuat file spesifikasi seperti yang diberikan di bawah ini:

deskripsikan ('Masuk ke Aplikasi', fungsi () {
var userID = elemen (by.name ('username'));
var password = elemen (by.name ('password'));
var logInButton = elemen (by.id ('Kirim'));

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

}

beforeEach (function () {
browser.ignoreSynchronisation = true;
browser.get (''); // yang akan membuka halaman login aplikasi
});

itu ('memiliki login ke aplikasi', function () {
loginToApplication ('77777', 'test')
browser.ignoreSynchronisation = false
mengharapkan (browser.getTitle ()). toEqual ('Software');
});
});

Mendapatkan pesan kesalahan di bawah ini:
Gagal: Kesalahan saat menunggu Busur derajat disinkronkan dengan halaman: "window.an
gular tidak ditentukan. Ini bisa jadi karena ini adalah halaman non-sudut atau
karena pengujian Anda melibatkan navigasi sisi klien, yang dapat mengganggu Prot
bootstrap ractor. Lihat http://git.io/v4gXM untuk detailnya "

Hai lihat di http://www.protractortest.org/#/timeouts # how-to-disable-waiting-for-angular
Biasanya ada beberapa cara untuk login menggunakan halaman non-Angular tetapi pertama-tama coba yang satu ini di dokumen.
Salam Hormat
Unta

Saya menyadari bahwa ini adalah diskusi yang panjang, tetapi ini mungkin bisa membantu seseorang.

Pesan kesalahan seperti itu juga dapat terjadi saat halaman memuat ulang secara tidak terduga karena kesalahan yang tidak tertangani terjadi di komponen Angular. Fakta bahwa konsol browser mungkin tidak bertahan , bersama dengan seberapa cepat pengujian dijalankan membuat saya tidak bisa langsung memahami apa yang sedang terjadi.

Jadi mungkin ada sesuatu yang bisa dilakukan sejauh menyangkut pesan kesalahan, karena kasus yang disebutkan di atas bukanlah 'navigasi sisi klien' per se :)

Hai @AngelBoy

Tnx untuk info tambahan Anda. Mungkin Anda bisa menambahkan PR untuk menjelaskan ini di dokumen jika Anda mau?

Saat ini saya mendapatkan kesalahan ini saat melakukan perjalanan ke halaman login kami (masalah umum):

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"

Melakukan trik ignoreSync sepertinya tidak membantu:

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

Tautan mendarat di sini di utas ini, tetapi apa yang harus dilakukan selanjutnya tidak sepenuhnya jelas.

Diuji dengan versi Protractor: 5.2.1, 5.1.1, 5.1.0, 5.0.0

@benjaminapetersen - Anda dapat mencoba menggunakan waitForAngularEnabled alih-alih ignoreSynchronization . Saya melihat halaman referensi API untuk Protractor v5.1.2 dan tidak lagi menyertakan ignoreSynchronization , tetapi melihat melalui CHANGELOG Saya tidak melihat kapan, jika pernah, properti itu secara resmi tidak digunakan lagi ...

Saya mencoba waitForAngularEnabled tetapi saya masih mendapatkan kesalahan yang sama seperti @benjaminapetersen . Ini konfigurasi saya saat ini:

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

@thompnm terima kasih! Meskipun sepertinya waitForAngularEnabled juga tidak digunakan lagi ....

@benjaminapetersen bahwa tag doc yang tidak digunakan lagi ada di properti ignoreSynchronization , bukan waitForAngularEnabled

waitForAngularEnabled juga tidak berfungsi untuk saya. Ini berfungsi dengan IgnoreSynchronization sebelum meningkatkan ke Protractor 5. Saya perlu beralih ke iframe non-Angular, dan sekarang saya tidak bisa. Mohon saran. Terima kasih

@ seel93 Cobalah mengomentari rootElement: 'app' , atau coba menggantinya dengan rootElement: '*[ng-app]' .
Saya baru saja menginstal busur derajat versi terbaru dan menulis beberapa spesifikasi untuk aplikasi Angular 1.6.1 dan tampaknya berfungsi dengan baik sejauh ini. Saya menemukan pesan kesalahan itu ketika saya mencoba masuk ke aplikasi saya, tetapi saya sekarang menggunakan pendekatan ini:

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

Catatan: Saya memiliki ng-app pada tag html

rootElement: '*[ng-app]' ? bekerja hanya untuk mencari halaman untuk node apa pun? Belum pernah melihat ini sebelumnya.

Saya baru saja menyelesaikan masalah saya. 🥇 Akar penyebab: Efek samping konsol pengembang

Saya mengalami masalah ini dan perbaikan untuk saya akhirnya mengubah busur derajat "^ 5.3.2" di package.json saya

Saya memiliki halaman login biasa dan kemudian saya mengarahkan ke halaman sudut.

Jadi saya tidak tahu persis bagaimana atau mengapa ini bekerja, karena saya benar-benar baru mengenal sudut dan sudut e2e, tapi saya berhasil setelah saya menggunakan browser.waitForAngularEnabled(false); dua kali.

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

Semoga membantu.

Solusi terakhir itu hampir berhasil untuk saya kecuali saya mendapat kesalahan setelah tes berlalu:
Kesalahan: ECONNREFUSED connect ECONNREFUSED 127.0.0.1:4444 Dari: Tugas: WebDriver.getCurrentUrl ()

Saya mendapat kesalahan ini dengan melakukan elemen (). GetText () di luar spesifikasi (tanpa browser.get () terjadi) - mencoba membuat pintasan untuk output div tertentu di luar spesifikasi. Mengubahnya menjadi sebuah fungsi dan semuanya baik-baik saja.

Ia bekerja untuk apa saja, Anda tidak dapat menggunakan lebih dari satu 'elemen (). Anyfunction ()' di luar 'itu'.
Menemukannya dengan cara yang sulit ...

Mendapat kesalahan saat beralih dari satu halaman web ke halaman lain di Busur derajat:

Gagal: Kesalahan saat menunggu Busur derajat disinkronkan dengan halaman: "baik testabilitas angularJS dan testabilitas sudut tidak ditentukan. Ini bisa jadi karena ini adalah halaman non-sudut atau karena pengujian Anda melibatkan navigasi sisi klien, yang dapat mengganggu Busur derajat bootstrap. Lihat http://git.io/v4gXM untuk detailnya "

kodenya adalah:
var url = browser.params.login.Url;
browser.get (url + '/ #! / app / manage-users');

Saya mulai mendapatkan kesalahan ini tiba-tiba CT saya terbentuk. Saya perhatikan bahwa kesalahan ini hanya terjadi dengan Firefox headless dan berfungsi dengan baik dengan Chrome headless di Linux. Saya memutakhirkan dari Firefox v69 ke yang terbaru (v72.0.2 saat ini) yang memperbaiki masalah ini.

browser.ignoreSynchronization sudah tidak digunakan lagi dan seharusnya tidak digunakan. Seperti yang diisyaratkan dari pos asli, menggunakan browser.get sepertinya bisa menyelesaikan masalah.

Jika Anda ingin menggunakannya dengan cara yang dapat menonaktifkan dan mengaktifkan waitForAngularEnabled sesuka hati, Anda perlu menggunakan browser.get setelah menyetel waitForAngularEnabled(true) . Sebagai contoh:

// 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 blok sampai halaman Angular dimuat.

Saat ini saya mengalami kesalahan ini:

_Exception telah terjadi: Error: Error saat menunggu Protractor disinkronkan dengan halaman: "testability angularJS dan angular testability tidak ditentukan. Ini bisa jadi karena ini adalah halaman non-sudut atau karena pengujian Anda melibatkan navigasi sisi klien, yang mana dapat mengganggu bootstrap Busur Derajat. Lihat http://git.io/v4gXM untuk detailnya "_

Tetapi hanya saat mencoba men-debug melalui debugger VS Code atau debug chrome inspector (ikuti petunjuk di sini untuk kedua kasus tersebut https://www.protractortest.org/#/debugging).

Inilah konfigurasi launch.json di VSCode.

{
    "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"
            ]
        }
    ]
}

Mungkin itu adalah kesalahan yang telah saya atur. Bantuan apa pun sangat kami hargai, mencoba menulis ini tanpa dapat melakukan debug dengan benar sangatlah sulit.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat