I have the following code snippet and the screenshot attached.
String query = "new UiScrollable(new UiSelector().className(\"androidx.recyclerview.widget.RecyclerView\"))" +
".scrollIntoView(new UiSelector().text(\"Test Group\"))";
driver.findElementByAndroidUIAutomator (query).click ();
What I want is to find an element with the text "Test Group" using UISelector, but inside the RecyclerView only (not searching the whole app source). What I get is the element inside search field instead (not in the RecyclerView).
Please advice. I know that I can get all searched elements using findElements(By.id("name")). But I want to use UI selector in this case.
With UiSelector you can use chaining:
String query = "new UiScrollable(resourseIdMatches(\".*recycler_view\")).scrollIntoView(resourseIdMatches(\".*recycler_view\")).childSelector(text(\"Text Group\")))";
In addition new UiSelector... part can be omitted. Appium does support this syntax.
I am using Selenium 3.x with Appium and working on Native iOS App which uses XCUITest as Automation name.
I can access individual element with Accessibility ID and it works fine e.g. driver.findElement(MobileBy.AccessibilityId("Location")).click();
Is there way to get a list of all Accessiblilty IDs (or the values) on a single page / form?
Thanks in advance.
You can try something like below, only you have tochange first line of the code as per android schema, as I'm not aware where all the elements are contained in an app.
Following example identifies the name (or accessibility id attribute in your case) for all the div elements, so you just need to tweak the first line:
List<WebElement> allElems = driver.findElements(By.xpath("//body//div"));
System.out.println("Avaialable Accesible ids :");
int c=0;
for(WebElement ele : allElems) {
c++;
System.out.print("for element " + c +" Accessibility ID is :");
System.out.println(ele.getAttribute("name"));
//or
System.out.println(ele.getAttribute("content-desc"));
}
I am trying to write an automation step which clicks on a link, the locator which I need to use to target the link is matching to the end of the title attribute, the reason being there may be multiple links of the same type, some of which will be named the same, this section of the title I am looking at is the only bit within these links guaranteed to be unique (not my call, this is an existing system in place I am writing tests for). I have no issue finding the locator of the link using this method.
Note: some elements of the code have been amended due to data security restrictions of my employer.
#FindBy(css = "#id .Content form > a[title$='12345678']")
WebElement linkName;
However the reference number at the end of the title that I'm looking for may change, depending on other data inputs, and it will be used in multiple places thorughout my automation suite, so what I am trying to do is store that number as a String at the very start of the suite and have the locator, and any other areas which need it, reference it, which is where my trouble begins. I seem to be unable to get the locator to work referencing the string.. When I try this I keep getting errors, usually syntax errors.
#FindBy(css = "#id .Content form > a[title$='%s']", titleVariable)
WebElement linkName;
I have tried rearranging this multiple times but can't seem to get it into a working format. Any suggestions would be welcome.
I apologise if this seems unclear, As stated above due to the nature of my employers business I can't give too many specifics due to data security restrictions so have had to explain things in a more round about way than I could have.
first of all, u must have to use constant variable here. so use code like below:
final String titleVariable = "ur title";
#FindBy(css = "#id .Content form > a[title$='"+titleVariable+"']")
WebElement linkName;
If you have WebDriver object in this class you can do this:
String titleVariable = "Your Title";
String cssSelector = "#id .Content form > a[title$='" + titleVariable + "']";
WebElement linkName = driver.findElement(By.cssSelector(cssSelector));
Need your help in locating proper XPath for findElements method in Selenium. Below are the details:
URL - http://www.cleartrip.com/hotels/info/hotel-royal-heritage-30km-before-mount-abu-713374/
From the above URL, I want to extract only the below headers available on right hand side of the page.
1) Basic Amenities
2) Food & Beverages
3) Travel
4) Personal Services
5) Other Amenities
I have tried below XPaths till now:
1) html/body/div[1]/div[4]/div[2]/*
This extracts everything along with amenities listed under the headers.
2) html/body/div[1]/div[4]/div[2]/h3/*
this doesn't work.
3) html/body/div[1]/div[4]/div[2]/h[*]
this doesn't work either.
Any ideas please?
Thanks,
Bharat.
You can try these
//*[#class='col col8']/h3
//*[#class='hotelInfo row']/div[2]/h3
You can iterate using this:
List<WebElement> expected = driver.findElements(By.xpath("//*[#class='col col8']/h3"));
for (int i=0; i<expected.size(); i++){
System.out.println(expected.get(i).getText());
}
Which prints
Basic amenities Food & Beverage Travel Personal Services Other
Amenities Hotel Amenities Basic Room Amenities
Why not store all the elements in a list?
List<WebElement> list = getDriver().findElements(By.xpath(.//*[#id='HotelTabs']/li));
This will make it easy for you to iterate over the headers and do what you need to do.
Below is xpath which can help you to identify the expected webelements.
Xpath: (//*[contains(#class,'amenitiesDescription ')]/div)[3]/following-sibling::div/strong
-> Strategy Used
-- Structure based locator (i.e. xpath)
-- tried to identified an element first and later tried to get the below siblings.
-- Added all the identified webelements to a list.
-- Used a for-each loop to iterate and get the inner text from the element and print on the console.
List<WebElement> eleList = driver.findElements(By.xpath("(//*[contains(#class,'amenitiesDescription ')]/div)[3]/following-sibling::div/strong");
for(WebElement ele: eleList){
System.out.println(ele.getText());
}
I have a curious case where the selenium chrome driver getText() method (java) returns an empty string for some elements, even though it returns a non-empty string for other elements with the same xpath. Here is a bit of the page.
<div __gwt_cell="cell-gwt-uid-223" style="outline-style:none;">
<div>Text_1</div>
<div>Text_2</div>
<div>Text_3</div>
<div>Text_4</div>
<div>Text_5</div>
<div>Text_6</div>
</div>
for each of the inner tags, I can get valid return values for getTagName(), getLocation(), isEnabled(), and isDisplayed(). However, getText() returns an empty string for some of the divs.
Further, I notice that if I use the mac chrome driver, it is consistently the ‘Text_5’ for which getText() returns an empty string. If I use the windows chrome driver, it is , it is consistently the ‘Text_2’ for which getText() returns an empty string. If I use the firefox driver, getText() returns the expected text from all the divs.
Has anyone else had this difficulty?
In my code, I use something like this…
ArrayList<WebElement> list = (ArrayList<WebElement>) driver.findElements(By.xpath(“my xPath here”));
for (WebElement e: list) System.out.println(e.getText());
As suggested below, here is the actual xPath I am using. The page snippet above deals with the last two divs.
//*[#class='gwt-DialogBox']//tr[contains(#class,'data-grid-table-row')]//td[contains(#class,'lms-assignment-selection-wizard-cell')]/div/div
Update: The textContent attribute is a better option and supported across the majority of browsers. The differences are explained in detail at this blog post: innerText vs. textContent
As an alternative, the innerText attribute will return the text content of an element which exists in the DOM.
element.getAttribute("innerText")
The isDisplayed() method can sometimes trip over when the element is not really hidden but outside the viewport; getText() returns an empty string for such an element.
You can also bring the element into the viewport by scrolling to it using javascript, as follows:
((JavaScriptExecutor)driver).executeScript("arguments[0].scrollIntoView(true);", element);
and then getText() should return the correct value.
Details on the isDisplayed() method can be found in this SO question:
How does Selenium WebDriver's isDisplayed() method work
WebElement.getAttribute("value") should help you !!
This is not a solution, so I don't know if it belongs in an answer, but it's too long for a comment and includes links, so I'm putting it an answer.
I have had this issue as well. After doing some digging, it seems that the problem arises when trying to get the text of an element that is not visible on the screen.(As #Faiz comments above.)This can happen if the element is not scrolled to, or if you scroll down and the element is near the top of the document and no longer visible after the scroll. I see you have a FindElements() call that gets a list of elements. At least some are probably not visible; you can check this by trying boolean b = webElement.isDisplayed(); on each element in the list and checking the result. (See here for a very long discussion of this issue that's a year old and still no resolution.)
Apparently, this is a deliberate design decision (see here ); gettext on invisible elements is supposed to return empty. Why they are so firm about this, I don't know. Various workarounds have been suggested, including clicking on the element before getting its text or scrolling to it. (See above link for example code for the latter.) I can't vouch for these because I haven't tried them, but they're just trying to bring the element into visiblity so the text will be available. Not sure how practical that is for your application; it wasn't for mine. For some reason, FirefoxDriver does not have this issue, so that's what I use.
I'm sorry I can't give you a better answer - perhaps if you submit a bug report on the issues page they'll see that many people find it to be a bug rather than a feature and they'll change the functionality.
Good luck!
bsg
EDIT
See this question for a possible workaround. You won't be able to use it exactly as given if isDisplayed returns true, but if you know which element is causing the issue, or if the text is not normally blank and you can set an 'if string is empty' condition to catch it when it happens, you can still try it. It doesn't work for everyone, unfortunately.
NEW UPDATE
I just tried the answer given below and it worked for me. So thanks, Faiz!
for (int count=0;count<=sizeofdd;count++)
{
String GetInnerHTML=getddvalue.get(count).getAttribute("innerHTML");
}
where,
1. getddvalue is the WebElement
2. sizeofdd is the size of getddvalue
element.getAttribute("innerText") worked for me, when getText() was returning empty.
I encountered a similar issue recently.
I had to check that the menu tab "LIFE EVENTS" was present in the scroll box. The problem is that there are many menu tabs and you are required to scroll down to see the rest of the menu tabs. So my initial solution worked fine with the visible menu tabs but not the ones that were out of sight.
I used the xpath below to point selenium to the parent element of the entire scroll box.
#FindBy(xpath = "//div[contains(#class, 'menu-tree')]")
protected WebElement menuTree;
I then created a list of WebElements that I could increment through.
The solution worked if the menu tab was visible, and returned a true. But if the menu tab was out of sight, it returned false
public boolean menuTabPresent(String theMenuTab) {
List<WebElement> menuTabs = new ArrayList<WebElement>();
menuTabs = menuTree.findElements(By.xpath("//i/following-sibling::span"));
for(WebElement e: menuTabs) {
System.out.println(e.getText());
if(e.getText().contains(theMenuTab)) {
return true;
}
}
return false;
}
I found 2 solutions to the problem which both work equally well.
for(WebElement e: menuTabs) {
scrollElementIntoView(e); //Solution 1
System.out.println(e.getAttribute("textContent")); //Solution 2
if(e.getAttribute("textContent").contains(theMenuTab)) {
return true;
}
}
return false;
Solution 1 calls the method below. It results in the scroll box to physically move down while selenium is running.
protected void scrollElementIntoView(WebElement element) {
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true)", element);
}
Solution 2 gets the text content (even for the menu tabs not currently visible) of the attribute that you are pointing to. Thus doing the job properly that .getText() was not able to do in this situation.
Mine is python, but the core logic is similar:
webElement.text
webElement.get_attribute("innerText")
webElement.get_attribute("textContent")
Full code:
def getText(curElement):
"""
Get Selenium element text
Args:
curElement (WebElement): selenium web element
Returns:
str
Raises:
"""
# # for debug
# elementHtml = curElement.get_attribute("innerHTML")
# print("elementHtml=%s" % elementHtml)
elementText = curElement.text # sometime NOT work
if not elementText:
elementText = curElement.get_attribute("innerText")
if not elementText:
elementText = curElement.get_attribute("textContent")
# print("elementText=%s" % elementText)
return elementText
Calll it:
curTitle = getText(h2AElement)
hope is useful for you.
if you don't care about isDisplayed or scrolling position, you can also write
String text = ((JavaScriptExecutor)driver).executeScript("return $(arguments[0]).text();", element);
or without jquery
String text = ((JavaScriptExecutor)driver).executeScript("return arguments[0].innerText;", element);
Related to getText() I have also an issue and I resolved so:
WebElement errMsg;
errMsg = driver.findElement(By.xpath("//div[#id='mbr-login-error']"));
WebElement parent = driver.findElement(By.xpath("//form[#id='mbr-login-form']"));
List<WebElement> children = parent.findElements(By.tagName("div"));
System.out.println("Size is: "+children.size());
//((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView(true);", children);
for(int i = 0;i<children.size();i++)
{
System.out.println(i + " " + children.get(i).getText());
}
int indexErr = children.indexOf(errMsg);
System.out.println("index " + indexErr);
Assert.assertEquals(expected, children.get(indexErr).getText());
None of the above solutions worked for me.
Worked for me:
add as a predicate of xpath the length of string greater than 0:
String text = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//span[string-length(text()) > 0]"))).getText();