Transportador: ¿Cómo esperar a que se complete la página después de hacer clic en un botón?

78

En una especificación de prueba, necesito hacer clic en un botón en una página web y esperar a que la nueva página se cargue por completo.

emailEl.sendKeys('jack');
passwordEl.sendKeys('123pwd');

btnLoginEl.click();

// ...Here need to wait for page complete... How?

ptor.waitForAngular();
expect(ptor.getCurrentUrl()).toEqual(url + 'abc#/efg');
Zach
fuente
2
¿Podría ser más específico en la página que está esperando? ¿Está esperando un cambio de página o una carga asincrónica?
Furzel

Respuestas:

92

Dependiendo de lo que quieras hacer, puedes probar:

browser.waitForAngular();

o

btnLoginEl.click().then(function() {
  // do some stuff 
}); 

para resolver la promesa. Sería mejor si pudiera hacerlo en el beforeEach.

NB: Me di cuenta de que el esperar () espera a que se resuelva la promesa dentro (es decir, getCurrentUrl) antes de comparar.

glepretre
fuente
Gracias por compartir, ayudó a identificar algunos problemas intermitentes extraños.
Hakan Serce
1
Todavía tengo el problema: Se agotó el tiempo de espera del resultado del script asincrónico
Emna Ayadi
3
Esto no resolvió mi problema de esperar a que javascript terminara de modificar la página después de hacer clic en el botón. Agregar browser.driver.sleep(1000)como se sugiere a continuación hizo el truco.
CGFoX
3
waitForAngular() no debe utilizarse . Acerca de click().then()que no funcionó para mí. Solo podía confiar en browser.wait(//use of protractor.ExpectedConditions).
Coli
30

Acabo de echar un vistazo a la fuente: Protractor está esperando Angular solo en algunos casos (como cuando element.allse invoca o configura / obtiene la ubicación).

Entonces Protractor no esperará a que Angular se estabilice después de cada comando.

Además, parece que a veces en mis pruebas tuve una carrera entre el ciclo de resumen angular y el evento de clic, así que a veces tengo que hacer:

elm.click();
browser.driver.sleep(1000);
browser.waitForAngular();

usando sleep para esperar la ejecución para ingresar al contexto AngularJS (desencadenado por un clickevento)

Filip Sobczak
fuente
1
Transportador no sincroniza el .click (), sincronizó la siguiente operación que involucra ElementFinder / ElementArrayFinder.
Max
Sé por experiencia que el transportador esperará angular al evaluar las expectativas usando expect. En otros casos utilizo explícitamente waitForAngular.
jrharshath
1
aunque tu publicación tiene casi dos años, creo que todavía tienes razón. Actualmente necesito agregar un '.sleep (1000)' después de un transportador element(by.css('my-css')).click(). Parece que el .click NO está esperando, aunque se devuelve una promesa.
bob.mazzo
Siempre uso promesas. Por ejemplo:return elm.click().then(function () { return nextAction(); }
Ed Greaves
3
No recomendaré usar suspensiones explícitas, ya que duermes incluso si tu aplicación se carga más rápido que la suspensión configurada.
timbru31
25

No es necesario esperar. El transportador espera automáticamente a que angular esté listo y luego ejecuta el siguiente paso en el flujo de control.

Andrés D
fuente
5
en teoría, sí, porque waitForAngular()se llama internamente, pero también tuve que llamarlo para algunas especificaciones.
glepretre
8
¿Espera automáticamente? Mirando algo como browser.get, dice explícitamente que existe para sobrescribir lo que envuelve. Si no hay un clickmétodo para ElementFinder, entonces parece que solo delega en webDriver.WebElement. angular.github.io/protractor/#/api?view=ElementFinder
Snekse
5
@Snekse Protractor sincronizó todas las operaciones sobre ElementFinder y ElementArrayFinder. Entonces, cada vez que su prueba intente buscar cualquier elemento, la búsqueda en sí esperará a que angular complete el ciclo de digestión y luego delegará la llamada a webdriver. Lo mismo sucede en la llamada a esperar ().
Max
8
Si no tuviéramos que esperar, este hilo no se habría visto 100.000 veces.
Justin
7

Con transportador, puede utilizar el siguiente enfoque

var EC = protractor.ExpectedConditions;
// Wait for new page url to contain newPageName
browser.wait(EC.urlContains('newPageName'), 10000);

Entonces su código se verá algo así como,

emailEl.sendKeys('jack');
passwordEl.sendKeys('123pwd');

btnLoginEl.click();

var EC = protractor.ExpectedConditions;
// Wait for new page url to contain efg
ptor.wait(EC.urlContains('efg'), 10000);

expect(ptor.getCurrentUrl()).toEqual(url + 'abc#/efg');

Nota: Esto puede no significar que la nueva página haya terminado de cargarse y que DOM esté listo. La siguiente declaración 'espera ()' asegurará que Transportador espere a que DOM esté disponible para la prueba.

Referencia: condiciones esperadas del transportador

milán pandya
fuente
3

En este caso, puede utilizar:

Objeto de página:

    waitForURLContain(urlExpected: string, timeout: number) {
        try {
            const condition = browser.ExpectedConditions;
            browser.wait(condition.urlContains(urlExpected), timeout);
        } catch (e) {
            console.error('URL not contain text.', e);
        };
    }

Prueba de página:

page.waitForURLContain('abc#/efg', 30000);
Presa de Dao Minh
fuente
2

Por lo general, solo agrego algo al flujo de control, es decir:

it('should navigate to the logfile page when attempting ' +
   'to access the user login page, after logging in', function() {
  userLoginPage.login(true);
  userLoginPage.get();
  logfilePage.expectLogfilePage();
});

logfilePage:

function login() {
  element(by.buttonText('Login')).click();

  // Adding this to the control flow will ensure the resulting page is loaded before moving on
  browser.getLocationAbsUrl();
}
Justin Helmer
fuente
1

Usa esto, creo que es mejor

   *isAngularSite(false);*
    browser.get(crmUrl);


    login.username.sendKeys(username);
    login.password.sendKeys(password);
    login.submit.click();

    *isAngularSite(true);*

Para que pueda utilizar esta configuración de isAngularSite, debe poner esto en su protractor.conf.js aquí:

        global.isAngularSite = function(flag) {
        browser.ignoreSynchronization = !flag;
        };
Dantinho
fuente
-1

puedes hacer algo como esto

emailEl.sendKeys('jack');
passwordEl.sendKeys('123pwd');

btnLoginEl.click().then(function(){
browser.wait(5000);
});

ashish bansal
fuente
browser.wait (5000) devolverá "No asignable a la función de tipo", ya que browser.wait toma> 1 argumentos, el primero es una condición, el segundo es el tiempo ...
IWI
-2
browser.waitForAngular();

btnLoginEl.click().then(function() { Do Something });

para resolver la promesa.

Shiwantha Lakmal
fuente