Winkelmesser: Wie kann ich warten, bis die Seite vollständig ist, nachdem ich auf eine Schaltfläche geklickt habe?

78

In einer Testspezifikation muss ich auf eine Schaltfläche auf einer Webseite klicken und warten, bis die neue Seite vollständig geladen ist.

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
quelle
2
Könnten Sie auf der Seite, auf die Sie warten, genauer sein? Warten Sie nur auf einen Seitenwechsel oder auf ein asynchrones Laden?
Furzel

Antworten:

92

Je nachdem, was Sie tun möchten, können Sie Folgendes versuchen:

browser.waitForAngular();

oder

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

das Versprechen zu lösen. Es wäre besser, wenn Sie das in der tun können beforeEach.

NB: Mir ist aufgefallen, dass Expect () darauf wartet, dass das Versprechen (dh getCurrentUrl) vor dem Vergleich gelöst wird.

glepretre
quelle
Vielen Dank für das Teilen, hat geholfen, einige seltsame zeitweise auftretende Probleme zu identifizieren.
Hakan Serce
1
Ich habe immer noch das Problem:
Zeitüberschreitung
3
Dies löste nicht mein Problem, darauf zu warten, dass Javascript die Änderung der Seite nach dem Klicken auf die Schaltfläche beendet. Das Hinzufügen browser.driver.sleep(1000)wie unten vorgeschlagen hat den Trick getan.
CGFoX
3
waitForAngular() sollte nicht verwendet werden . Über das hat click().then()es bei mir nicht geklappt. Ich konnte mich nur darauf verlassen browser.wait(//use of protractor.ExpectedConditions).
Coli
30

Ich habe mir gerade die Quelle angesehen - Winkelmesser wartet nur in wenigen Fällen auf Angular (z. B. wenn er element.allaufgerufen wird oder wenn der Standort festgelegt / abgerufen wird).

Der Winkelmesser wartet also nicht darauf, dass sich Angular nach jedem Befehl stabilisiert.

Außerdem sieht es so aus, als hätte ich in meinen Tests manchmal ein Rennen zwischen dem Angular Digest-Zyklus und dem Klick-Ereignis gehabt, also muss ich manchmal Folgendes tun:

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

Verwenden Sie sleep, um auf die Ausführung zu warten, um in den AngularJS-Kontext zu gelangen (ausgelöst durch ein clickEreignis).

Filip Sobczak
quelle
1
Der Winkelmesser synchronisiert nicht .click (), sondern die nächste Operation, an der ElementFinder / ElementArrayFinder beteiligt ist.
Max
Ich weiß aus Erfahrung, dass Winkelmesser bei der Bewertung der Erwartungen mit auf Winkel warten expect. In anderen Fällen verwende ich ausdrücklich waitForAngular.
Jrharshath
1
Obwohl Ihr Beitrag fast zwei Jahre alt ist, finde ich, dass Sie immer noch Recht haben. Ich muss derzeit nach einem Winkelmesser eine '.sleep (1000)' hinzufügen element(by.css('my-css')).click(). Es scheint, dass der .click NICHT wartet, obwohl ein Versprechen zurückgegeben wird.
Bob.mazzo
Ich benutze immer Versprechen. Zum Beispiel:return elm.click().then(function () { return nextAction(); }
Ed Greaves
3
Ich empfehle nicht, explizite Ruhezustände zu verwenden, da Sie auch dann schlafen, wenn Ihre Anwendung schneller als der konfigurierte Ruhezustand geladen wird.
Timbru31
25

Sie müssen nicht warten. Der Winkelmesser wartet automatisch darauf, dass der Winkel bereit ist, und führt dann den nächsten Schritt im Kontrollfluss aus.

Andres D.
quelle
5
theoretisch ja, weil waitForAngular()intern aufgerufen wird, aber ich musste es auch für einige Spezifikationen nennen.
Glepretre
8
Wartet es automatisch? Wenn man so etwas betrachtet browser.get, sagt es ausdrücklich, dass es existiert, um das, was es umhüllt, zu überschreiben. Wenn es keine clickMethode für gibt ElementFinder, dann scheint es, als würde es nur an die delegieren webDriver.WebElement. angle.github.io/protractor/#/api?view=ElementFinder
Snekse
5
@Snekse Protractor synchronisierte alle Operationen über ElementFinder und ElementArrayFinder. Wenn Ihr Test also versucht, ein Element zu suchen, wartet die Suche selbst darauf, dass Angular den Digestionszyklus abschließt, und delegiert den Aufruf dann an den Webdriver. Gleiches passiert beim Aufruf von expected ().
Max
8
Wenn wir nicht warten müssten, wäre dieser Thread nicht 100.000 Mal angesehen worden.
Justin
7

Mit Winkelmesser können Sie den folgenden Ansatz verwenden

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

Ihr Code sieht also ungefähr so ​​aus:

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

Hinweis: Dies bedeutet möglicherweise nicht, dass die neue Seite vollständig geladen wurde und DOM bereit ist. Die nachfolgende Anweisung 'expected ()' stellt sicher, dass der Winkelmesser darauf wartet, dass DOM für den Test verfügbar ist.

Referenz: Winkelmesser ExpectedConditions

Mailand Pandya
quelle
3

In diesem Fall können Sie Folgendes verwenden:

Seitenobjekt:

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

Seitentest:

page.waitForURLContain('abc#/efg', 30000);
Dao Minh Dam
quelle
2

Normalerweise füge ich dem Kontrollfluss einfach etwas hinzu, dh:

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
quelle
1

Verwenden Sie dies, ich denke, es ist besser

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


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

    *isAngularSite(true);*

Damit Sie diese Einstellung von isAngularSite verwenden können, sollten Sie dies hier in Ihre protractor.conf.js einfügen:

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

Sie können so etwas tun

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

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

aschiges Bansal
quelle
browser.wait (5000) gibt "Nicht der Typfunktion zuweisbar" zurück, da browser.wait> 1 Argumente akzeptiert, wobei das erste eine Bedingung ist, das zweite die Zeit ...
IWI
-2
browser.waitForAngular();

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

das Versprechen zu lösen.

Shiwantha Lakmal
quelle