Cant get protractor to wait for an existing element to be clickable (condition.elementToBeClickable)

Question

We have an Angular 1.5 application which has a login screen, nothing was changed in the app code nor in our tests. we use protractor (with grunt-protractor etc..)
versions:

  "dependencies": {
    "async": "^0.9.0",
    "chalk": "^1.1.1",
    "fs-extra": "^0.24.0",
    "grunt": "~0.4.5",
    "grunt-contrib-jshint": "^0.10.0",
    "grunt-protractor-runner": "^4.0.0",
    "grunt-protractor-webdriver": "^0.2.5",
    "jshint-stylish": "^1.0.0",
    "load-grunt-tasks": "~3.1.0",
    "lodash": "^2.4.1",
    "log4js": "^0.6.21",
    "protractor": "^4.0.11",
    "selenium-webdriver": "^3.0.1"
  }

All of our tests are in the following format:

  • login to the app and sleep
  • the tests (it). each it gets the done() function which called by the end of the test from the browser.sleep('1000').then(done) promise (jasmine syntax).

    describe('login', function () {
        browser.get('/');
        components.login.loginDefault();
        console.log('done login');
        browser.driver.manage().window().maximize(); // just in case the driver wont reach the '.add-new-type' button 
        browser.sleep(1000);
    });
    
    describe('post login', function () {
        it('just a test for after user loged in', function (done) {
            console.log('post login');
            const ec = protractor.ExpectedConditions;
            const getStarted = element(by.css('.add-new-type')); // just a button appears on the next page
            console.log('getStarted ' + JSON.stringify(getStarted));
            browser.wait(ec.elementToBeClickable(getStarted), 5000);
            console.log('post wait');
            browser.sleep(5000).then(done);
       })});  
    

We didn't change the dependencies versions or nothing in our environment, suddenly nothing works, the tests only pass the login phase and then fail for not finding the element (I guess) and stuck until jasmine throws timeout exception

Session created: count=1, browserName=chrome, chromeOptions={args=[--no-sandbox, --test-type=browser, --disable-extensions], prefs={download={default_directory=./e2e/tmp, prompt_for_download=false}}}
node path changed
done login
Started
post login
F 

The post login test is just an example, we tried other ways to make the driver wait beside wait for 'ExpectedConditions'. If I'll look for the element in the console debugger (chrome) I'll get the element properly... We also tried to debug and on repl mode printed

element(by.css('.add-new-type')).getText()

and the behavior was the same - nothing / no response

Will any help!


Show source
| angularjs   | protractor   | selenium   | automated-tests   2017-01-04 10:01 3 Answers

Answers ( 3 )

  1. 2017-01-04 10:01

    I think it's because your tests are running faster than the browser can load your element, see if this works;

    describe('post login', function () {
    it('just a test for after user loged in', function (done) {
        console.log('post login');
        const ec = protractor.ExpectedConditions;
        const getStarted = element(by.css('.add-new-type'));
    
        browser.wait(ec.visibilityOf(getStarted), 5000);
    
        console.log('getStarted ' + JSON.stringify(getStarted));
        browser.wait(ec.elementToBeClickable(getStarted), 5000);
        console.log('post wait');
        browser.sleep(5000).then(done);
    })});  
    

    Hope it helps!

  2. 2017-01-04 11:01

    Have you tried wait for elements and urls?

    'use strict';
    
    var WaitUtils = function () {
    
        this.waitElement = function (element , timeout) {
            timeout = timeout || browser.params.time.long;
            var expected = protractor.ExpectedConditions;
            return browser.wait(expected.visibilityOf(element), timeout, "Element not found");
        };
    
        this.waitUrl = function (url, timeout) {
            timeout = timeout || browser.params.time.long;
            var expected = protractor.ExpectedConditions;
            return browser.wait(expected.urlContains(url), timeout, "URL has not contains "+url);
        };
    };
    
    module.exports = WaitUtils;
    
  3. 2017-01-05 08:01

    So after investigating it, I found the problematic commit, we hadn't changed any css in our application but I did implemented an autosave mechanism using $timeout. I think our internal timeout somehow caused conflict with protractor's timeout... refer to the issue here (protractor's github repo)

    They suggested using $interval instead of timeout - this is actually solved the problem but I'm not sure if I want to use this workaround.

◀ Go back