How to find an element by using DOM structure in Selenium? - xpath

My application integrates with Google Maps and I'm trying to write some UI tests using Selenium. As a part of one of my tests, I need to find the X in the infoPopup provided by Google Maps. This element does not have any id or class that I can use directly to find it in Selenium. I can use the XPath but it would make my test very brittle to any changes from Google.
On the other hand, I can walk up the DOM structure from my custom elements (use parent and sibling) and find it very easily (this is how I am accessing it in javascript). My question is whether I can also access it the same way in Selenium.
HTML form:
<div style="width: 10px; height: 10px; overflow: hidden; position: absolute; opacity: 0.7; right: 12px; top: 12px; z-index: 10000; cursor: pointer;">
<img src="http://maps.gstatic.com/mapfiles/mv/imgs8.png" draggable="false" style="position: absolute; left: -18px; top: -44px; width: 68px; height: 67px; -webkit-user-select: none; border: 0px; padding: 0px; margin: 0px;">
</div>
XPath: //*[#id="map"]/div[1]/div[1]/div/div[3]/div[3]/div/div[13]/div[1]
I have very limited experience with Selenium. So if there are other ways of finding elements that might help me, would love to learn about them as well.

You may use By.XPath:
driver.FindElement(By.XPath("//*[#id='map']/div[1]/div[1]/div/div[3]/div[3]/div/div[13]/div[1]"));
However, XPath like this will be highly unstable and hard to maintain, I don't recommend to do so.
Use something like meaningful XPath or CssSelector would be nice.
By.XPath("//*[#id='map']//div[./img[contains(#src, 'mapfiles/mv/imgs8.png')]]");
By.CssSelector("#map img[src$='mapfiles/mv/imgs8.png']");
For more info about XPath or CssSelector, please refer to the documentation.

If you are just beginning I would suggest you use FireBug+FirePath add on to Firefox browser. To begin with it will give you the precise xpath of the elements you highlight on the UI.Click Here to see it

Related

Unable to click and capture the correct xpath of an image using Selenium Webdriver

I need to click on the that appears after clicking in box that opens after clicking on an expand icon. Using Webdriver I am able to expand the box but after that I am unable to click on the image icon which suposed to open a dialog box.
The xpath is showing for that image is as follows:
html/body/div[2]/div/div/div/div[3]/div/div[2]/div/div[2]/div/div[2]/div/div/div/div/div/div/div/div[14]/div/div/div/div[1]/div/div[1]/div/div[2]/div/div/div/img
The code is coming as:
<div id="isc_X1" style="POSITION:relative;VISIBILITY:inherit;Z-INDEX:205382;CURSOR:default;" eventproxy="page$mainWindow$interactionsUI$$content$InteractionDetail$VerticalLayout1">
<div id="isc_X2" class="normal" onscroll="return page$mainWindow$interactionsUI$$content$InteractionDetail$customerInteractionSearchGrid.$lh()" style="position: absolute; left: 0px; top: 0px; width: 717px; height: 64px; z-index: 205400; margin: 0px; -moz-box-sizing: border-box; overflow: hidden;" eventproxy="page$mainWindow$interactionsUI$$content$InteractionDetail$customerInteractionSearchGrid">
<div id="isc_Y8" class="normal" onscroll="return page$mainWindow$interactionsUI$$content$InteractionDetail$MenuLayout.$lh()" style="position: absolute; left: 0px; top: 64px; width: 800px; height: 18px; z-index: 205454; padding: 0px; -moz-box-sizing: border-box; overflow: hidden; cursor: default;" eventproxy="page$mainWindow$interactionsUI$$content$InteractionDetail$MenuLayout">
<div id="isc_Y9" style="POSITION:relative;VISIBILITY:inherit;Z-INDEX:205454;CURSOR:default;" eventproxy="page$mainWindow$interactionsUI$$content$InteractionDetail$MenuLayout">
<div id="isc_YB" class="imgButton" onscroll="return page$mainWindow$interactionsUI$$content$InteractionDetail$ImageAdd.$lh()" style="position: absolute; left: 782px; top: 0px; width: 18px; height: 18px; z-index: 205472; -moz-box-sizing: border-box; overflow: hidden; cursor: pointer;" tabindex="7583" onblur="if(window.isc)isc.EH.blurFocusCanvas(page$mainWindow$interactionsUI$$content$InteractionDetail$ImageAdd,true);" onfocus="if(event.target!=this)return;isc.EH.focusInCanvas(page$mainWindow$interactionsUI$$content$InteractionDetail$ImageAdd,true);" role="button" eventproxy="page$mainWindow$interactionsUI$$content$InteractionDetail$ImageAdd">
<div id="isc_YA" style="POSITION:relative;VISIBILITY:inherit;Z-INDEX:205472;CURSOR:pointer;" eventproxy="page$mainWindow$interactionsUI$$content$InteractionDetail$ImageAdd">
<img border="0" align="TEXTTOP" height="18" width="18" suppress="TRUE" name="isc_YApage$mainWindow$interactionsUI$$content$InteractionDetail$ImageAdd" src="http://kolcaresuse01:12345/cwf/r/orga_pics/add_icon.gif?v=1371640285409en-xx"/>
Please help to solve this.
Use shorter locators if possible, //tag[#attribute_name='attribute_value'] for example
You need to use explicit and implicit waits. They're discribed here
If I understand your code right, the <img> is in <div id="isc_YA" style="POSITION:relative;VISIBILITY:inherit;Z-INDEX:205472;CURSOR:pointer;" eventproxy="page$mainWindow$interactionsUI$$content$InteractionDetail$ImageAdd"> tag. So here's the python example:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
## Here you're expanding the box, then:
WebDriverWait(driver, 5).until(lambda driver : driver.find_element_by_xpath("//div[contains (#id, 'constant_part_of_id')]/img").is_displayed(), "No icon displayed")
## 5 is for 5 seconds to wait
## driver is for instance of webdriver
## check the locator, it might be wrong
driver.find_element_by_xpath("//div[contains (#id, 'constant_part_of_id')]/img").click()
## Or whatever you're going to do with that
I would use FluentWait instead of WebDriverWait because it sounds like you may be getting a exception that you need to handle/ignore until the element is ready to be acted upon. Also, #AlexanderPetrovich is correct and you should use a shortened locator or perhaps a css locator instead. Also, I would use the Firefox plugin "FirePath" to verify your locator syntax.

How to use the new image replacement technique by Scott Kellum

I am practicing using various image replacement methods and recently came across a couple articles discussing a new, supposedly more efficient method by Scott Kellum.
Original website article regarding this new method
It seems good and I would like to practice using it, but am not to sure what the html and css for it should be. So in the example below, I have an h1, with the example logo text inside. Then I added a class of .hide-text to my h1 and styled it with CSS. I used a photoshop logo image I made and set that as the background image....the image has a width of 203px and a height of 57px.
Question 1:
When I tested my code in the browser, everything seems to be working fine, however is my usage of Mr.Kellum's image replacement technique correct?
Question 2:
Should I target the h1 in the css and declare the width and height or is it okay to include the width and height directly in the hide-text class like in my example below?
<style>
.hide-text {
background: url(images/mylogo.jpg) 0 0 no-repeat;
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
width: 203;
height: 57px;
}
<body>
<h1 class="hide-text">MyLogo text</h1>
</body>
Any help is greatly appreciated. Thank you community!
I have found the css image replacement museum while searching for the actual trends on image replacement. I met the Scott Kellum method's there. After that I found this question - so I'm not an expert using this technique - and i want to share my opinion about.
Implementation copy-pasted from the link above
Simple, as also posted on the question.
<h3 class="skm">CSS-Tricks</h3>
CSS
h3.skm {
width: 300px;
height: 75px;
background: url(test.png);
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
}
Implementation as I would do it
I've read the original article and i think it's better to split the css code for reusability. Maybe we'll replace with images more than a single element.
<h1 class="ir">An awesome pretty title</h1>
<h2>Some words here not replaced with images<h2>
<nav>
<!-- some links replaced with images that also use css sprites -->
<a class="ir" href="#">home</a>
<a class="ir" href="#">sweet</a>
<a class="ir" href="#">home</a>
</nav>
Reusing the ir class for the image replacement technique, as suggested on the post you linked on the question, keeps things tidy.
.ir {
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
}
h1 {
background-image: url('/the-title-replacement.png'');
width: /*the-image-width*/px;
height: /*the-image-height*/px;
}
nav a {
background-image: url('/the-menu-icons-sprite.png');
width: 24px;
height: 24px;
}
nav a { background-position: 0 0; }
nav a + a { background-position: 0 24px; }
nav a + a + a { background-position: 0 48px; }
Conclusions
The image url & the size must be set for each replaced element. If we are using sprites the background position also comes in play for each element, though the element size is often shared between all the elements.
All of this use cases can benefit from splitting the css code, keeping the stylesheet tidier.
NOTE: I've made these thoughts for a pure css implementation. Using a css preprocessor - such as less for example - changes the rules.
NOTE 2: Another trending method is the proposed by the H5BP team. I am undecided about which to use.

DIV's not recognized in FF + Opera, Works in IE + Chrome

I've tried and tried so hard to overcome this problem the past few days as I just want to get this site launched above all now. I have been developing this for the last week or so and I have been using my specific preferred browser, Google Chrome. Yes, big mistake!
Anyway, here is the demo site which shows what I want near everything to look like (apologies for some things that are out of place, haven't quite finished yet!): http://www.weburton.co.uk/content/demo/
You see the social area? It displays properly in Chrome; exactly as I want it. In IE it displays the div areas, but there are some styling issues such as the text on the Twitter side.
However, the div areas are completely ignored in other browsers it seems; its a strange problem, I'll admit that. I have them encased in a div which has a background image (selenasocial) and then have the other divs floating. Here is the code (CSS):
#selenasocial {
background: url(images/wls/social-bg.jpg) no-repeat top center;
display: inherit;
width: 100%;
min-height: 263px;
z-index: 555;
border: none;
overflow:auto;}
.selenasocial {
background: url(images/wls/social-bg.jpg) no-repeat top center;
display: inherit;
width: 100%;
min-height: 263px;
z-index: 255;
border: none;
overflow:auto;}
.selenasocial img {
border: none;}
.twitsocial {
float: left;
width: 480px;
padding-top: 10px;
text-align: center;
border: none;}
.facesocial {
float: left;
width: 480px;
padding-top: 10px;
text-align: center;
border: none;}
And here is the HTML, I am using Widgets (and yes, they have been styled correctly in functions.php):
<!-- Selena Gomez Social Networks -->
<div class="selenasocial">
<?php if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar("Social Sidebar") ) : ?> <?php endif;?>
<?php if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar("Social Sidebar 2") ) : ?> <?php endif;?>
</div>
I overcame the error in IE (as it was happening there, too) by copying the CSS above into a separate IE.css file. I just don't understand why two browsers which are leaps and bounds ahead of IE aren't reading from the main CSS file.
Any help would be HUGELY appreciated - I've been tearing my hair out about this for the past few days.
Thanks in advance!
There's (technically) nothing wrong with your code - the part you posted. You are setting both float properties to left, which I guess is not what you want, but that did not explain why the other properties were getting ignored.
I won't read your 4700-lines CSS file to find what is wrong with it but I will try to help you do it yourself.
The first thing I did was to try to hunt the CSS code you posted with firebug and, to my surprise, it was not there. The very last line of CSS firefug gave me was the 902th which was this:
.clearfix {
zoom: 1;
}
Actually, firebug did not show that zoom thing (the brackets were empty). So I went to the CSS file directly to find it out and, after wondering why would anyone use such non-standardized property, I checked the next lines to find there was a parentheses instead of a bracket in the 907th line.
After finding such error I proceeded to run a CSS validator on your CSS file and results were not very good. Fix those errors and Firefox will draw that properly.
Deciding whether IE and Chrome's capability of interpreting wrong CSS files is actually good or bad is not to be discussed here but learning how to find and correct your mistakes can help you get things to work with stricter browsers.

IE css how to?

Im struggling with this for the past 3 months!! - how to adapt css3 to IE7,8 and 9??
this is my page
I am using buttons there, I want to make rounded corners (basic, no?)
so I have used this css
body .main_title {
font-size: 16px;
padding: 0.3em 1.5em;
display: inline-block;
cursor: pointer;
line-height: 1.5;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-ms-border-radius: 10px;
-o-border-radius: 10px;
border-radius: 10px;
background-color: #222222;
color: white;
behavior: url(PIE.htc);
}
and the button is
<button type="submit" id="1" class="main_title">מאפיינים</button>
as you noticed, I also used an "extention" called css3pie to make it work but nothing!!
any suggestion?
any suggestion?
Sit back. Relax. Don't worry about minor cosmetic details in old browsers with falling marketshare.
CSS3 pie is kind of buggy. Try putting a position:relative; on it. Also make sure that's the correct path to PIE.htc — if I remember correctly, it may help to link to it absolutely.
I think you can probably use jquery for this http://jquery.malsup.com/corner/ in your javascript.
Anything from IE9 onwards will be ok with this in the css
border-radius:10px
http://caniuse.com/#search=border-radius

Resize Google Map + API v3

I am using Google Maps API v3.
In Chrome, the map fits fine into the div element I set with width 200px and height 200px.
In Firefox, it tries to take up the whole screen. I noticed the styling code that google maps uses there is this line:
<div style="position: absolute; left: 0px; top: 0px; overflow: hidden; width: 100%; height: 100%; z-index: 0;">
I've been trying to modify this via the API to set the width to 190 and hieght to 190.
Does anyone know how to do this?
The CSS styling I used for the div was:
div.map {
height: 190px;
width: 190px;
}
I added this into my API call already thinking it would resize based on the div styling:
google.maps.event.trigger(map, 'resize')
Happy Holidays!!
you have to hard code your width/height in an inline style. I ran into the same problem. The reason is it uses the width/height to create the other elements within the map.. try setting your code as follows:
<div style="position: absolute; left: 0px; top: 0px; overflow: hidden; width: 190px; height: 190px; z-index: 0;">

Resources