I have an element to find:
//div[contains(#class, 'bPageBlock')][.//*[.='Agreement Documents']]//div[#class='pbBody']//tr[contains(#class,'dataRow')]//a[text()='View']
The problem is, this finds two elements and I want only one. One is under an iframe and one isn't. It would be easy if I wanted the one under the iframe. I could do
//iframe///div[contains(#class, 'bPageBlock')][.//*[.='Agreement Documents']]//div[#class='pbBody']//tr[contains(#class,'dataRow')]//a[text()='View']
However, as you probably guessed, I want the one that is NOT under the iframe. I don't know how to specify something like //not iframe//. And even if I could, the // would find something one step lower or higher that was not an iframe.
Any suggestions how to find the one NOT under the iframe. The roots and paths other than that all seem to be the same with each other. I have tried lots of different things.
If you want to see the specific iframe:
<iframe frameborder="0" id="RLPanelFrame" name="RLPanelFrame" src="/emptyHtmlDoc.html" title="Hidden Frame - Ignore" style="height: 176px;"></iframe>
Then there are many sub-units under it with auto-generated meaningless IDs.
I don't think I can find each one using driver.find() and get the full xpath and check for "iframe" because selenium does not have an xpath extractor. I guess for each one I could keep getting the parent until I got to //html or //iframe but that would take a long time.
Any suggestions? This with Java and Selenium
Related
I am working on a testing program that operates with very little information. In this particular case, my program doesn't know the ID of elements in the page before it runs, because the Javascript on the page dynamically assigns those at run time. The only constants I have is the structure and the text I'm looking for. I'm including a screenshot of one example of the DOM being generated. In this case I know that I want to access the button with text apply that is displayed next to the label with the text "To Location:" Is there a way to use xpath manipulate their relationship and ensure that I'm accessing the right element. I can't just access the apply button because there are 6 apply buttons on the page with dynamically generated IDs. The label's next to them are different so I'm trying to use that and manipulate the path's from there. Help?
This is possible. If you provide the entire html code I could provide a better xpath. But for what you pasted, here's a simple one that might work:
//td[div//label[text()='To Location:']]/following-sibling::td[1]//button[text()='Apply']
There's a slightly longer winded way but thats generating a list of elements by class and clicking the one with the right text
`var elements = driver.FindElements(By.Class("text-pb"));
foreach(var element in elements)
{
if(element.Text.Equals("Searched Text"))
{
element.click();
}
}`
that might work thats if you want to click the button.
i use these sort of things on the pages works site generates so it should do what your after.
I have a few nav bar items that I am trying to find with driver.findElement(by.id("menu-news-menu-item")) and driver.findElements(by.id("menu-news-menu-item")). It can't find them for some reason. I have verified that the id is correct on the site but it still can't be found. I know there are other ways to get to the info, but it is my understanding that using the id is the best way to go about finding elements. Below I have included an HTML snippet of what I am trying to search for. If I need to provide any more information please let me know.
<div class="navbar-collapse collapse">
<li>
<a id="menu-news-menu-item" href="/novus/news">News</a>
</li>
</div>
From looking at your HTML I see one potential problem. There may be more.
The top level DIV you posted has a class navbar-collapse collapse. That indicates to me that that DIV is collapsible and is currently collapsed which means that any of its children will be hidden. Selenium was designed to allow the user to only interact with visible elements. This means that if you search for your A tag by ID and it's a child of the DIV that is currently collapsed, Selenium won't find it. What you need to do before you search for the A tag is to unhide it. I don't know for sure how to do this but it probably involves clicking the collapsible DIV.
With this info, try to figure the rest out on your own. You should be able to investigate the page HTML, try some code, and see what happens. If it doesn't work and you get stuck. Come back and post some more of the surrounding HTML, the code you tried, and the result (error messages, etc.) and we'll try to help you more.
I've been asked this question on a interview. What is the best way to find particular button on a page, from two identical buttons?
Two buttons like this on a page, i need to find the second.
button class="button-signin" name="btnlogin_login" value="Login" type="submit"> Sign In /button>
I've answered that I'd locate both and choose what I need from the list - they said that it's no good, because page can be changed. Can you suggest me the good way to do this?
If they said to find always the second element I would go for a solution like this:
List<WebElement> buttons = driver.findElements(By.class("button-signin"));
if(buttons.size() > 1){
buttons.get(1);
}
But what dont make sense for me is what they told you, than the page can change...Technically if the page change you should modify yours tests to make them easier to find elements save time and make them more readable, you cant do a test forever as a page is not forever.
Basically, the buttons must be child elements of some HTML elements.
Case 1: Parent are different, you can refer to each button by specify different parent e.g. cssSelector("#component1 > button") and cssSelector("#component2 > button").
Case 2: They have the same parent or path are identical, there are a couple options.
Use index such as XPath //button[2] or CssSelector button:nth-child(2)
Change the application, add something to differentiate the buttons
For case 2, I do think there is no point to have the 2 buttons which have the exactly same properties in the application. Personally, I prefer the option#2
I have two buttons on a page that have really similar xpaths -
the button im trying to click -
/html/body/div[#id='wrapper']/div[#id='content']/div[#id='contentarea']/div[#id='votecontent']/div[#id='votetext']/div[#id='voteboxes']/div[#id='votenow'][2]/form/input[2]
and the other button im trying to ignore -
/html/body/div[#id='wrapper']/div[#id='content']/div[#id='contentarea']/div[#id='votecontent']/div[#id='votetext']/div[#id='voteboxes']/div[#id='votenow'][1]/form/input[2]
the only difference between the two is the
[#id='votenow'][1]
and
[#id='votenow'][2]
but I can't figure out how to interact with the one that has the votenow[2], whichever way I go about it, it always seems to interact with the first one because that's the first one it finds
this is for java using the firefox driver, any suggestions would be great :)
Just find them both and get the desired one by index:
List<WebElement> buttons = driver.findElements(By.xpath("your xpath"));
WebElement secondButton = buttons.get(1);
First
Please talk to your developers! It is really bad practice to assign the same id to two different elements (in your case buttons) on the same page! It makes life for DEV and QA unnecessarily harder than it need be!
Second
The xpath-expressions you posted already contain the differentiation between these two buttons. So you just need to find the first one and click it.
via xpath:
You can use xpath - should be enough to search for the elements with id="votenow". As said before, you can be pretty precise in this case and already filter for the 2nd button:
WebElement button02 = driver.findElement(By.xpath("//div[#id='votenow'][2]/form/input[2]"));
button02.click();
via id:
As #alecxe already pointed out, you can also first go for a more general search of several elements and then filter the right one out. Personally I would use the id in this case:
List<WebElement> buttonWrappers = driver.findElements(By.id("votenow"));
// you want the button-input-element in the 2nd wrapper element, indexing starts at 0, so do this:
WebElement button02 = buttonWrappers.get(1).findElement(By.xpath("//input[2]"));
// since it seems there are several input elements below the desired div, you can use xpath again
i am trying to navigate through pages using selenium web driver and i am stuck at one point
please refer to the image where i have shown the output of inspect element for that page that i am working on.
but in the page source (which i saw on the browser and also using Jsoup) looks like this,
<html>
<head>
</head>
<frameset rows="75,60,*" resize="no" SCROLLING="NO" name=main border="0">
<frame src="/frame/topnewprof.shtml" name="top" SCROLLING=NO>
<frame src="/frame/blank.html" name="menu" SCROLLING=NO >
<frame src="/itrade/user/welcome.exe?action=chk_seckey_stat" name="body" SCROLLING=AUTO>
</frameset>
<body>
</BODY></html>
why is this mismatch? and the yellow stuff that i have highlight in the image above has the element that i need!!
how will i get there using selenium??
i know that we can navigate into the iframe using selenium's switchTo().frame() but even if i get into any of the three frames as shown above in the page source information, i'm not able to find the information i need,
can this be achieved ? is it even possible?
UPDATE:
hello guys! i found the solution to this and now that huddle is crossed.
actually what happened was , when i was trying to do getPageSource, selenium was actually getting the frame source of one of the frames ("body" - as mentioned above), i accidentally figured that out.
Next to solve my problem i wanted to come one step back from where i was so i can select this iframe = (name="top") which was the target where i had the content as shown in the image. to Achieve this i used Selenium's defaultContent() function and came back one step then with switchTO().frame() went into the frame of my desire and accomplished the task
hope this helps!!
and thanks for everyone who tried to help me on this.
I couldn't exactly tell you why this mismatch is caused but I have an idea of how you could solve this problem.
I had similar problems with javascript phrases on pages. Normally such elements have to be clicked to get into. But if this element isn't clickable or a click doesn't sole the problem you could also search the information you need by using unique Xpath's.
I'm not sure if you using Selenium IDE already but maybe you could record navigating to this element and use the thrown java code from the Selenium IDE to get the required Information.
... I only have seen this problem while using Selenium remote control not the Selenium WebDriver...
I think the problem could also be solved by using xpaths. The easiest way to get the correct xpath is using firebug with firefox. Right click on the element in developer tools and click copy xpath. Firebug's incredibly accurate when producing xpaths. It has solved many problems like that one for me.
*Even if you aren't using firefox, most of the time you can use the same xpath from firebug in chrome webdriver testing.
It's a life saver.
Warning though, sometimes the path is long like:
final static String planTitlePath = "/html/body/div[1]/div[2]/div[1]/div[2]/div[5]/div/div/div/div/section/div/div[2]/div/ol/li/div[1]/plan-card/h4/span";
i found the solution to this and now that huddle is crossed. actually what happened was , when i was trying to do getPageSource, selenium was actually getting the frame source of one of the frames ("body" - as mentioned above), i accidentally figured that out. Next to solve my problem i wanted to come one step back from where i was so i can select this iframe = (name="top") which was the target where i had the content as shown in the image. to Achieve this i used Selenium's defaultContent() function and came back one step then with switchTO().frame() went into the frame of my desire and accomplished the task
hope this helps!! and thanks for everyone who tried to help me on this.