I've been trying to select this WebElement for a while. It's a sign up button on the front page of the web application I test. I was wondering, is there a method I could use to grab text within the HTML to define a WebElement?
<div>
<div>
<div style="">
<div style="transform: translate(0px, 0px) scale(0.5, 0.5) rotate(0deg);">
<div role="img">
<img src="images/lsloginform/newskin/try_it_normal.png?1444658058414">
</div>
</div>
<div style="transform: translate(0px, 75px) scale(1, 1) rotate(0deg);">
<canvas height="7" width="75" style="top: 0px; left: 0px; width: 75px; height: 7px;"></canvas>
</div>
<div style="transform: translate(0px, 82px) scale(1, 1) rotate(0deg);">
<div style="font-family: franklin-gothic-ext-comp-urw; font-weight: 700; font-style: normal; font-size: 15px; opacity: 1; color: rgb(63, 63, 63); transform: translate(7px, 0px) scale(1, 1) rotate(0deg);">SIGN UP</div>
</div>
</div>
<div style="display: none;"></div>
<div style="display: none;">
<div style="transform: translate(0px, 0px) scale(0.5, 0.5) rotate(0deg);">
<div role="img">
<img src="images/lsloginform/newskin/try_it_MO.png?1444665385167">
</div>
</div>
<div style="transform: translate(0px, 75px) scale(1, 1) rotate(0deg);">
<canvas height="7" width="75" style="top: 0px; left: 0px; width: 75px; height: 7px;"></canvas>
</div>
<div style="transform: translate(0px, 82px) scale(1, 1) rotate(0deg);">
<div style="font-family: franklin-gothic-ext-comp-urw; font-weight: 700; font-style: normal; font-size: 15px; opacity: 1; color: rgb(63, 63, 63); transform: translate(7px, 0px) scale(1, 1) rotate(0deg);">SIGN UP</div>
</div>
<div></div>
</div>
<div style="display: none;"></div>
<div style="display: none;"></div>
</div>
</div>
Specific example, I'd like to the xpath of the above div utilizing the "SIGN UP" text at the end of the HTML. How do I go about doing that?
The application I test on is finicky as all hell, and being able to select by that attribute would make my life much easier. The reason this is a problem is because I need 3 different methods of grabbing an xpath: One for the button as normal, one for the hover, and another because the button changes momentarily when it is clicked. Most of my automation scripts look something like:
public class changeLanguageLogin {
public void run(WebDriver driver) {
WebElement changeLanguage = getWebElement(driver, "xpath", "img", "src", "select_application_language_normal");
Actions actions = new Actions(driver);
actions.moveToElement(changeLanguage).build().perform();
WebElement changeLanguageMO = getWebElement(driver, "xpath", "img", "src", "select_application_language_hover");
changeLanguageMO.click();
WebElement changeLanguageClicked = getWebElement(driver, "xpath", "img", "src", "select_application_language_pushed");
changeLanguageClicked.click();
}
private static By buildXPathExpression(String htmlElement, String attributeName, String attributeValue)
{
return By.xpath("//"+htmlElement+"[contains(#"+attributeName+",'"+attributeValue+"')]");
}
private static By buildCSSExpression(String htmlElement, String attributeName, String attributeValue)
{
return By.cssSelector(""+htmlElement+"["+attributeName+"='"+attributeValue+"']");
}
private static WebElement getWebElement(WebDriver driver, String operation, String htmlElement, String attributeName, String attributeValue)
{
By byObj = null;
WebElement webElementObj = null;
if(operation!= null)
{
if(operation.equals("xpath"))
{
byObj = buildXPathExpression(htmlElement,attributeName,attributeValue);
}
else if(operation.equals("cssSelector"))
{
byObj = buildCSSExpression(htmlElement,attributeName,attributeValue);
}
}
if(byObj != null)
{
webElementObj = driver.findElement(byObj);
}
return webElementObj;
}
}
Many, many, many times a day, one method of defining the xpath simply "will not work" and I have to scrounge around for another one. The goal is to not use any "hard coded" xpaths, as that was problematic when I had began the job.
So the answer I'm looking for: Define an xpath by the text in the HTML, "SIGN UP".
This response will not help if you are bound to only xpath or
css lookups.
Option 1
If you would be willing to add another case to your helper method I'm thinking that By.linkText may do what you're wanting?
/**
* #param linkText The exact text to match against
* #return a By which locates A elements by the exact text it displays
*/
public static By linkText(final String linkText) {
if (linkText == null)
throw new IllegalArgumentException(
"Cannot find elements when link text is null.");
return new ByLinkText(linkText);
}
Or possibly By.partialLinkText
/**
* #param linkText The text to match against
* #return a By which locates A elements that contain the given link text
*/
public static By partialLinkText(final String linkText) {
if (linkText == null)
throw new IllegalArgumentException(
"Cannot find elements when link text is null.");
return new ByPartialLinkText(linkText);
}
This would potentially be an issue if you're testing against a system that has been internationalized. Depending on the environment the locale of the user/browser would change the text you're looking for.
This can also be a maintenance issue if the text changes.
Option 2
If you have control of the HTML, you may consider adding id's to the elements on the page. With that then you can use the By.id lookup. From some of my preliminary research the element id is seen as one of the more reliable and consistent paths.
/**
* #param id The value of the "id" attribute to search for
* #return a By which locates elements by the value of the "id" attribute.
*/
public static By id(final String id) {
if (id == null)
throw new IllegalArgumentException(
"Cannot find elements with a null id attribute.");
return new ById(id);
}
Option 3
My final suggestion would be to try to implement your own By lookup. I would fall short on suggesting an implementation for the lookup, but if this behavior is what you're needing then you should be aware that you could potentially create a subclass to do what you're wanting.
Best of Luck.
For old time inlie style css, you generate the css selector depends on the style written for the div like "div[style*='paste_style_attribute']". However this method is not dependable because of duplication of same style.
For the following div:
<div style="font-family: franklin-gothic-ext-comp-urw; font-weight: 700; font-style: normal; font-size: 15px; opacity: 1; color: rgb(63, 63, 63); transform: translate(7px, 0px) scale(1, 1) rotate(0deg);">SIGN UP</div>
You can generate the following css selector:
"div[style*='font-family: franklin-gothic-ext-comp-urw; font-weight: 700; font-style: normal; font-size: 15px; opacity: 1; color: rgb(63, 63, 63); transform: translate(7px, 0px) scale(1, 1) rotate(0deg);']"
Java code:
driver.findElement(By.cssSelector("div[style*='font-family: franklin-gothic-ext-comp-urw; font-weight: 700; font-style: normal; font-size: 15px; opacity: 1; color: rgb(63, 63, 63); transform: translate(7px, 0px) scale(1, 1) rotate(0deg);']"))
Related
I want to count how many IMG tags there are under the surface div tag and echo the amount.
<div id="surface" style="width: 4567px; height: 4137px; left: -1850px; top: -1152px; cursor: default;">
<img src="https://media.memories.png" data-seat="L:106|EE:5" data-pl="1" style="position: absolute; cursor: pointer; width: 14px; height: 14px; left: 2221px; top: 1561px; display: block;">
<img src="https://media.memories.png" data-seat="L:106|EE:6" data-pl="1" style="position: absolute; cursor: pointer; width: 14px; height: 14px; left: 2237px; top: 1561px; display: block;">
<img src="https://media.memories.png" data-seat="L:106|EE:7" data-pl="1" style="position: absolute; cursor: pointer; width: 14px; height: 14px; left: 2253px; top: 1561px; display: block;">
<img src="https://media.memories.png" data-seat="L:106|EE:8" data-pl="1" style="position: absolute; cursor: pointer; width: 14px; height: 14px; left: 2269px; top: 1561px; display: block;">
</div>
Here is my non working attempt to get the count however its not returning the count to run my test in selenium IDE.
"//div[#surface='data-seat']/img"
Option 1:
You can simply use the below xpath and then get the count.
xpath to Image - "//div[#id='surface']/img"
System.out.println(driver.findElements(By.xpath("//div[#id='surface']/img")).size());
Option 2:
If you want to make it more complex, use the js to run the query and return the count.
JavascriptExecutor js = (JavascriptExecutor) driver;
Long number_of_imgs = (Long) js.executeScript("return document.querySelectorAll(\"div[id='surface'] img\").length");
System.out.println(number_of_imgs);
I would prefer the option 1.
Try:
//div[#surface='data-seat']/count(img)
For your example html, it outputs 4.
You can use the XPath-1.0 expression
count(//div[#id='surface']/img)
It counts all img children of all div elements.
To print the count of <img> tags within the <div> tag, you need to induce WebDriverWait for the visibilityOfAllElementsLocatedBy() and you can use either of the following Locator Strategies:
xpath:
System.out.println(new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//div[#id='surface']//img"))).size());
cssSelector:
System.out.println(new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("div#surface img"))).size());
I'm trying to fill a form on a website and I am unable to find the element that is listed in the code.
My code:
new WebDriverWait(driver, 30).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div[1]/form/div/div/input[1]")));
driver.findElement(By.xpath("/html/body/div[1]/form/div/div/input[1]")).sendKeys("TEST");
Relative website code:
<body>
<div id="pf_form" class="pf_formcontainer">
<form id="PF_1" class="form formBoxShadow" style="height: 1600px; width:
1800px; display: block; left: 0px; top: 30px;">
<div id="PF_4Container" class="PageContainer" style="left:0px;top:0px;z-
index:0;position:absolute">
<div id="PF_4" class="page" tabindex="" name="PF_4" style="width: 1800px;
height: 1600px; background-color: rgb(255, 255, 255); display: block;">
<input id="PF_5" class="textinput" name="PF_5" maxlength="99" value=""
onclick="return false;" style="left: 169px; top: 107px; z-index: 6; height:
18px; line-height: 18px; width: 206px; display: block;" type="text">
...
I've tried to change to the frame PF_4 and PF_4Container, no luck there. I've tried to find it by ID and other means but this one is kicking my butt.
The form is publicly visible here http://app.perfectforms.com/PresentationServer/Form.aspx/Play/FdjigAcE?f=FdjigAcE
Any guidance would be greatly appreciated. I've been trying to resolve this for weeks now.
If you have your HTMl elements with ids already why using xpath?
Simply use:
WebDriverWait wait = (new WebDriverWait(driver, 30));
WebElement input = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("PF_5")));
input.sendKeys("tests tests");
The program I have made contains only one search bar, so I can't filter more accurate or related tables.
I need one more search bar in order to enter the value in two search field by clicking post it will search from database and get most related once.
<?php
if(isset($_POST['search']))
{
$valueToSearch = $_POST['valueToSearch'];
// search in all table columns
// using concat mysql function
$query = "SELECT * FROM `included` WHERE CONCAT(`id`, `a`, `b`,
`c`,`c`,`d`,`e`,`f`,`g`,`h`,`i`) LIKE '%".$valueToSearch."%'";
$search_result = filterTable($query);
}
else {
$query = "SELECT * FROM `included`";
$search_result = filterTable($query);
}
// function to connect and execute the query
function filterTable($query)
{
$connect = mysqli_connect("localhost", "root", "", "hospitaldata");
$filter_Result = mysqli_query($connect, $query);
return $filter_Result;
}
?>
<!DOCTYPE html>
<html>
<head>
<img src="nop.jpg">
<title>PHP HTML TABLE DATA SEARCH</title>
<style>
table,tr,th,td{
border:.3px solid blue;
color:#000;
font-family:sans-serif;
}
div.relative {
position: relative;
top: -50px;
width: 1400px;
height: 100px;
color: #0C3;
font-family: "Arial Black", Gadget, sans-serif;
font-size: 24px;
}
div.absolute {
position: absolute;
top: 51px;
right: 20;
width: 1261px;
height: 40px;
color: #999;
font-family: Verdana, Geneva, sans-serif;
left: 65px;
}
input[type=text] {
alignment-baseline:central;
width: 130px;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
font-size: 16px;
background-color: white;
background-image:url('ds.jpg');
padding: 12px 20px 12px 40px;
-webkit-transition: width 0.4s ease-in-out;
transition: width 0.4s ease-in-out;
}
input[type=text]:focus {
width: 50%;
}
table,tr,th,tr
{
border:1px solid blue;
}
</style>
</style>
</head>
<body>
<div class="relative"><h1 align="center">HOSPITAL</h1>
<div class="absolute" align="center">Check provided points here</div>
</div>
<form action="index.php" method="post">
<input type="text" name="valueToSearch" placeholder="Search..."><br>
<input type="submit" name="search" value=">>"><br><br>
<table>
<tr>
<th>Building</th>
<th>Floor</th>
<th>zone</th>
<th>Room no</th>
<th>Room Type</th>
<th>Room Name</th>
<th>Types of Connection</th>
<th>Suggested</th>
<th>Provided</th>
</tr>
<!-- populate table from mysql database -->
<?php while($row = mysqli_fetch_array($search_result)):?>
<tr>
<td><?php echo $row['a'];?></td>
<td><?php echo $row['b'];?></td>
<td><?php echo $row['c'];?></td>
<td><?php echo $row['d'];?></td>
<td><?php echo $row['e'];?></td>
<td><?php echo $row['f'];?></td>
<td><?php echo $row['g'];?></td>
<td><?php echo $row['h'];?></td>
<td><?php echo $row['i'];?></td>
</tr>
<?php endwhile;?>
</table>
</form>
</body>
</html>
From your comments I understand the following:
you have a webpage with a search input field
you want a second input so your users can search more presice
one serach button should send both input fields
A really plain (and untested) version could look like this:
<form action="search.php" method="post">
<label><input name="search1"/> First keyword</label>
<label><input name="search2"/> Second keyword</label>
<input type="submit" value="Serach"/>
</form>
<?php
// If the Search button was pressed
if(isset($_POST['search1'])) {
$stmt = $pdo->prepare($query = "SELECT * FROM `included` WHERE CONCAT(`id`, `a`, `b`, `c`) LIKE '%:search1%' OR CONCAT(`d`, `e`) LIKE '%:search2%'");
$stmt->execute(['search1' => $POST['search1'], 'search2' => $POST['search2'] :? 'default');
foreach ($stmt as $row) {
// do something with $row
}
}
Of course you have to fit the SQL statement to your needs.
For infos about how to setup the $pdo database connection, please refer to the link: http://stackoverflow.com/a/60496/1152471
I was tring to make a question answer forum in which each question being displayed is having three divisons : Answers Count,View count,Question.So for achieving this I do something like this :
<div id="container">
<div id="a">
<p align="center">0</p>
<p align="center">Answers</p>
</div>
<div id="b-wrapper">
<div id="b">
<p align="center">0</p>
<p align="center">Views</p>
</div>
</div>
<div id="c-wrapper">
<div id="c">
<p align="center">Question</p>
<p align="right">Asked By Micheal</p>
</div>
</div>
<br style="clear: both;">
</div>
In css i did :
#container {
width: 800px;
}
#a, #b-wrapper, #c-wrapper {
float: left;
}
#a {
width: 10%;
background-color: #0ff;
}
#b-wrapper {
width: 10%;
}
#b {
margin-left: 20px;
background-color: #0f0;
}
#c-wrapper {
width: 60%;
}
#c {
margin-left: 20px;
background-color: #EEEEEE;
}
Now I am facing two problems.
The divison for Answer is getting a bit bigger in height.How to manage it.
I am fetching questions from database Like :
while(rs.next){
String myid=rs.getString("ID");
//display here all three divisons where rs is ResultSet
}
So here problem is that i want to assign this myid to each of the divison And on click of any divison move to second.jsp.
Please help to solve these problems.
I am not able to get the text from the web table. Please see the screen shot below for the text I am looking for. How to get the text Quick App from the below screen shot.
In the screen shot, if I find the Quick App then I have to click on Edit link for that User.
Code for xpath count for the table below:
//table[#id='ctl00_MasterPlaceHolder_GvUsers']/tbody/tr
I have tried to capture the text by using below code:
text = driver.findElement(By.xpath("//table[#id='ctl00_MasterPlaceHolder_GvUsers']
/tbody/tr["+k+"]/td[3]")).getText();
System.out.println(text);
I am getting Null value after executing the above code.
Please help me in this issue by providing code for it. Help will be appreciated.
<table id="ctl00_MasterPlaceHolder_GvUsers" class="btext" cellspacing="0" cellpadding="2" border="0" style="color:#333333;width:100%;border-collapse:collapse;"> <tbody> <tr align="left" style="color:White;background-color:#507CD1;font-weight:bold;"> <tr class="text" style="color: rgb(28, 28, 28); background-color: rgb(249, 182, 115); font-weight: normal; height: 10px; text-decoration: none;" onclick="javascript:__doPostBack('ctl00$MasterPlaceHolder$GvUsers','Select$0')" onmouseout="javascript:setMouseOutColor(this);" onmouseover="javascript:setMouseOverColor(this);">
<tr style="background-color: White; height: 10px; text-decoration: none;" onclick="javascript:__doPostBack('ctl00$MasterPlaceHolder$GvUsers','Select$1')" onmouseout="javascript:setMouseOutColor(this);" onmouseover="javascript:setMouseOverColor(this);"> <tr style="background-color: rgb(239, 243, 251); height: 10px; text-decoration: none;" onclick="javascript:__doPostBack('ctl00$MasterPlaceHolder$GvUsers','Select$2')" onmouseout="javascript:setMouseOutColor(this);" onmouseover="javascript:setMouseOverColor(this);">
<tr style="background-color: White; height: 10px; text-decoration: none;" onclick="javascript:__doPostBack('ctl00$MasterPlaceHolder$GvUsers','Select$3')" onmouseout="javascript:setMouseOutColor(this);" onmouseover="javascript:setMouseOverColor(this);"> <tr style="background-color: rgb(226, 222, 208); height: 10px; text-decoration: none;" onclick="javascript:__doPostBack('ctl00$MasterPlaceHolder$GvUsers','Select$4')" onmouseout="javascript:setMouseOutColor(this);" onmouseover="javascript:setMouseOverColor(this);"
<tr style="background-color: White; height: 10px; text-decoration: none;" onclick="javascript:__doPostBack('ctl00$MasterPlaceHolder$GvUsers','Select$5')" onmouseout="javascript:setMouseOutColor(this);" onmouseover="javascript:setMouseOverColor(this);"> <td>7CUser44</td> <td>Swamy m Kumara</td> <td>Quick App</td> <td>QuickApp User</td> <td>Active</td> <td>halcyon2</td> <td>COTTAGE GROVE </td> <td>WI</td> <td> </tr>
int xpathcount= driver.findElements(By.xpath((OR.getProperty("xpathcount_Users_ID")))).size();
System.out.println("Number of rows displayed in Site History table: " +xpathcount);
int k;
for (k=1;k<=xpathcount;k++)
{
Select table = new Select(driver.findElement(By.xpath("//table[#id='ctl00_MasterPlaceHolder_GvUsers']/tbody/tr["+k+"]/td[3]")));
text1 = table.getFirstSelectedOption().getText();
System.out.println("Selected User Level is: "+text1);
Thread.sleep(2000);
text = driver.findElement(By.xpath("//table[#id='ctl00_MasterPlaceHolder_GvUsers']/tbody/tr["+k+"]/td[3]")).getText();
System.out.println(text);
}
Please find the code I have used.
Here, i have modified my code as below and worked. Thanks for all the members who tried helping me.
int xpathcount=
driver.findElements(By.xpath((OR.getProperty("xpathcount_Users_ID")))).size();
System.out.println("Number of rows displayed in Site History table: " +xpathcount);
int k;
for (k=2;k<=xpathcount;k++)
{
text = driver.findElement(By.xpath("//table[#id='ctl00_MasterPlaceHolder_GvUsers']
/tbody/tr["+k+"]/td[3]")).getText();
System.out.println(text);
}
Here i can give on simple example using python webdriver. but i don't know how to get text using java. see below example
word=driver_find_element_by_xpath("xpath value which text you need from web table")
print word.text
Answer will be show which you have selected in web table.
Hard to give a proper answer with no HTML but here goes something that might help.
public void getEditTable(final WebDriver driver, final By table, final String query) {
List<WebElement> lines = table.findElements(By.tagName("tr"));
for (WebElement line : lines) {
List<WebElement> cols = line.findElements(By.tagName("td"));
if (cols.get(2).getText().equals(query)) {
List<WebElement> actions = cols.get(8).findElement(By.tagName("a"));
actions.get(0).click();
}
}
}
Now i have to point out that this would most likely need a lot of work on your side, but maybe you can get the main idea. I do something similar to the web tables for my company CRUD sites.