Ak02
Ak02

Reputation: 161

Inconsistent error : element is not attached to the page document

I know this is a duplicate question but I am not getting solution for it hence asking it again.

I am using selenium C# and getting the above error for couple test at same action on same page. My tests are working fine on my local machine but same tests are inconsistent when I execute on server via TFS.

I made changes in my test as it was reloading the DOM after click action and now I am checking the object after reload its working fine on my local machine but is inconsistent on server. I need to uncheck check boxes if they are checked. I was getting the group of checkboxes(CB) using ".//*[@type='checkbox']" on the table which on contains this CB.

But this was producing the same error so I changed my approach and later was geet the individual checkbox from the text which adjacent to checkbox but this way is inconsistent and is working on my local machine but not on the server.

Not sure way this is happening. and I need to do this action in multiple test so I wrote a common function to uncheck CB

Following is HTML for checkBoxes to be clicked

    <tr>	<td>
            <input id="ContentPlaceHolder1_cblModules_0" type="checkbox" name="ctl00$ContentPlaceHolder1$cblModules$0" checked="checked" onclick="javascript:setTimeout('__doPostBack(\'ctl00$ContentPlaceHolder1$cblModules$0\',\'\')', 0)" value="0"><label for="ContentPlaceHolder1_cblModules_0">Collector</label>
            </td>
    </tr>
    <tr>	<td>
            <input id="ContentPlaceHolder1_cblModules_1" type="checkbox" name="ctl00$ContentPlaceHolder1$cblModules$1" onclick="javascript:setTimeout('__doPostBack(\'ctl00$ContentPlaceHolder1$cblModules$1\',\'\')', 0)" value="1">
            <label for="ContentPlaceHolder1_cblModules_1">Maintenance</label>
            </td>
    </tr>
    <tr>	<td>
            <input id="ContentPlaceHolder1_cblModules_2" type="checkbox" name="ctl00$ContentPlaceHolder1$cblModules$2" onclick="javascript:setTimeout('__doPostBack(\'ctl00$ContentPlaceHolder1$cblModules$2\',\'\')', 0)" value="2">
            <label for="ContentPlaceHolder1_cblModules_2">Manager</label>
            </td>
</tr>

my first approach i Tried

string checkboxList = ".//*[@id='ContentPlaceHolder1_cblModules' and @class = 'checkBoxList']";
IWebElement e1 = SeeElement.GetElement(driver,checkboxList);// internal function to get element
string CBchecked =".//*[@type='checkbox']";
IReadOnlyCollection<IWebElement> ele1 = e1.FindElements(By.XPath(CBchecked));
foreach (IWebElement e in ele1)
                {
                    string isChecked = e.GetAttribute("checked");
                    if (isChecked != null)
                    {
                        e.Click();                            
                    }
                }

here I was getting the same error so I change the approach to

 List<string> checkedItems = new List<string>();
 string checkboxList = ".//*[@id='ContentPlaceHolder1_cblModules' and @class = 'checkBoxList']";
 string CBchecked = checkboxList+"//input[@type='checkbox']/following-sibling::label";
IReadOnlyCollection<IWebElement> ele1 = driver.FindElements(By.XPath(CBchecked));
        foreach (IWebElement e in ele1){ checkedItems.Add(e.Text); }
        foreach (string s in checkedItems)
        {
            string xPath;
            xPath = "//*[text()='" + s + "']/preceding-sibling::input[@type='checkbox']";
            IWebElement e;
            e = driver.FindElement(By.XPath(xPath));
            string isChecked = e.GetAttribute("checked");
            if (isChecked != null)
            {
                e.Click();
            }
        }

this is working fine on my local machine but not working on server. and in some random run it is executing in one test while failing in other test.

Not sure why this is happening.

thanks, amey

Upvotes: 0

Views: 390

Answers (1)

lauda
lauda

Reputation: 4173

This is very known mistake in automation testing, stale element exception, you should not use a list/array/collection of objects in a loop that can change the page.

When the page changes all your current objects are not bound to the object page since is not the same object.

You need to find the element each time before clicking it.

You should use a do-while with an if, should look like (I haven't worked with c# so you might have to do some changes)

do
   string checked = driver.FindElement(By.XPath(xPath_for_checked));

   if (checked != null)
       {
            checked .Click();
       }

while (checked != null)

and the selector should be:

xpath: //input[contains(@id, 'ContentPlaceHolder')][@checked]

css: input[id*=ContentPlaceHolder][checked]

Upvotes: 2

Related Questions