1

Working with Protractor by Bruno Baia v0.9.2 Selenium Webdriver v3.0.1 Selenium.Webdriver.ChromeDriver v2.27.0 I'm facing the following problem. I'm logging in from a non Angular page. When I'm on the first Angular page of my application I want to click on the first row of a NgRepeater on the page as follows:

class CarCompanies
{
    NgWebDriver driver;

    [FindsBy(How = How.XPath, Using = "Bedrij")]
    private IWebElement linkBedrijven;

    public bool ContainsText(string text, string heading)
    {
        return SelecteerElement.pageContainsHeadingElementWithText(driver, text, heading);
    }

    public void ClickFirstCar()
    {
        driver.FindElements(NgBy.Repeater("dmsInstance in dmsInstanceList"))[0].Click();   
    }

    public CarCompanies(NgWebDriver driver)
    {
        this.driver = driver;
        PageFactory.InitElements(driver, this);
    }

}

This works fine when the preceding statement is a Thread.Sleep() but without this unwanted Sleep an IndexOutOfRangeException appears. The driver tells meIgnoreSynchronisation = false isAngular2 = false.

What am I doing wrong?

Frank
  • 831
  • 1
  • 11
  • 23

1 Answers1

-1

I'm guessing the element is not there yet when you call FindElements without the sleep. You should wait for the element to be there before looking for it.

Most probably using

driver.WaitForAngular();

will solve the issue (the methods waits for angular to finish loading).

If not, you can set an implicit wait or write an extension to wait while finding the element.

By the way, there is no need in your case to use FindElements(By)[0], method FindElement will return the first element in the DOM.

Ory Zaidenvorm
  • 896
  • 1
  • 6
  • 20
  • 1
    The only reason I'm using Protractor is that I don't have to write my own waiting mechanism because Protractor is doing this for me in Angular pages. That is the main point of my question. – Frank Feb 07 '17 at 05:36
  • @Frank, I hear you, but you misunderstand. Protractor/WebDriver will still handle the wait for you (there are many things happening under the hood when you instruct it to wait). But you should still tell it to wait. There has been much written on the subject, Google is your friend. Here's some links: [SauceLabs Best Practice](https://wiki.saucelabs.com/display/DOCS/Best+Practice%3A+Use+Explicit+Waits) , [WatirMelon](https://watirmelon.blog/2014/01/29/waiting-in-c-webdriver/) , [ToolsQA](http://toolsqa.com/selenium-webdriver/c-sharp/advance-explicit-webdriver-waits-in-c/) – Ory Zaidenvorm Feb 08 '17 at 08:04
  • 1
    Specifically to Angular & Protractor, that is what `WaitForAngular` is for. – Ory Zaidenvorm Feb 08 '17 at 08:05
  • The links are about general waiting mechanisms in Selenium, I'm familiar with this mechanisms and using ExplicitWait extensively. Are you sure about using WaitForAngular? In the documentation of Protractor about this command is said "Instruct webdriver to wait until Angular has finished rendering and has no outstanding $http or $timeout calls before continuing. Note that Protractor automatically applies this command before every WebDriver action". So what could be the benefits of using this command yourself. – Frank Feb 08 '17 at 12:52
  • By the way, driver.WaitForAngular doesn't solve my problem where a Thread.Sleep(2000) does. – Frank Feb 10 '17 at 12:57
  • WaitForAngular is already called by NgWebDriver.FindElements here : ``driver.FindElements(NgBy.Repeater("dmsInstance in dmsInstanceList"))[0].Click();`` – bbaia Feb 12 '17 at 17:54
  • As stated in the documentation I cited above. – Frank Feb 12 '17 at 21:13
  • Interesting, I did not know that "Protractor automatically applies this command before every WebDriver action". In our solution we have had to call it explicitly many times (but we also have a mixed use of NgWebDriver and normal WebDriver). I guess without a publicly available example we won't know if this is an issue with Protractor implementation or with your approach. – Ory Zaidenvorm Feb 14 '17 at 06:44