I'm looking to implement a general localisation test using webdriver and my idea is:
Select all elements that contain text
Use a java language identification library to verify that the text is in some specific language
I looked up various ways to select elements using text but everything documented seems to show ways of locating using specific text using contains() or text()
I thought the following would work:
//*[contains(text(), '')]
but that selects everything whether it has text or not. It also selects elements in the header. I want to select all visible text on the page, extract that text and pass it through the language identification library element by element.
You can use this XPath
//*[text() != ""]
This will give you all the elements with non-empty text.
So that
List<WebElement> list = driver.findElements(By.xpath("//*[text() != '']"));
will give you a list of all web elements on the page containing texts.
UPD
If you wish to get only elements containing texts themselves, you can exclude the elements containing texts in their children only by this code:
List<WebElement> real = new ArrayList<>();
for(WebElement element : list){
js = (JavascriptExecutor)driver;
String text = js.executeScript("""
return jQuery(arguments[0]).contents().filter(function() {
return this.nodeType == Node.TEXT_NODE;
}).text();
""", element);
if(text.length()>0){
real.add(element);
}
The final list of elements will be in real list.
The idea is from here. Translated from Python to Java according to this syntax
Related
I need to get the IDs present in the DOM that start with "starx-" into an array. After that hyphen, there is usually some combination of uppercase, lowercase, and digits - it depends upon the dropdown selected previously. But starx- is common to all ids, no matter what is selected in the previous dropdown (and there are a LOT of options so... no to creating a bunch of "if" statements based on the previous drop down)
To do so, I created this line here to match all of the id's in the DOM that start with starx-:
List<WebElement> allStarX = driver.findElements(By.cssSelector("[id^='starx-']"));
So it's good at finding them. A few print statements I threw in there show me that if there are 4 such IDs in the DOM, it will find them all. If there are 7, it will have 7 elements in that List. Unfortunately , this List doesn't contain the actual IDs. It contains:
[[ChromeDriver: chrome on WIN8_1 (f665490daee44e1039265763f67008cc)] -> css selector: [id^='starx-']]
for each id beginning with starx- that exists in the DOM. Ideally I'd get all the ID using the .getAttribute method, but that's for strings. For example, if I add it onto the end of this:
List<WebElement> allStarX = driver.findElements(By.cssSelector("[id^='starx-']")).getAttribute();
I have a type mismatch. And if I do this:
for (WebElement starx : allStarX)
{
starx.getAttribute("id");
System.out.println(starx);
}
It still prints out a bunch of this:
[[ChromeDriver: chrome on WIN8_1 (f665490daee44e1039265763f67008cc)] -> css selector: [id^='starx-']]
I kind of know why that last one doesn't work, but I don't understand why the first one doesn't.
Absolute xpaths don't seem to work because there are a lot of previous options add and remove things from the DOM.
Can anyone suggest something that might help?
As far as my understanding goes, you are trying to get the IDs which start with the text of 'starx-'. You have created a list of webelements (List<WebElement>) and while extracting the text, you are looping it by not extracting the attribute of the id, which is the issue.
You can handle it as mentioned below:
List<WebElement> allStarX = driver.findElements(By.cssSelector("[id^='starx-']"));
for (WebElement starx : allStarX)
{
System.out.println(starx.getAttribute("id"));
}
Hope this helps.
Is it possible to derive (i.e. by automatically applying all inherited CSS styles and, if it is possible - JS scripts as well) colour of the text in given WebElement?
For instance, I want to detect colour of text in each visible element:
WebElement body = driver.findElement(By.tagName("body"));
List<WebElement> elements = body.findElements(By.cssSelector("*"));
for (WebElement we : elements) {
if (we.isDisplayed()) {
// ... colour of text in "we" element?
}
}
Is it possible to do?
P.S. I realise that each we element can contain nested elements and colour inside them can differ. But let's simplify the issue and consider each we as element without nested tags.
You can use getCssValue() something like below:
element.getCssValue("color")
which in your case will be
we.getCssValue("color")
For reference - http://www.seleniumeasy.com/selenium-tutorials/how-to-get-css-values-using-webdriver
I am trying to identify a xpath of a textfield where the class name is "DeleteBackwardTextField" and Origin class is "UITextField". There are no label, name and text it. No other information to identify it.
There are 2 textfield with same above properties.
So my following xpath identifies two text fields.
By.xpath("//textfield[#class='DeleteBackwardTextField']")
How can I identify the xpath of 1 particular field. I assume index can be used. Can anybody provide a syntax for indexing.
Appreciate your help.
You can go with XPATH or CSS. The trick is to have a list of WebElements identified and then you can iterate over it.
List<WebElement> myList = driver.findElements(by.cssSelector(...); //or XPATH;
for (WebElement txtField : myList) {
// do what you need here, for each element at a time
}
Use this xpath.
(//textfield[#class='DeleteBackwardTextField'])[index]
EX: (//textfield[#class='DeleteBackwardTextField'])[1] -> first element when you have many elements matching //textfield[#class='DeleteBackwardTextField']
Note that this xpth - //textfield[#class='DeleteBackwardTextField'][2] has different meaning - it means second child of its parent.
I have this xpath: //*[#id="someId::button"]
Pressing it shows a dropdown list of values.
Now, I know all the elements in the list have an id like this :
//*[#id="someId--popup::popupItemINDEX"]
, where INDEX is a number from 1 to whatever the number of options are.
I also know the value which I must click.
One question would be: since I will always know the id of the button which generates the dropdown, can I get all the elements in the dropdown with a reusable method? (I need to interact with more than one dropdown)
The way I thought about it is:
get the root of the initial ID, as in:
//*[#id="someId
then add the rest : --popup::popupItem. I also need to add the index and I thought I could use a try block (in order to get though the exceptions when I give a bigger than expected index) like this:
for(int index=1;index<someBiggerThanExpectedNumber;index++){
try{
WebElement aux= driver.findElement(By.xpath(builtString+index+"\"]"));
if(aux.getText().equals(myDesiredValue))
aux.click();
}catch(Exception e){}
}
Note that I am using the webdriver api and java.
I would like to know if this would work and if there is an easier way of doing this, given the initial information I have.
EDIT: The way I suggested works, but for an easier solution, the accepted answer should be seen
As a rule of thumb, try to select more elements by one query, if possible. Searching for many elements one-by-one will get seriously slow.
If I understand your needs well, a good way to do this would be using
driver.findElement(By.id("someId::button")).click();
driver.findElement(By.xpath("//*[contains(#id, 'someId--popup::popupItem') " +
"and text()='" + myDesiredValue + "']"))
.click();
For more information about XPath, see the spec. It's surprisingly a very good read if you can skip the crap!
That finds and clicks an element with text equal to you desired value which contains "someId--popup::popupItem" in its ID.
List<WebElement> list = driver.findElements(By.xpath("//*[contains(#id, 'someId--popup::popupItem')]"));
That finds all just all elements that contain "someId--popup::popupItem" in their ID. You can then traverse the list and look for your desired element.
Did you know you can call findElement() on a WebElement to search just it's children?
- driver.findElement(By.id("someId")).findElements(By.className("clickable"))
Without a peek on the underlying HTML, I guess I can't offer the best approach, but I have some in my head.
Have you tried using JavascriptExecutor?
If you are willing to write a little JavaScript then this would be straightforward than in java (I think)
All you will need to do is have some JavaScript crawl through the DOM subtree, and return a list of DOM elements matching your criteria. WebDriver will then happily marshall this as List<WebElement> in the java world.
The Safer Method to use here is
int size=driver.findElements(By.xpath("//*[#id='someId::button']")).size();
Start using Index Now
String builtString="//*[#id='someId::button'][";
for(int index=1;index<=size();index++)
{
try
{
WebElement aux= driver.findElement(By.xpath(builtString+index+"\"]"));
if(aux.getText().equals(myDesiredValue))
aux.click();
}
catch(Exception e){}
}
Please Let me know is the above funda is working or not.
I'm new to Jsoup, but this appears to be a great tool. I'm trying to extract the robots metatag.
I have the following code:
Document doc = Jsoup.parse(htmlContent);
Elements metatags = doc.select("meta");
Element robots = metatags.attr("name", "robots"); // is getting the first element of the list
The last line is wrong.
I want to know if is necessary to run the list of elements to find the element that matches the attribute or there a way that extracts the element that matches the attribute from the Elements list.
Edit 1: I solved this changing to doc.select("meta[name=robots]").
Edit 2: In another words: I want to know how to get all elements in a Elements list that matches some atribute requisite.
Edit 3: I was precipitated doing this question because I had not seen the main documentation yet. Sorry.
It's possible to set the attribute and value you want to retrieve in the select() method to do a better filtering.
Change the select to: doc.select("meta[name=robots]"); and it will get all elements that has the meta tag and it have the name attribute equals robots.
Have you read the JSoup documentation? Here it is from the method you are using:
attr
public Elements attr(String attributeKey,
String attributeValue)
Set an attribute on all matched elements.
Parameters:
attributeKey - attribute key
attributeValue - attribute value
Returns:
this
It returns this. Which means it will return an Elements object. This can't be assigned to an Element object.
I also think you want to use Document.getElementsByTag(String), instead of select.