1

I have a feature file like so:

Feature: Test feature

Scenario: Step 1
    Given I go to "test-process/#/step-1"
    When I have checked the checkbox
    Then the button is enabled

My steps.js file is as follows:

'use strict';

var chai = require('chai'),
    chaiAsPromised = require('chai-as-promised');

chai.use(chaiAsPromised);

module.exports = function () {

    this.Given(/^I go to "([^"]*)"$/, function (path, callback) {
        browser.get(path);

        callback();
    });

    this.When(/^When I have checked the checkbox$/, function (callback) {
        var checkbox = element(by.id('check'));
        checkbox.click();

        callback();
    });

    this.Then(/^the button is enabled$/, function (callback) {
        var button = element(by.id('next'));

        chai.expect(button.isEnabled()).to.eventually.equal(true).and.notify(callback);
    });

};

I also have a config like like this:

exports.config = {
    framework: 'custom',
    frameworkPath: '../../../../node_modules/protractor-cucumber-framework',
    seleniumAddress: 'http://localhost:4444/wd/hub',
    specs: ['features/*.feature'],
    baseUrl: 'http://localhost:60625/',
    cucumberOpts: {
        require: 'steps/*.steps.js',
        format: 'pretty'
    }
};

On the actual page, the checkbox and button both have the specified ID attributes.

When I run the test, the first two steps pass, but the last step fails with the reason:

ElementNotVisibleError: element not visible

However, I see Chrome launch and the checkbox and button are both visible on the page! the worst part is, when I wrote the test and ran it for the first time, all the steps passed. Now, it fails every time and nothing has actually changed.

Any ideas?

Edit

I've tried wrapping the callback invocations in then() as suggested. This has changed the output slightly but has not fixed the issue. Now, the second step fails and the last step is skipped. Previously, the second step passed, and the last step failed.

I've also tried making the window fullscreen as suggested with browser.driver.manage().window().maximize();

I've also tried adding a longer timeout with this.setDefaultTimeout(10000); but this appears not to have made any difference.

As requested, here is the stacktrace in the console output:

Running "protractor:all" (protractor) task Using the selenium server at http://localhost:4444/wd/hub [launcher] Running 1 instances of WebDriver

Scenario: Step 1
Given I go to "test-process/#/step-1"
When I have checked the checkbox

 ElementNotVisibleError: element not visible
    (Session info: chrome=47.0.2526.111)
    (Driver info: chromedriver=2.20.353145 
    (343b531d31eeb933ec778dbcf7081628a1396067),platform=Windows NT 6.1 SP1 x86_64) > (WARNING: The server did not provide any stacktrace information)
 Command duration or timeout: 15 milliseconds
 Build info: version: '2.48.2', revision: '41bccdd', time: '2015-10-09 19:59:12'
 System info: host: 'BDTUK79DW', ip: '172.23.83.166', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.8.0_71'
 Driver info: org.openqa.selenium.chrome.ChromeDriver
 Capabilities [{applicationCacheEnabled=false, rotatable=false, mobileEmulationEnabled=false, chrome={userDataDir=C:\Users\DanW\AppData\Local\Temp\scoped_dir14556_23663}, takesHeapSnapshot=true, databaseEnabled=false, handlesAlerts=true, hasTouchScreen=false, version=47.0.2526.111, platform=XP, browserConnectionEnabled=false, nativeEvents=true, acceptSslCerts=true, locationContextEnabled=true, webStorageEnabled=true, browserName=chrome, takesScreenshot=true, javascriptEnabled=true, cssSelectorsEnabled=true}]
 Session ID: 8591f8db6eea372305d94c1aea52eca0
      at new bot.Error (fakepath\node_modules\grunt-protractor-runner\node_modules\selenium-webdriver\lib\atoms\error.js:108:18)
      at Object.bot.response.checkResponse (fakepath\node_modules\grunt-protractor-runner\node_modules\selenium-webdriver\lib\atoms\response.js:109:9)
      at fakepath\node_modules\grunt-protractor-runner\node_modules\selenium-webdriver\lib\webdriver\webdriver.js:379:20
      at [object Object].promise.Promise.goog.defineClass.invokeCallback_ (fakepath/node_modules/grunt-protractor-runner/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:1337:14)
      at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_.execute_ (fakepath/node_modules/grunt-protractor-runner/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2776:14)
      at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_ (fakepath/node_modules/grunt-protractor-runner/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2758:21)
      at goog.async.run.processWorkQueue (fakepath\node_modules\grunt-protractor-runner\node_modules\selenium-webdriver\lib\goog\async\run.js:124:15)
      at process._tickCallback (node.js:405:9)
  Error
      at [object Object].ElementArrayFinder.applyAction_ (fakepath\node_modules\grunt-protractor-runner\node_modules\protractor\lib\element.js:382:21)
      at [object Object].ElementArrayFinder.(anonymous function) [as click] (fakepath\node_modules\grunt-protractor-runner\node_modules\protractor\lib\element.js:78:17)
      at [object Object].ElementFinder.(anonymous function) [as click] (fakepath\node_modules\grunt-protractor-runner\node_modules\protractor\lib\element.js:711:7)
      at World.<anonymous> (fakepath\Static\test\e2e\steps\test.steps.js:21:18)

Then I am allowed to proceed to the next step

Failing scenarios: fakepath\test\e2e\features\test.feature:3 # Scenario: Acknowledge warnings

1 scenario (1 failed) 3 steps (1 failed, 1 skipped, 1 passed) 0m02.814s [launcher] 0 instance(s) of WebDriver still running [launcher] chrome #1 failed 1 test(s) [launcher] overall: 1 failed spec(s) [launcher] Process exited with error code 1

Test failed but keep the grunt process alive.

Done, without errors.

It's crazy because if I visit the page manually, the element is there with the expected ID. When the test runs and the browser launches, I can see the element there on the page before the browser closes again!

If it would specify exactly which element it thinks is not visible it would help

danwellman
  • 9,068
  • 8
  • 60
  • 88
  • 1
    Could you post the complete traceback? Thanks. And a quick check: is maximizing the browser window helping: `browser.driver.manage().window().maximize();`? – alecxe Jan 22 '16 at 14:22

2 Answers2

2

I have found that if you do not wrap the callbacks in your steps, that things do not seem to stay in sequence. I would try re-writing your steps as below:

this.Given(/^I go to "([^"]*)"$/, function (path, callback) {
    browser.get(path).then(function(){callback();});
});

this.When(/^When I have checked the checkbox$/, function (callback) {
    var checkbox = element(by.id('check'));
    checkbox.click().then(function(){callback();});
});

this.Then(/^the button is enabled$/, function (callback) {
    var button = element(by.id('next'));
      chai.expect(button.isEnabled()).to.eventually.equal(true)
         .and.notify(callback);
});

This way the callback does not get executed until after protractor has done what it needs to do.

Coding Smackdown
  • 1,173
  • 8
  • 14
  • This should work. To be concise, you can also do something like `browser.get(path).then(callback);` – nilesh Jan 22 '16 at 17:30
  • Thanks, I'll try this first thing on Monday. I did try wrapping the second callback in a then, but not both. If it still doesn't work I'll post the full traceback. – danwellman Jan 22 '16 at 19:49
2

Usually the following things help to tackle "Element not visible" errors:

  • move to the element and then click:

    browser.actions().mouseMove(checkbox).click().perform();
    
  • scroll into view of the element and then click:

    browser.executeScript("arguments[0].scrollIntoView();", checkbox.getWebElement());
    checkbox.click();
    
  • click via JavaScript (see also WebDriver click() vs JavaScript click()):

    browser.executeScript("arguments[0].click();", checkbox.getWebElement());
    
Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • Thanks, I tried these and result is the same. I progressed slightly, using isDisplayed I see that this method is returning false, so somehow the element is not visible at this point. Could be related maybe to using ui-router I guess – danwellman Jan 25 '16 at 15:05
  • @danwellman might be an error in the logic of your test, you expect the element to be visible, but it is really not. Make a screenshot when the test fails and see if you can actually see the element. Also the last option I've posted should not result into the same "element not visible" error..thanks. – alecxe Jan 25 '16 at 15:18
  • I'm seeing 'obj.indexOf is not a function' using the third option. I will try the screenshot to see what's happening. The page is in a ui-view, and even in browser it takes some time to load. I've tried setting a huge timeout, I've tried using browser.wait() and/or browser.sleep(). I've tried nesting isDisplayed inside isPresent. Nothing I've tried has worked. I've got to the stage now where I've tried *so many* variations it's hard to remember what I have and have not tried :( – danwellman Jan 25 '16 at 15:26
  • @danwellman okay, yeah, I know how you feel :) Could you make the example reproducible, or this is a private site? Thanks. – alecxe Jan 25 '16 at 15:29
  • it's private unfortunately, totally internal at the moment. I've tried to make a cut-down version of the issue here, but I think the cut-down version is *too* cut down to be of much value – danwellman Jan 25 '16 at 15:34
  • Any idea how to take a screenshot? All the examples are using Jasmine – danwellman Jan 25 '16 at 15:45
  • @danwellman sorry, haven't done it with cucumber/protractor, is this related https://github.com/angular/protractor/issues/957? And this: http://stackoverflow.com/a/33739439/771848. – alecxe Jan 25 '16 at 15:52
  • Probably, but not really helpful, the first doesn't have enough context (what file should that be done in (I'm guessing the steps file, but still, if it doesn't work is it actually not working, or I added it to the wrong file), what is scenario (for me it's undefined)). With second link, I added that option to my conf file and it just gives errors saying the file doesn't exist! Surely the file should be created. It would be nice to take a screenshot, but it's telling me the element isn't there so I guess when it tries to click the checkbox, it isn't there yet. – danwellman Jan 25 '16 at 16:12