0
votes

I'm newbie with Test Automation. When I locating element through Firepath with target:

 xpath=(//td[contains(@id, 'catProdTd_4723290')]/div/div[2]/h2)

Firefox founds that element and verify text. But, when I trying to locate this element with Visual Studio 2012 and Selenium Web driver, I constantly have error: "Unable to locate element: {"method":"xpath","selector":"//td[contains(@id, 'catProdTd_4723290')]/div/div[2]/h2"}" .

I tried escaping:

//td[@id=\"catProdTd_4723290\"]/div/div[2]/h2

but nothing. When I use isElementPresent method, it founds elements. Is there some special method or rule that should be use when writing Xpath for WebDriver ? I defined ISelenium variable, WebDriver... Clicks works, WaitForPageToLoad works, but this can not locate element.

IWebElement we= driver.FindElement(By.XPath("//td[contains(@id, 'catProdTd_4723290')]/div/div[2]/h2"));

HTML from page:

<td class="productItem" id="catProdTd_4723290"><div class="product-details">
    <div class="product-aside"> <img border="0" alt="Fork and Spoon Set" src="/_photos/store/glass-large.jpg" id="catlproduct_4723290">
     </div>
    <div class="product-main">
    <h2 class="product-name">Fork and Spoon Set</h2>
    <div class="price"><strong>$17.99</strong></div>
    <hr>

    <div class="attributes"></div>
    <hr>
    <div class="product-col-1">
    <div class="qty"> Quantity: <strong><input type="text" value="1" name="AddToCart_Amount" class="productTextInput" id="Units_4723290"></strong></div>
    <div class="stock">(N/A in-stock)</div>
    </div>
    <div class="product-col-2">
    <input type="submit" onclick="AddToCart(192951,4723290,'',4,'','',true);return false;" value="Buy Now" name="AddToCart_Submit" class="productSubmitInput">
    <div class="wish"><a href="/FavoriteProcess.aspx?OID=4723290&amp;OTYPE=27" class="favoritelink">Add to Wishlist</a></div>
    </div>
    <div class="product-description">
    <h4>Product Information:</h4>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit.  Aenean
    commodo ligula eget dolor.  Aenean massa.  Cum sociis natoque penatibus
     </div>
    </div>
    <!-- End Main -->
    </div>
    <!-- End Product Details -->
</td>

I must add that I try to wait during debug and with

Manage().Timeouts().ImplicitlyWait

but nothing. This happens on other places also. I using Firefox for tests

3
Does that element become visible if something happens on the page? Does it take time to appear? What browser are you running against? Any IFrames? Please post the section of HTML that you are running it against. - Arran

3 Answers

2
votes

You are running into dynamic attributes.

My first recommendation to you. Switch to CSS.

My second recommendation, instead of boiling down into an entire parent-child hierarchy, why don't you just KISS!

So, lets look at your issue. You are trying to fetch the product name. Easy.. we can use classes here.

css=td.productItem h2.product-name

voila, it was that easy to fetch.. instead of having this huge ugly xpath selector, we've simplified it to a css selector.

So onto the next problem, if we have multiple of td.productItem's on the page, we can use a couple things.

Try,

css=td.productItem:nth-child(1) h2.productName

That will select the first td with class, productItem.

note: you may need to specify the td's parent.. e.g. css=div#container td.productItem:nth-child(1)

More specifics...

The reason your xpath is failing, is because of that catProdTd_4723290 id assigned to the <td> element being generated automatically, rendering that element unselectable. You can work around that, by doing starts with. for example, with css -

css=td[id^='catProdTd']

will select that <td> take note though, that there might be more than 1 element selected.

0
votes

I suggest using such a method for waiting:

 public bool boolWaitForElementIsDisplayed(By locator, int secondsToWait)
    {

        WebDriverWait Wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(secondsToWait));

        try
        {
            var FoundElement = Wait.Until<Boolean>(d =>
            {
                try
                {
                    return (d.FindElement(locator).Displayed && d.FindElement(locator).Enabled);
                }
                catch
                {
                    return false;
                }
            });
        }
        catch (WebDriverTimeoutException)
        {
            return false;
        }
        return true;
    }

and then check as follows:

IWebElement h2Element = null;

string xpath = "//td[contains(@class,'productItem')]/div/div[contains(@class,'product-main')]/h2";
if (boolWaitForElementIsDisplayed(By.XPath(xpath), 30))
    h2Element = Driver.FindElement(xpath);
-1
votes

So, the problem was that page isn't loaded. Why? Because WebElement.Click() not works. Why Click not working?! I don't know. I resolved problem with clicks using JavascriptExecutor:

IJavaScriptExecutor executor = (IJavaScriptExecutor)chauffeur;
IWebElement webel1 = chauffeur.FindElement(By.CssSelector("#nav ul:nth-child(1) li:nth-child(2) a[href='/products']")); 

Instead of using

webel1.Click(); 

which not works, I used:

executor.ExecuteScript("arguments[0].click();", webel1);