web-dev-qa-db-de.com

Wie kann ich auf eine Bedingung warten?

Ich bin neu im Winkelmesser und versuche, einen e2e-Test zu implementieren ist keine vollständige Winkelseite, also ... ich habe einige Probleme.

Auf meiner ersten Spezifikation habe ich: 

describe('should open contact page', function() {
var ptor = protractor.getInstance();

beforeEach(function(){

   var Login = require('./util/Login');
   new Login(ptor);
});

Ich habe diese Login-Klasse erstellt, aber nach dem Anmelden möchte ich die Kontaktseite öffnen. Der Winkelmesser versucht jedoch sofort, das Element zu finden, bevor die Seite vollständig geladen ist.

Ich habe versucht zu verwenden:

browser.driver.wait(function() {

    expect(browser.findElement(by.xpath("//a[@href='#/contacts']")).isDisplayed());
    ptor.findElement(by.xpath("//a[@href='#/contacts']")).click();

});

Aber es funktioniert nicht ... es wird immer versucht, das Element zu finden, bevor die Seite geladen wird . Ich habe auch dieses versucht:

browser.driver.wait(function() {
    expect(ptor.isElementPresent(by.xpath("//a[@href='#/contacts']")));          
    ptor.findElement(by.xpath("//a[@href='#/contacts']")).click();
});

Ich kann das mit browser.sleep();, aber ich denke nicht, dass dies eine gute Option ist. Irgendeine Idee? In meiner Login-Klasse habe ich:

ptor.ignoreSynchronization = true;

Wie kann ich auf diesen @href='#/contacts warten, bevor der Winkelmesser versucht, darauf zu klicken?

48
Muratso

Ich hatte das gleiche Problem, das Sie am längsten mit dem Winkelmesser hatten. In meinem e2e-Test starte ich in einer nicht winkeligen App, steige dann in einen winkeligen Bereich und wieder in einen nicht winkeligen Bereich. Dinge knifflig gemacht. Der Schlüssel ist, die Versprechen zu verstehen und wie sie funktionieren. Hier sind einige Beispiele meines realen Codes in einem funktionierenden e2e-Test. Wenn Sie hoffen, dass Sie so einen Eindruck bekommen, wie Sie Ihre Tests strukturieren? Wahrscheinlich eine schlechte Praxis in diesem Code, bitte verbessern Sie dies, aber ich weiß, dass es funktioniert, vielleicht nicht der beste Weg.

Um zu Winkel zu kommen, benutze ich

var ptor;
var events = require('events');
var eventEmitter = new events.EventEmitter();
var secondClick = require('./second-click');

beforeEach(function () {
    browser.driver.get('http://localhost:8080/');
},10000);

it("should start the test", function () {
    describe("starting", function () {
        it("should find the  link and start the test", function(){
            var elementToFind = by.linkText('Start'); //what element we are looking for
            browser.driver.isElementPresent(elementToFind).then(function(isPresent){
                expect(isPresent).toBe(true); //the test, kind of redundant but it helps pass or fail
                browser.driver.findElement(elementToFind).then(function(start){
                    start.click().then(function(){ //once we've found the element and its on the page click it!! :) 
                        ptor = protractor.getInstance(); //pass down protractor and the events to other files so we can emit events
                        secondClick(eventEmitter, ptor); //this is your callback to keep going on to other actions or test in another file
                    });
                });
            });
        });
    });
},60000);

Im Winkel funktioniert dieser Code

 describe("type in a message ", function(){
        it("should find and type in a random message", function(){
            var elementToFind = by.css('form textarea.limited');
            browser.driver.isElementPresent(elementToFind).then(function(isPresent){
                element(elementToFind).sendKeys(randomSentence).then(function(){
                    console.log("typed in random message");
                    continueOn();
                });
            });
        });
    },15000);

Nach dem Verlassen des Winkels

browser.driver.wait(function(){
   console.log("polling for a firstName to appear");
   return    browser.driver.isElementPresent(by.name('firstName')).then(function(el){
         return el === true;
       });
     }).
   then(function(){
       somefunctionToExecute()
    });

Hoffe, das gibt eine Anleitung und hilft dir raus!

23
asherrard

Der Winkelmesser 1.7.0 hat auch eine neue Funktion eingeführt: Erwartete Bedingungen .

Es gibt mehrere vordefinierte Bedingungen, auf die explizit gewartet werden soll. Wenn Sie auf die Anwesenheit eines Elements warten möchten:

var EC = protractor.ExpectedConditions;

var e = element(by.id('xyz'));
browser.wait(EC.presenceOf(e), 10000);

expect(e.isPresent()).toBeTruthy();

Siehe auch:

51
alecxe

Ich finde es endlich heraus ...

   var waitLoading = by.css('#loading.loader-state-hidden');

   browser.wait(function() {
       return ptor.isElementPresent(waitLoading);
   }, 8000);

   expect(ptor.isElementPresent(waitLoading)).toBeTruthy();

   var openContact = by.xpath("//a[@href='#/contacts']");
   element(openContact).click();

Mit diesem Winkelmesser konnte auf dieses Element gewartet werden, bis die Ladeseite verschwunden ist .. Vielen Dank für alle, die XD helfen wollten.

33
Muratso
browser.driver.wait(function() {
    return browser.driver.isElementPresent(by.xpath("//a[@href='#/contacts']"));
});

Das funktioniert auch für mich (ohne das Zeitlimit param) ..

weitere Informationen finden Sie unter http://angular.github.io/protractor/#/api?view=webdriver.WebDriver.prototype.wait

9
Henry Neo

Dank der obigen Antworten war dies meine vereinfachte und aktualisierte Verwendung

function waitFor (selector) {
  return browser.wait(function () {
    return browser.isElementPresent(by.css(selector));
  }, 50000);
}
1
Kirk Strobeck

Ich bin überrascht, dass niemand diese Lösung hinzugefügt hat. Wenn Sie modale Dialoge verwenden, erhalten Sie im Allgemeinen ein sichtbares Element, das angeklickt werden kann, jedoch nicht anklickbar ist. Dies geschieht, weil sich der Winkelmesser schneller bewegt als der Winkel und bereit ist, das nächste Element anzuklicken, während der Modal durch Winkel noch geschlossen wird.

Ich schlage vor zu verwenden

public async clickElementBug(elementLocator: Locator) {
const elem = await element(elementLocator);
await browser.wait(
  async function() {
    try {
      await elem.click();
      return true;
    } catch (error) {
      return false;
    }
  },
  this.TIMEOUT_MILLIS,
  'Clicking of element failed: ' + elem
);

}

0
Raymond Kelly

Haben Sie versucht, den ng-app in das <html>-Tag zu setzen (vorausgesetzt, dieser Teil des Codes steht unter Ihrer Kontrolle)? Dies löste für mich viele Probleme beim Initialisierungszeitpunkt.

0

Beste Möglichkeit, Wartebedingungen im Winkelmesser zu verwenden, die dazu beitragen, die richtige Fehlermeldung für ein bestimmtes Element anzuzeigen, wenn der Testfall fehlgeschlagen ist

const EC = ExpectedConditions;
const ele = element(by.xpath(your xpath));

return browser.wait(EC.visibilityOf(ele),9000,'element not found').then(() => {
            ele.click();
         });
0
rohit saini