3
\$\begingroup\$

I want to get a result from the website when I submit a form. There are several things that can go wrong.

In a simple scenario I want to return:

true - when form was submitted

false - when form wasn't submitted

null - when we don't know if form was submitted or not

I did that ugly try, because of NullReferenceException (if form is filled correctly, there would be no summary element, and if form is filled incorrectly, there would be no popup element).

How can I make this more elegant?

public bool? GetResult(TimeSpan timeout)
{
    var deadline = DateTime.Now.Add(timeout);

    do
    {
        // check if success
        try
        {
            var success = new WebDriverWait(Driver, TimeSpan.FromSeconds(5))
        .Until(ExpectedConditions.TextToBePresentInElement(Driver.FindElement(By.Id("summary")), "Success!"));
            if (success) return true;
        }
        catch (Exception ex)
        {  }

        // check if not enough data
        try
        {
            var notEnoughData = new WebDriverWait(Driver, TimeSpan.FromSeconds(5))
        .Until(ExpectedConditions.TextToBePresentInElement(Driver.FindElement(By.Id("popup")), "Not enough data"));
            if (notEnoughData) return false;
        }
        catch (Exception ex)
        { }

        // check if too much data
        try
        {
            var tooMuchData = new WebDriverWait(Driver, TimeSpan.FromSeconds(5))
        .Until(ExpectedConditions.TextToBePresentInElement(Driver.FindElement(By.Id("popup")), "Too much data"));
            if (tooMuchData) return false;
        }
        catch (Exception ex)
        { }

        // check if empty data
        try
        {
            var tooMuchData = new WebDriverWait(Driver, TimeSpan.FromSeconds(5))
        .Until(ExpectedConditions.TextToBePresentInElement(Driver.FindElement(By.Id("popup")), "Empty data"));
            if (tooMuchData) return false;
        }
        catch (Exception ex)
        { }


    } while (DateTime.Now > deadline);

    return null;
}
\$\endgroup\$
  • \$\begingroup\$ You should at least include code for WebDriverWait (so we can review async operations on it) and Driver (so we can try to avoid null reference exceptions). And use StopWatch for verifying elapsed time. \$\endgroup\$ – dfhwze Jun 5 at 16:07
  • \$\begingroup\$ That doesn't seem to be your working code. \$\endgroup\$ – Heslacher Jun 5 at 19:07
  • \$\begingroup\$ @dfhwze WebDriverWait is part of Selenium api: seleniumhq.org/docs/04_webdriver_advanced.jsp. \$\endgroup\$ – dafie Jun 6 at 6:28
  • \$\begingroup\$ @Heslacher it is. \$\endgroup\$ – dafie Jun 6 at 6:28
  • 1
    \$\begingroup\$ @dfhwze chack my answer about the NRE \$\endgroup\$ – Heslacher Jun 6 at 23:45
3
\$\begingroup\$

I did that ugly try, because of NullReferenceException (if form is filled correctly, there would be no summary element, and if form is filled incorrectly, there would be no popup element).

This problem can be easyly handled by a null check of the returned WebElement from the call to Driver.FindElement().

A little bit more problematic is IMO the looping condition because the condition only could evaluate to true if the passed TimeSpan is negativ. If this is what you want you really should place a comment there. If you didn't mean to pass a negative timespan then you should reverse the looping condition to DateTime.Now < deadline.

Extracting the repeated call to TimeSpan.FromSeconds(5) to a variable will make the code easier to read.

You know although copy & pasta will save time, you need to check if the pasted code is correct (empty data vs tooMuchData)

    // check if empty data
    try
    {
        var tooMuchData = new WebDriverWait(Driver, TimeSpan.FromSeconds(5))
    .Until(ExpectedConditions.TextToBePresentInElement(Driver.FindElement(By.Id("popup")), "Empty data"));
        if (tooMuchData) return false;  

Implementing the mentioned points will look like so

public bool? GetResult(TimeSpan timeout)
{
    var deadline = DateTime.Now.Add(timeout);
    var waitTimeout = TimeSpan.FromSeconds(5);

    do
    {
        WebElement summaryWebElement = Driver.FindElement(By.Id("summary"));
        if (summaryWebElement != null)
        {
            var success = new WebDriverWait(Driver, waitTimeout).Until(ExpectedConditions.TextToBePresentInElement(summaryWebElement , "Success!"));
            if (success) return true;
        }

        WebElement popupWebElement = Driver.FindElement(By.Id("popup"));
        if (popupWebelement != null)
        {
            var notEnoughData = new WebDriverWait(Driver, waitTimeout).Until(ExpectedConditions.TextToBePresentInElement(popupWebElement, "Not enough data"));
            if (notEnoughData) return false;

            var tooMuchData = new WebDriverWait(Driver, waitTimeout).Until(ExpectedConditions.TextToBePresentInElement(popupWebelement, "Too much data"));
            if (tooMuchData) return false;

            var emptyData = new WebDriverWait(Driver, waitTimeout).Until(ExpectedConditions.TextToBePresentInElement(popupWebElement, "Empty data"));
            if (emptyData) return false;
        }

    } while (DateTime.Now > deadline);

    return null;
}  

Because the checks for the popup text only differs from the expected text you could think about using a foreach loop over an array containing the expected strings.

\$\endgroup\$
  • \$\begingroup\$ the only thing I would change is to get rid of that DateTime for checking elapsed time. \$\endgroup\$ – dfhwze Jun 7 at 4:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.