Selenium div attributes keep changing, how can I find this element? - java

I am trying to find an element with Selenium and Java, the problem is that the element's id, class, and name always increment so I am not able to find it with selenium. Below is what I am currently trying:
WebElement field = driver.findElement(By.xpath("//input[contains(#linkText, 'Broadcast copy')]"));
In my html file these are the attributes that keeps changing:
id="files[%2Fopt%240%2Frules%2F%2F000102%2.xml][%2Fcluster%2Fname]"
name="files[%2Fopt%240%2Frules%2F%2F000102%2.xml][%2Fcluster%2Fname]"
value="copy (Cluster 102)"
Entire html
<tbody>
<tr class='rowOdd'>
<td><b>Name</b></td>
<td> <input type='text' data-validation='required validate-name-unique validate-name-not-empty' size='65' id='files[%2Fopt%240%2Frules%2F%2F000102%2Fcluster.xml][%2Fcluster%2Fname]' name='files[%2Fopt%240%2Frules%2F%2F000102%2Fcluster.xml][%2Fcluster%2Fname]' value='copy (Cluster 102)' /> </td>
These always increment and I have no access to the html file to change anything. So my question is how can I find this input element? Thanks in advance.
UPDATE
I get the error:
Unable to locate element:{"method":"id", "selector":"files[.*][.*]"}

I believe the xpath you are using is incorrect. Use
//input[contains(text(), 'Broadcast copy')]
instead of
//input[contains(#linkText, 'Broadcast copy')]
According to the html you have provide the following should work as well
//body[contains(.,'Name')]//input

Try this..
In case "copy (Cluster" text in value attribute is not changing, then you can try below xpath:-
//body[contains(.,'Name')]//input[contains(#value,'copy (Cluster')]

Since the attributes of id, class, and css were constantly changing, 'data-validation' was one that stayed the same all the time. So the code below worked for me.
driver.findElement(By.xpath("//input[#data-validation='required validate-name-unique validate-name-not-empty']"));

Related

I was able to run my program till morning. But suddenly getting this error " Driver info: driver.version: unknown [duplicate]

I am getting the following error:
"Compound class names not permitted"
While trying to access web element where-in the element's class name have spaces in between. The page source for the web element is as below.
driver.findElement(By.className("alert alert-success"));
<div class="alert alert-success" alert-dismissable"="" id="58417" style="display: none;">
<button type="button" class="close hide-panel close-icon-58417" data-dismiss="alert" aria-hidden="true" style="display: inline-block;">×</button><span id="caret-58417" class="notification-caret caret-58417"></span>
<div class="hide-panel close-icon-58417" id="58417" style="display: block;">
<span class="glyphicon glyphicon-ok-sign"></span><strong>Success</strong> KeyLinks Updated Successfully
<div class="notification-panel-body panel-body-58417">REST Invocation Success</div>
</div>
</div>
I tried to find the element by CSS path as below. But the element is not searchable with this.
driver.findElement(By.cssSelector(".alert alert-success"));
This was the workaround given in the Link but still no success. your help will be much appreciated.
You can access the element if it has multiple classes using "By":
from selenium.webdriver.common.by import By
driver.findElement(By.cssSelector(".alert.alert-success"));
You can use
driver.findElement(By.className("alert-success"));
or
driver.findElement(By.className("alert"));
As right now selenium doesn't support multiple class name.If your class name includes a space, WebDriver will see it as a "compound selector".
You can use cssSelector or id for selecting the webelement.
If usage of class name is must you can use the following ways:
1) css selectors:
driver.findElement(By.cssSelector(".alert.alert-success");
2) using xpath
driver.findElement(By.xpath("//div[#class='alert alert-success']"))
Try avoiding xpath and use css selectors instead.
The issue is because of the way find by Class name works.
in your code class name is class="alert alert-success"
If the class name has space you'll get the above error. You can simply get rid of the issue by using Id, CSS, Xpath, regular expression or any other element finder method.
Do you need to use Class Name or can you use another method? Let me know if you need to use class name.
It can also be done using class name like:
driver.find_element_by_class_name("alert")
or
driver.find_element_by_class_name("alert-success")
you can select anyone class name from two or more class names separated by spaces it'll work just fine.
Most of the time class name attribute of any element has groups of classes names.
like class = 'alert alert-success another class name'
if you are using css selector ,then just remove spaces between the class names and create you clas name like below :
driver.findElement(By.cssSelector(".alert.alert-success.another.class.name")
. => represent class
=> represent ID
for CSS selector.

How we can get java object value( url ) in Thymeleaf conditional operator?

I want to put one condition in thymeleaf, If my object contain url so i want to print anchor tag with Url so i can open it and if not, then a message should be display.
<span th:utext="${#strings.contains({resultModel.results},'s3')} ? '<a target="_blank" href="${resultModel.results}" >URL</a>' : ${resultModel.results}"></span>
I want to get URL as a java object in href. Please suggest href="${resultModel.results}"
If i use href="http://google.co.in" so it is working but while using href="${resultModel.results}" i am not getting value.
Note: In Above html code else condition is working and getting message as a results.
I wouldn't try and combine that logic... Avoid putting html in html by just splitting the tags out the inner html into its own tags.
<th:block th:with="condition=${#strings.contains(resultModel.results, 's3')}">
<a th:if="${condition}" target="blank" th:href="${resultModel.results}">URL</a>
<span th:unless="${condition}" th:text="${resultModel.results}" />
</th:block>

Extract DOM property value using Selenium

In Firebug and other DevTools you can get the DOM properties and values corresponding to an HTML element.
How can such values be extracted using selenium-java code?
I had tried getAttribute(), but it seems to be working only for HTML attributes and not for DOM properties like "value" or "spellcheck" etc.
The reason I went for this approach is that the value associated with the <input> text field (snippet below) is run-time generated and data is bound to it using Knockout. And hence it's not possible to capture them with standard approaches like getText(), getAttribute("value"), getAttribute("text"), getAttribute("innerHTML"), getAttribute("innertext"), etc.
HTML snippet for the HTML element:
<input class="form-control" type="text" style="cursor: text" readonly="readonly" data-bind="textInput: url">
I know this is an old question but it might give someone else a hand out
Use this in the console
$$("input.form-control").value
if it returns the required you will have to execute the Javascript using WebDriver i.e.
driver.ExecuteScript("var data = arguments[0].value; return data;", (Element as RemoteWebElement)
According to the Selenium documentation, there is only the getAttribute() function, which is described as follows:
Get the value of a the given attribute of the element. Will return the current value, even if this has been modified after the page has been loaded. More exactly, this method will return the value of the given attribute, unless that attribute is not present, in which case the value of the property with the same name is returned (for example for the "value" property of a textarea element). If neither value is set, null is returned. ...
According to this, getAttribute("value") should return the DOM property value in case there is no HTML attribute named value.
If that's not the case, it may be a timing issue. I.e. the value is read by Selenium before it gets set.
In Selenium 4 use getDomAttribute() and getDomProperty().

Java selenium xpath - getting all elements under a specific element

this is a simplified HTML structure i'm searching through:
<div class="main">
...other stuff...
<td class="child">44</td>
<td class="child">59</td>
<td class="child">11</td>
</div>
<div class="main">
...other stuff...
<td class="child">5</td>
<td class="child">14</td>
<td class="child">98</td>
</div>
...this kind of structure repeats with similar numbers a few more times but with identical class names
I need to extract all the numbers under the first found main class so I've made a query to search for the first main, and all td's with the specific class under it. Can somebody give me a hint what I'm doing wrong since this query gives me all the numbers from all td's with class "child" in all "main" div's:
List<WebElement> koefi = driver.findElements(By.xpath("//div[#class='main'][1]//td[#class='child']"));
What am I doing wrong or is my logic right but I'm missing some other parts of html which I haven't pasted here since the structure is too cumbersome..?
Thank You!!
p.s.:
I tried this also but again, I get contents of all td's with "child" class, and not only the first "main"..
List<WebElement> koefi = driver.findElements(By.xpath("//*[1][#class='main']//td[#class='child']"));
UPDATE:
I managed to solve my problem by first getting the first occurence of the "main" div which is by default found by the .findElement function:
WebElement element = driver.findElement(By.xpath("//*[1][#id='main']"));
And then extracting with .findElements function the "child" classes:
List<WebElement> kk = element.findElements(By.className("child"));
I am still unable to figure out why doesn't the .findElements with my xpath work, or it works too well, it extracts every "main" class and not only the first one. And the original HTML is too big to paste here, so I don't want to bother you guys!!
A much cleaner solution would be to first grab all the divs with class main, like so:
List<WebElement> allDivs = driver.findElements(By.className("main"));
Then, as you specified, find all the tds with class child, like so:
List<WebElement> tds = allDivs[0].findElements(By.className("child"));
After that, it is just a matter of iterating over all the "tds" and read out your values.
You say in a comment that
the "main"'s are not direct siblings
so I suspect you are falling foul of a common error related to the definition of // in XPath. The path
//div[#class='main'][1]
does not select the first "main" div in the document. The reason for this is that // is a shorthand for /descendant-or-self::node()/ (including the leading and trailing slashes), so what this path actually means is
/descendant-or-self::node()/child::div[#class='main'][1]
When you see it fully expanded you realise that the [1] relates to the child:: step and not the search for descendants, i.e. you'll get all the div elements in the document that have the class "main" and are the first div-with-class-main under their respective parent elements. If your actual HTML is
<div>
<div class="main">...</div>
</div>
<div>
<div class="main">...</div>
</div>
then that XPath would select both of them (they're both the first under their parents). If you do just want the first one in the document then you should use the descendant:: axis
/descendant::div[#class='main'][1]
which will give you the first matching descendant only.

JSP send data to Java class

I'm looking to send information after each link click to my java class to help increment a counter and to change an object which is held in my bean (myGame) which holds an array of 'cases'. I understand that I can increment a counter using JS, but i'd like to keep all game logic within the bean if possible.
I have considered using forms and changing the anchor to a submit button, however, I'd like to keep that the player can no longer click the link after it the case is eliminated.
The printCase(int) function works by finding the corresponding case in the array, checking the value of a boolean (is the case is eliminated from the game [deal or no deal]) and then prints the amount of money held in the case if eliminated; the case number if it is not.
I have about a dozen cases.
<jsp:useBean id="myGame" scope="session" class="dealOrNoDeal.GameLogic"/>
<table border="1" id="dndTable">
<form action="/../doStuff.jsp" method="post">
<tr>
<td> <%= myGame.printCase(0) %> </td>
</tr>
</form>
</table>
I've also considered changing my bean to a servlet. Does that work? Can you have a bean in a servlet?
Thanks all.
Update: I've made printCase now print the tag that it's within now, as well. Prints as a submit button if the case is not opened, prints as a <p> if it is (I need it to use the class). Attempted putting the <td>s in there as well, but it somehow messes up the formatting.
I'm now looking to get the name of the one button that was clicked, any ideas?
I'm not sure about understand completely your qestion. But i'll try:
U have 2 ways:
You have to build a jquery where on each button click u call a servlet where u send information to your java class;
Using DWR: http://directwebremoting.org/dwr/index.html

Categories