I have an issue and I'm quite new with protractor.
I need to get an element by its text, right now it is not possible to change how the UI is built to use better selectors.
So what I have right now is a span tag with the text Summary inside of it, to retrieve the element using XPath I do the following:
const myElement = element(by.xpath("//span[text()='Summary']"));
That works for the first occurrence when there's only one element on the screen, however, when there are two elements, it fails with the following error:
Failed: element not interactable
Possibly because it is trying to access the first element which is toggled.
So I tried accessing the element index as I read around with:
element(by.xpath("//span[text()='Summary']")[1]);
And got the following error:
Failed: Invalid locator
I read somewhere that the values start on 1 and not on 0 so I tried with:
element(by.xpath("//span[text()='Summary']")[2]);
Yet, I'm still getting the same error:
Failed: Invalid locator
Is there a way I can get to these second element?
When you are using list slicing then there exist more then one elements. So you can try to use elements instead of element
element(by.xpath("(//span[text()='Summary'])[2]");
OR
element(by.xpath("(//span[contains(text(),'Summary')])[2]");
You can try this XPath, it has additional brackets, you have been almost there.
(//span[text()='Summary'])[2]
Reference:
XPath query to get nth instance of an element
Related
PROBLEM:
I am having an issue to identify an element in Appium.
As I can't identify the element, I managed to identify by xpath the next element. Let's call it "FOUND" element.
SO now I try to get the previous element from this element "FOUND".
DETAILS:
In this screenshot above, you can see the elements I am speaking about.
To find the "FOUND" element, I am looping in all the element with the class "android.widget.TextView", I extract the attribute 'text' and compate it to the string 'Website'.
Then from the element FOUND, I try to find the element I need. I tried so many various expression, but I didn't succeed to get it. I use a "try, except" to try to cath it, but without success.
here is the code:
elements_of_profile_detail_page = driver.find_elements_by_class_name("android.widget.TextView")
list_xpath=[
"preceding-sibling::android.widget.TextView[1]",
"preceding-sibling::android.widget.TextView[1]",
"(/preceding-sibling::android.widget.TextView)[1]",
"/*preceding-sibling::android.widget.TextView[1]",
"(/*preceding-sibling::android.widget.TextView)[1]",
"(preceding-sibling::android.widget.TextView)[1]",
"../android.widget.TextView[0]",
"preceding-sibling::*[1]",
"/preceding-sibling::android.widget.TextView",
"preceding-sibling::android.widget.TextView",
"(preceding-sibling::android.widget.TextView)[1]"
]
i=0
while i<len(list_xpath):
try:
website = element_of_profile_detail_page.find_element_by_xpath(list_xpath[i]).get_attribute('text')
print(f"website : {website}")
print(f"xpath : {xpath}")
break
except:
print("It didn't work!")
i+=1
And here is another screenshot with more details of the element I need:
I am using Appium 1.15.1 and Python 3.7. I don't think it is important as it is a matter of Xpath.
I hope I gave enough details to find the solution. I am working on it since very early this morning.
You can directly find the element by using its text in the xpath like:
element = driver.find_element_by_xpath("//*[contains(#text,'AlfangeAcademy')]")
i have dynamic elements in my android app and there is nothing to find it out .Please check screen shot of my app and attributes and let me how can we do it.
I have tried with the given attributes
I just want ti find these elements and send keys
Try find element by xpath with this value:
//*[contains(#class,'android.widget.EditText')]
It will return the first element if there are many elements with same class.
If you want other element with class EditText, you can add count like this:
(//*[contains(#class,'android.widget.EditText')])[2]
The above for second element.
I tried this way of finding element:
List name = driver.findElements(By.xpath("android.widget.EditText"));
name.get(0).click();
But i am getting bellow error:-
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
Please let me know what is the issue?
I found one of my dynamic element through this method :-
findElementByXPath("//android.widget.FrameLayout[#index='0']/android.widget.EditText[#index='0']")
but for second element also , these details are same, so if i am putting same method to find second element , it search the first one only.
Than i printed size of the element with this find method
Size is coming like this
(996, 89)
Please let me know how can i find second element , because it has same details.
I'm working through Selenium Webdriver, and I've come up to the issue of dynamic objects as a DOM ID. One of my instances gets generated as an ID, something like this:
"//*[#id="888itsAnExampleBoi573"]/div[1]/div[2]",
and I need to click on the button in the example item to Make Stuff Happen.
Because I cannot predict what an objectID will be for my dynamic content, however, I would like to be able to do this, instead:
//*[contains(text(), 'example')]/div[1]/div[2].
I've tried to do this, but I'm returned a strange error:
Caused by: org.openqa.selenium.InvalidSelectorException: invalid
selector: Unable to locate an element with the xpath expression
//*[contains(text(), 'example')]/div/div/div[1]/div[3]/div
because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document':
The string '//*[contains(text(), 'example')]/div/div/div[1]/div[3]/div'
is not a valid XPath expression.
On a different element that is a hyperlink with text elements, I've been able to use contains(text()) to solve things, so I believe I've formatted this correctly.
I've tried a few different things to solve this issue, but am at somewhat of a loss as to how to solve this. Does anyone have any ideas or resources to point me towards? Or better yet, a solution?
This error message...
Caused by: org.openqa.selenium.InvalidSelectorException: invalid selector: Unable to locate an element with the xpath expression //*[contains(text(), 'example')]/div/div/div[1]/div[3]/div because of the following error: SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//*[contains(text(), 'example')]/div/div/div[1]/div[3]/div' is not a valid XPath expression.
...implies that the Locator Strategy is not a valid XPath expression.
The expressions:
'//*[contains(text(), 'example')]/div/div/div[1]/div[3]/div'
"//*[contains(text(), "example")]/div/div/div[1]/div[3]/div"
Are invalid as '' and "" were present in multiple places within the xpath.
Solution
As an effective alternative dynamic xpath for the following:
"//*[#id="888itsAnExampleBoi573"]/div[1]/div[2]"
will be:
"//*[contains(#id,'itsAnExampleBoi')]/div[1]/div[2]"
It appears that in order to solve this, sometimes you must frame the question. As I had been using a relative XPATH, I had been working under the pretense that the text div itself was where I would be able to access elements that were not the children of my div. They were actually only loosely related!
"//*[contains(text(), 'Flag this')]
//parent::div
//parent::div[contains(#class,'exampleDrop')]
//child::div[contains(#class, 'pointed exampleAction')]"
I ended up installing Chropath and spidering around the DOM, finding the div with the text in it, and using a relative path in this statement. If you're having issues like these, sometimes I would recommend making sure that you're asking the right question.
I am tring to find a button in a webpage using find elements, the page can contain one of the below button ID's.
driver.findElements(By.xpath("//*[contains(#id,'topBtn')]"))
driver.findElements(By.xpath("//*[contains(#id,'WSMplasticTop')]"))
driver.findElements(By.xpath("//*[contains(#id,'bottomApplyBtn')]"))
The above code is working as expected when i use the Firefox Driver, where as getting the below error when i run in Chrome Driver.
org.openqa.selenium.InvalidSelectorException: invalid selector: Unable to locate an element with the xpath expression //*[contains(#id='bottomApplyBtn')] because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//*[contains(#id='bottomApplyBtn')]' is not a valid XPath expression.
Just wanted to know whether i have done any mistake
Try to use
'//*[contains(#id,'bottomApplyBtn')]'
instead of
'//*[contains(#id='bottomApplyBtn')]'
When you are using contains method in your XPath expression, you basically are using an inbuilt method to find the element.
This method takes 2 parameters.
First the tag you in which you want to search.
Second is the actual text value which you are looking for inside the above tag.
Basically you have to call the method with 2 parameters and that 2 parameters should be comma separated.
So //*[contains(#id='bottomApplyBtn')] is wrong you should instead remove this = sign.
//*[contains(#id, 'bottomApplyBtn')]
|_______|____________________ Parameter 1
|__________________________________Parameter 2
Hope it helps!
I am trying to validate xpath expression and if it is true click element .Following is the code that I am trying to do .
Xpath_combined variable returns Boolean : true . Please help me in correcting the syntax or valid expression
Variable
${xpath_combined} //div[text()='00:04:56:AC:41:F6'] AND //div[contains(text(),'Device-77')]
Keyword
Run keyword if ${xpath_combined} == "true" Click Element //i[#class='fa fa-lg fa-file-text-o grow']
Error from console output
Evaluating expression '//div\[text()='00:04:56:AC:41:F6'\] AND //div\[contains(text(),'Gambit-77')\] == "true"' failed: SyntaxError: invalid syntax (<string>, line 1)]
You can create different scenarios how to solve this question. But, you can try this solution:
Xpath = With xpath, find the the parent element which contains both elements. But this depends on your code structure f.e. Try to find body element, with two child elements containing specific text conditions:
xpath=//body[//div[text()='00:04:56:AC:41:F6'] AND //div[contains(text(),'Device-77')]]
Set variable the right way or use scalar. Note: we will use Get Matching Xpath Keyword, so we don't need to use 'xpath=' prefix
${xpath_combined}= Set Variable //body[//div[text()='00:04:56:AC:41:F6'] AND //div[contains(text(),'Device-77')]]
Get Matching Xpath Count It will return 1 occurence of xpath. There is only one body element which passes the xpath expression
${count}= Get Matching Xpath Count ${xpath_combined}
Run Keyword If If the xpath count is exactly 1 time, the elements are present on the page and you are allowed to click on icon. Note: don't forget to add xpath= prefix to Click Element locator
Run keyword if ${count} == 1 Click Element xpath=//i[#class='fa fa-lg fa-file-text-o grow']
Though the other solution is fully viable one, here's an alternative which is an it more universal.
It combines two keywords - Get Webelement which returns a selenium object if it exists, and Run Keyword And Return Status - which returns True if a keyword succeeds, False otherwise:
${locator}= Set Variable //body[//div[text()='00:04:56:AC:41:F6'] AND //div[contains(text(),'Device-77')]]
${target}= Set Variable //i[#class='fa fa-lg fa-file-text-o grow']
${the element is present}= Run Keyword And Return Status Get Webelement ${locator}
Run Keyword If ${the element is present} Click Element ${target}
Another benefit is that you are not constrained by an xpath locator - it'll work with css, id or whatever other strategy.
Alternatively, one could use Element Should Be Visible instead of Get Webelement, but that works only for elements actuaĺly visible, not just present in the DOM.