Is it possible to use any such filters?
I have a bunch of buttons with id starting with 'save' i.e 'save100', 'save193', 'save198' and then another set that starts with 'reset' i.e 'reset100', 'reset193', 'reset198' etc. The 3 digit postfix number is generated at runtime and could be anything.
I am using dom=document.getElementsByTagName('input')[1], dom=document.getElementsByTagName('input')[2],dom=document.getElementsByTagName('input')[3] to operate on them.
But i would much like to identify them on the basis of their partial ID combined with their instance. For example I would like an expression 'the element whose id starts with 'webButton' and is the 2nd instance of it's kind'. Is this possible with DOM. I am only interested in DOM or CSS locators as I have to run this IE. I know this could be done using XPATH easily but I can't use XPATH as it does not work in IE..
If I were using QTP to click the 'save100' button given it is the first save button on the page (order in html document) then i would use something like
Browser().Page().webButton("html id=save.*","index=0").click
Please note nth-child in CSS-selector does not mean instance.
Since when does xpath not work in IE?
Since forever bill. Filters like contains does not work in IE. They work perfectly well in firefox/chrome mind you. This is a major drawback and a deal-breaker when you are talking of enterprise level application test automation. All enterprise applications are tested in IE not in firefox.
Also note that Selenium supports XPATH 1.0 which does not support regex. XPATH 2.0 supports regexp and I hope selenium supports this xpath version in the next release.
I have written this JS function that could help people use dom identifiers using full power of regexp. I want to make this into a user-extension but for now will use it as it is.
/*Usage: Copy paste everything in blue after replacing elementClassName,attributeName,attribtePtrn,elemIndex given in green with the appropriate values in the function call. Add the 'dom=' prefix
elementClassName is the tag name like 'input', 'select' etc
attributeName is the name of the attribute within this node that you wish to use as a identifier i.e 'name', 'id' etc
attribtePtrn is the value of the attribute in regex i.e 'ctl00_middlecontent_radio.*' to refer to all elements that have the attribute value starting with 'ctl00_middlecontent_radio'
elemIndex is the instance of this element in the html page i.e 0,1,2 etc*/
function getLocator(elementClassName,attributeName,attribtePtrn,elemIndex){
var allInputArray = new Array();
var requiredElement;
allInputArray=document.getElementsByTagName(elementClassName);
var i=0;
var index=0;
var requiredIndex=elemIndex;
var pattrn=new RegExp("^"+attribtePtrn+"$");
for(i=0; i<allInputArray.length; i++){
if (pattrn.test(allInputArray[i].getAttribute(attributeName))){
if (index==requiredIndex){
requiredElement=allInputArray[i];
break;}
index=index+1;
}
}
return requiredElement;
}
//function call use only one function call; I have added 2 calls to getLocator just for example; replace the parameters with your own values
getLocator("input","id","webButton.*",16); //to refer to the 16th input element that has id starting with 'webButton'
getLocator("input","name","[a-c]{1}tl00_middleContent_Chec.*",2); //to refer to the 2nd input element that has name starting with any one character either a,b or c followed by 'tl00_middleContent_Chec' //followed by anything
//Don't forget the 'dom=' prefix
I've have developed a massive selenium framework for my company which runs primarily on IE (it is an enterprise app) but rus on firefox also and is exclusively in xpath, with some very complex expressions, and there isnt a single xpath v1 function which doesnt work in IE thats meant to, including 'contains' and 'starts-with'. Infact, about 80% of our expressions uses a 'contains', so I don't know where you have got this idea it doesn't work, because it does.
This is on both the ajaxslt and the javascript-xpath (v0.1.11) libraries which I ported to a few months back and needed very little changes to any expressions.
Any locator of the form 'xpath=...' does not work in IE. This is common knowledge. Many of the members of this forum have reached this conclusion numerous times.
Please refer to these threads to understand how we reached to this conclusion
http://clearspace.openqa.org/thread/16584
http://clearspace.openqa.org/thread/16715
Also compared to a DOM locator it takes 20 times more time to locate an element based on it's xpath. This fact too is well documented and common knowledge. But I will agree that the performance of xpath locators vary from application to application. I will be most gratefull to you if you could demostrate a working example of xpath locator (filters like contains and start-with) on IE. Also please explain how we can port our Selenium scripts to xpath 2.0 (this ver supports regexp).
hi Mahesh,
i think you too mush misunderstand with xpath. not all xpath with 'contains' or 'start-with' function doesn't work in IE, nor does xpath starts with "xpath=". IE just doesn't correctly parse some xpath expressions which are too complex or too special.
speaking of thread http://clearspace.openqa.org/thread/16584, i said "xpath=(//input[contains(@id,'ctl00_middleContent_CheckBox')])[2]" doesn't work in IE, that means in this xpath IE can't parse the index. it has nothing to do with "xpath=" prefix and "contains" function. actually, "xpath=//input[contains(@id,'ctl00_middleContent_CheckBox')]" can work without problem both in FF and IE.
is there a workround? of course. several day ago i ran into a page written by gyrm http://stressfreetesting.com/selenium-wiki/doku.php?id=locator_optimization. it talked about using "descendant axis" instead of "//" prefix. that gives me inspiration, i think this could solve your problem, and then i make an experiment. finally my assumption is proved, it works both in IE and FF. here is the script:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="http://video.google.com/" />
<title>discendant</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">discendant</td></tr>
</thead><tbody>
<tr>
<td>open</td>
<td>http://video.google.com/</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>xpath=/descendant::div[contains(@id, 'hs_v')][6]</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>
Indeed, It will solve the problem, I suggested using decendant instead of // here for the same IE index issue: http://clearspace.openqa.org/message/52588 Which worked fine for me on his example
To me at least the use of decendant is actually a much better way of writting the expression full stop.
I'm not sure if this is a ajaxslt quirk or not, so the original expression could well work on javascript-xpath anyway.
I want to point to the second checkbox on the page having 'ctl00_middleContent_CheckBox' in it's ID. Following xpath works perfectly well in FF and fails in IE.
Xpath=(//input[contains(@id,'ctl00_middleContent_CheckBox')])[2]
How do I make this work in IE?
And is there a solution to the performance degradation caused by xpath expressions when executing tests in IE?
Edit: I can see that from gyrm's post on the wiki that the following should work in IE.
Xpath=(/descendant::input[contains(@id,'ctl00_middleContent_CheckBox')])[2]
I will test this out first thing in the morning and report back here. Thankyou for your reply.
hi Mahesh,
if you use "descendant axes", the parentheses is needless:
Xpath=/descendant::input[contains(@id,'ctl00_middleContent_CheckBox')][2]
Thankyou Bill & Gim,
Your solution works perfectly well in IE.
