I got a website, which got the following snippet of code:
<div class="list_item_normal">
<div class="main_content">
<div class="img_wrap">
<img alt="Miniaturebillede af omslaget til Operating System Concepts" src="/images/product_thumb/9781/118/093/9781118093757.jpg?1354045210" title="Miniaturebillede af omslaget til Operating System Concepts" />
</div>
<div class="data_wrap">
<h4>
<!-- Added by sathiyaraj regarding E-book integration CR -->
Operating System Concepts <small style='background-color:yellow;'></small>
</h4>
<h5>
Abraham Silberschatz and Peter B. Galvin
(2013)
</h5>
<div class="imprint">
John Wiley & Sons, Limited
</div>
<div class="price">
610,00 kr.
</div>
</div>
</div>
I need to get what is encased within the h5 tag only. I've tried to do this the past 30 minutes without luck. My current piece of code looks like this:
content = driver.findElement(By.xpath("//div[contains(#class, 'content')]"));
List<WebElement> list
= content.findElements(
By.xpath("//div[contains(#class, 'list_item_normal')]"));
System.out.println(list.size()); // Just for debugging purposes
for (WebElement e : list) {
System.out.println(e.findElement(By.xpath("//h5")).getText());
}
driver.close();
}
It's a book store and the author is within the h5 tag. Now using the code above just produce a list of 10 identical authors even though many of them have different authors. I don't know where I am going wrong with this.
So how do I fetch data which is within that specific tag?
EDIT:
Here is the entire page HTML: http://pastebin.com/QALCvtaG
Well I think your mistake is trying to find elements within elements without implying so in xpath. Correct the line in your code to following, it should work.
System.out.println(e.findElement(By.xpath(".//h5")).getText());
You might also have to correct xpath in following line:
List<WebElement> list = content.findElements(By.xpath(".//div[#class= 'list_item_normal']"));
The only thing that I have changed is that I have added a dot before each of your xpath for finding elements within element.
Related
I have this html code below and I want to differentiate between these two PagePostsSectionPagelet as I only want to find web elements from the first PagePostsSectionPagelet. Is there any way I can do it without using <div id="PagePostsSectionPagelet-183102686112-0" as the value will not always be the same?
<div id="PagePostsSectionPagelet-183102686112-0" data-referrer="PagePostsSectionPagelet-183102686112-0">
<div class="_1k4h _5ay5">
<div class="_5sem">
</div>
</div>
<div id="PagePostsSectionPagelet-183102686112-1" class="" data-referrer="PagePostsSectionPagelet-183102686112-1" style="">
<div class="_1k4h _5ay5">
<div class="_5dro _5drq">
<div class="clearfix">
<span class="_5em9 lfloat _ohe _50f4 _50f7">Earlier in 2015</span>
<div id="u_jsonp_3_4e" class="_6a uiPopover rfloat _ohf">
</div>
</div>
<div id="u_jsonp_3_4j" class="_5sem">
<div id="u_jsonp_3_4g" class="_5t6j">
<div class="_1k4h _5ay5">
<div class="_5sem">
</div>
</div>
Tried using //div[#class='_1k4h _5ay5']//div[#class ='_5sem'] but it will return both.
Using //div[#class='_5dro _5drq']//span[contains(#class,'_5em9 lfloat _ohe _50f4 _50f7') and contains(text(), '')] will help me find the second PagePostsSectionPagelet instead.
you need to use the following xpath:
//div[contains(#class,'_1k4h') and contains(#class,'_5ay5')]
as selenium doesn't work properly with search of several classes in one attribute.
I mean By.Class("_1k4h _5ay5") will found nothing in any case and By.Xpath("//div[#class='_1k4h _5ay5']") can also found nothing in case of class will be "_5ay5 _1k4h" or " _5ay5 _1k4h".(as they possibly generated automatically, its may be have different position on page reload)
But for the best result by performance and by correctness I think will be the following xpath:
".//div[contains(#id, 'PagePostsSectionPagelet')][1]" -- for first div
".//div[contains(#id, 'PagePostsSectionPagelet')][2]" -- for second div
I see that dynamic in the div id is only the number so you can use something like:
WebElement element = driver.FindElements(By.XPath("//div[contains(.,'PagePostsSectionPagelet')])")[1];
This will take only the first web element.
Try using a css selector as below and refine further if required.
The code below returns a List of matching WebElements and then you grab the first one in the List.
List<WebElement> listOfElements = driver.findElements(By.cssSelector("div[data-referrer]"));
WebElement myElement = listOfElements.get(0);
Hint: use the Chrome console to test your css and xpath selectors directly. e.g. use
$$("div[data-referrer]") in the console to reveal what will get selected.
So I am writing automation tests using selenium and I am having a lot of trouble selecting the second element in a list of divs with the same class names
Boolean isExists2Accounts = driver.findElements(By.xpath("(//div[contains(#class, 'item-name')])[2]")).size() < 0;
if(isExists2Accounts)
{
//Finds second div element that has classname of item-name and clicks on it
driver.findElement(By.xpath("(//div[contains(#class, 'item-name')])[2]")).click();
}
else
{
driver.get("javascript:alert('There isn't a second account or you don't know how to select it!');");
Thread.sleep(5000);
org.testng.Assert.fail("transferTest6() Failed due to There isn't a second account or you don't know how to select it!");
}
HTML structure looks like this:
<div class="item-list">
<div class="item-name">
<div> clickable area </div>
<div class="button-wrap"></div>
</div>
<div class="item-name">
<div> clickable area </div>
<div class="button-wrap"></div>
</div>
<div class="item-name">
<div> clickable area</div>
<div class="button-wrap"></div>
</div>
<div class="item-name">
<div> clickable area </div>
<div class="button-wrap"></div>
</div>
</div>
Not really sure what I am doing wrong here, I looked at the html and there are 5 divs with the specified class name. Very new to selenium in general, using eclipse/junit/webdriver.
I have seen several questions similiar to this, and trying solutions people have posted have not worked. I have seen some suggestions to use .get(2) and I will try and implement that in the mean time.
Any help you could give would be good.
get(2) is THIRD element, not the second, as the countage begins from 0.
So:
driver.findElements(By.cssSelector(".item-name")).get(1).click();
OR depending on where is yr clickable
driver.findElements(By.cssSelector(".item-name div:not(.button-wrap)")).get(1).click();
Hey all the answer that was given by Stanjer works, I tested it with different markup, the developer that built the system I am testing through a random mousedown event (not click) for the html I am trying to interact with which was causing the problem.
So final solution with problem if it was a click event would be:
driver.findElements(By.cssSelector(".item-name")).get(1).click();
Just like he said.
However in this case I am instead going to send Javascript to the console to work with functions that have already been created by the developer.
I'm attempting to locate the following WebElement by class name:
<div class="aui-column-content aui-column-content-last lfr-asset-column-content lfr-asset-column-actions-content">
And since it has a space, I've attempted to use both css and xpath to find it like so ...
WebElement folderActions = driver.findElement(By.xpath("//div[#class='aui-column-content aui-column-content-last lfr-asset-column-content lfr-asset-column-actions-content ']"));
WebElement folderActions = driver.findElement(By.cssSelector("div[class='aui-column-content aui-column-content-last lfr-asset-column-content lfr-asset-column-actions-content ']"));
But both solutions are returning a NoSuchElementException. Any suggestions as to what I'm doing wrong?
Edit: Here is some adjacent html ...
<div id="aui_3_2_0_11858" class="portlet-body">
<div class="top-links-container">
<div id="aui_3_2_0_11857" class="aui-layout ">
<div id="aui_3_2_0_11856" class="aui-layout-content ">
<div class="taglib-header ">
<span class="header-back-to">
<h1 class="header-title">
</div>
<div class="aui-column aui-w75 lfr-asset-column lfr-asset-column-details aui-column-first ">
<div class="aui-column-content aui-column-content-first lfr-asset-column-content lfr-asset-column-details-content ">
</div>
<div id="aui_3_2_0_11855" class="aui-column aui-w25 lfr-asset-column lfr-asset-column-actions aui-column-last">
<div class="aui-column-content aui-column-content-last lfr-asset-column-content lfr-asset-column-actions-content">
</div>
</div>
</div>
Try using contains() function with xpath. And, as #Shoham A mentioned it does look like as multiple classes. Provide more html so we can help you with writing more perfect selector.
//div[contains(#class,'aui-column-content aui-column-content-last lfr-asset-column-content lfr-asset-column-actions-content')]
And, use explicit wait to make sure the element is present before started using that.
By byXpath = By.xpath("//div[contains(#class,'aui-column-content aui-column-content-last lfr-asset-column-content lfr-asset-column-actions-content')]");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(byXpath ));
Edit
//div[contains(#class,'aui-column-content-last')] should be enough to search for the target div. At least for the html provided by OP.
NOTE: Thinking the aui-column-content-last is unique on the page
The Xpath expression in your question would work if there was no whitespace character at the end of it:
//div[#class='aui-column-content aui-column-content-last lfr-asset-column-content lfr-asset-column-actions-content']
this will definitely find this div element. I'm not saying that this is the best method to locate it, but everybody seems to think path expressions somehow do not work with multiple classes.
EDIT
You have updated the question. Now, the div again looks slightly different and only
//div[contains(#class,'aui-column-content aui-column-content-last lfr-asset-column-content lfr-asset-column-actions-content')]
will find it. Any reason you cannot use the #id attribute of that div?
Have you met jQuery ? I do not have much experience with XPath, but it makes selecting elements easier, as:
$(".classname")
for CSS,
.aui-column-content.aui-column-content-last...
{
color: black;
}
should do it. Hope I helped!
Ok so I did my research for sure but couldn't find an answer to my problem. Using Selenium Webdriver and on the webpage there are a list of items below is a sample HTML
<div class="color-picker-slider" style="width: 180px;" active_state="black">
<div class="store_color_picker black-selector" style="width:20px;" color_name="black" product_id="132" base_color="black"></div>
<div class="store_color_picker slate-selector" style="width:20px;" color_name="slate" product_id="133" base_color="slate"></div>
<div class="store_color_picker violet-selector" style="width:20px;" color_name="violet" product_id="157" base_color="violet"></div>
<div class="store_color_picker flexlime-selector" style="width:20px;" color_name="lime" product_id="155" base_color="lime"></div>
<div class="store_color_picker pink-selector" style="width:20px;" color_name="pink" product_id="156" base_color="pink"></div>
<div class="store_color_picker teal-selector" style="width:20px;" color_name="teal" product_id="158" base_color="teal"></div>
<div class="store_color_picker tangerine-selector" style="width:20px;" color_name="tangerine" product_id="159" base_color="tangerine"></div>
<div class="store_color_picker navy-selector" style="width:20px;" color_name="navy" product_id="160" base_color="navy"></div>
<div class="store_color_picker red-selector" style="width:20px;" color_name="red" product_id="161" base_color="red"></div>
</div>
So I created an enum that contains all of the products with it's respective index location number. And that works great but the only problem is if the indexes change, let's say adding a new item not adding to the last index, then I have to go and change each and every index, therefore not very efficient. The only static attribute that I see is the product_id, which is unlikely to change. And if a new product_id is added I can just add it to the enum without having to change any indices and such.
My question then becomes how can I click on the element based on the product_id? I know how to get the attribute, but of course that returns a string but somehow I want to click on the item based on the product_id. Any help would be greatly appreciated! I use CSS for finding elements by the way. And this is not part of any dropdown list
You can write a CSS selector based on its attributes:
.store_color_picker[product_id='133']
Basically, the format is:
selector[attribute='attribute_value']
Thus, you could also do:
.store_color_picker[color_name='black']
if you wanted to select by the color name.
In Ruby Selenium (which is close to the Java version):
driver.find_element(:css, ".store_color_picker[product_id='133']")
Here's highly detailed documentation about css selectors, and you can find some more easily absorbed versions elsewhere as well.
I'm trying to use By.cssSelector to grab the nth dom element with class c3 with a structure like this:
<div class="c1">
<div class="c2">
<div class="c3">...</div>
</div>
</div>
<div class="c1">
<div class="c2">
<div class="c3">...</div>
</div>
</div>
<div class="c1">
<div class="c2">
<div class="c3">...</div>
</div>
</div>
Testing my CSS selectors, I'm becoming increasingly confused.
This selector selects the 2nd instance of c2/c3 correctly:
.c1:nth-of-type(2)
while:
.c2:nth-of-type(2)
.c3:nth-of-type(2)
select nothing.
Even worse, translating this into selenium, I seem to consistently find nothing for all 3 versions. There are plenty of alternative ways to select these elements (I'll probably just do XPATH), but my lack of understanding on nth-of-type is driving me crazy. Can anyone offer insight to why the second 2 don't work or correct my basic lack of comprehension on this selector?
This has been in Chrome (29/30) and Firefox (24/25)
I'm not enirely sure which one you want to select, but you should play around more with the :nth-* pseudo-classes. Here is a CSS selector that selects all 3 c3's using nth-child()
div.c1 div.c3:nth-child(1)
Like i said, you haven't really specified which one you want to select.
but my lack of understanding on nth-of-type is driving me crazy. Can anyone offer insight to why the second 2 don't work or correct my basic lack of comprehension on this selector?
One thing to keep in mind, is all of the :nth-*() pseudo-classes are dependent on their parents. Let me translate your selector:
.c1:nth-of-type(2)
Find anything with a class of c1 that is a second child.
In your case, <body> was most likely the parent, so...
<body>
<div .c1 />
<div .c1 /> // it highlights this one, because it's the 2nd child of the type ".c1"
<div .c1 />
</body>
Now let me explain why your other selectors are not working.
Both .c2:nth-of-type(2) and .c3:nth-of-type(2) are looking at the parent's as well. since you are specifying a parent, it's expecting <body> as the parent. In your case, <body> isn't the parent.. the <div .c1 /> is. In reality, that selector is looking for the DOM -
<body>
<div .c1 />
<div .c2 /> // this **would** be the second nth-of-type, but it's not really this way.
<div .c1 />
</body>
Play around with the different css selectors and pseudo-classes at http://cssdesk.com it's very helpful to actively experiment on your own. you'll figure it out.