Protractor tests inconsistently passing / failing for AngularJS app

后端 未结 3 1405
野趣味
野趣味 2021-01-31 20:20

My Protractor e2e tests are inconsistently passing and failing.

It seems this could be due to asynchronous javascript, as discussed here: Protractor : How to wait for

相关标签:
3条回答
  • 2021-01-31 20:41

    There is also an another technique to make your tests more stable: Explicit Waits and Expected Conditions (docs).

    I've found using Expected Conditions especially useful when testing against non-angular pages or angular applications that have a lot of animations involved.

    For example, you can wait for an element to be clickable before making a click:

    var EC = protractor.ExpectedConditions;
    var link = element(by.id("mylink"));
    
    browser.wait(EC.elementToBeClickable(link), "10000", "The link is still not clickable");
    link.click();
    

    There are also other built-in Expected Conditions, such as:

    • presenseOf()
    • visibilityOf()
    • alertIsPresent()
    • textToBePresentInElementValue()
    • etc

    And, it is easy to write a custom Expected Condition, example use case:

    • Testing link style changes

    You can also combine Expected Conditions using and, or and not, e.g.:

    var urlChanged = function() {
      return browser.getCurrentUrl().then(function(url) {
        return url != 'http://www.angularjs.org';
      });
    };
    
    // condition to wait for url to change, title to contain 'foo', and $('abc') element to contain text 'bar'
    var condition = EC.and(urlChanged, EC.titleContains('foo'), EC.textToBePresentInElement($('abc'), 'bar'));
    $('navButton').click();
    browser.wait(condition, 5000); //wait for condition to be true.
    
    0 讨论(0)
  • 2021-01-31 20:57

    browser.ignoreSynchronization = true; has a global effect for all your tests. you may have to set it back to false, so protractor waits for angular to be finished rendering the page. e.g. in or before your second beforeEach function

    0 讨论(0)
  • 2021-01-31 20:59

    I was able to resolve the issue based on the following:

    • Avishay's answer here about adding ptor.waitForAngular():
      No element found using locator: by.model() error

    • Changing browser.get to ptor.get, as in Harri Siirak's answer here:
      Protractor times out waiting for sync with page when using $resource

    • juliemr's comment here about ignoreSynchronization being an instance variable, and changing browser.ignoreSynchronization=true to ptor.ignoreSynchronization=true:
      https://github.com/angular/protractor/issues/49

    • glepretre's answer here about using .then():
      Protractor : How to wait for page complete after click a button?

    As mentioned by Nguyen Vu Hoang's comment to the original question, I am testing a pure Angular app with what I think is pure Protractor (no webdriver calls). I know ptor.ignoreSynchronization=true should not be required in this case, but for some reason, the tests are not proceeding at button click without this setting.

    My new spec:

    describe('Login', function() {
    
      var ptor;
    
      beforeEach(function() {
        ptor = protractor.getInstance();
        ptor.ignoreSynchronization = true;
        ptor.waitForAngular();
        ptor.get('https://127.0.0.1:8443');
        ptor.findElement(by.id('splash')).then(function(elem) {
            elem.click();
        });
      });
    
      describe('with correct email and password', function() {
    
        beforeEach(function() {
            ptor.findElement(by.id('email')).then(function(elem) {
                elem.sendKeys('admin@email.com');
            });
    
            ptor.findElement(by.id('password')).then(function(elem) {
                elem.sendKeys('adminpassword');
            });
    
            ptor.findElement(by.id('loginButton')).then(function(elem) {
                elem.click();
            });
        });
    
        afterEach(function() {
            ptor.findElement(by.id('logout')).then(function(elem) {
                elem.click();
            });
        });
    
        it('does not show alert', function() {
            expect(ptor.isElementPresent(by.css('.alert-danger'))).toBe(false);
        });
    
        it('changes route to /admin', function() {
            expect(ptor.getCurrentUrl()).toMatch(/\/admin/);
        });
      });
    });
    
    0 讨论(0)
提交回复
热议问题