I would like to know if there is a way to get locator for any text in robot framework ? I am using Robot Framework with Selenium2Library.
Scenario example : Suppose I have message "Hello" on my page and its position keeps on changing when new message appears.I want to click on this "Hello" word to show complete message. How can I do that. Please help.
I've seen locations change a lot with Angular webpages, so I understand what you mean. IDs can be generated anew every time the page loads and may change depending on the order in which you click on elements. Worse, they can affect dom- and xpath-based locators as well. The short answer to your question is no, it doesn't exist within standard Selenium, Selenium2, ExtendedSelenium2, or any other standard library.
The medium answer to your question is solved in my currently-most-advanced Click Element by Text custom keyword. It generates an xpath based on your inputs and if it can be found with a simple text search with no extra parameters, it'll do it. It is testy at times and may require argument injections to work, but in general it works very well and is easy to use when xpaths are remotely possible.
Click Element by Text
# EXAMPLE USAGE
# Click Element by Text "text on the element" id="midlevellocationoftext" button
# NOTE: Does not account for extra spaces at the beginning or end, text must be exact
# NOTE: Allows for injections on purpose to allow user to be more exact with their location
[Arguments] ${text} ${location}=* ${elementtype}=*
Click Element xpath=//*[#${location}]//${elementtype}[text()=${text}]
The long answer is that I'm working on something better. Here's what I know so far. The elements to do this do exist out there in the void. JavaScript can turn a webpage into a list of elements. I can call .innerHTML on those elements to get their text. I haven't worked out the details, but I honestly think it's possible and when I get it figured out, the code will be on Code Review for others to see.
Related
I am working on a program that auto-completes questions. But the answers to the questions are choices and they will change every time.
There are four choices and I only want it to click one of them.
This work but the text will change every time: driver.find_element_by_xpath("//p[contains(text(),'The home of a person/ company.')]").click()
I have tried this: driver.find_element_by_class_name("choices").click() and it won't work.
So, I want no matter what the text part is, the program can search and click on it. But only clicking one of the choices.
Picture of the website with html
HTML:<p class="choices" xpath="1">The home of a person/ company.</p>
xpath of this://p[contains(text(),'The home of a person/ company.')]
absXpath:/html[1]/body[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[3]/div[1]/div[3]/div[1]/label[4]/p[1]
Please help.
first check wheather you are using correct xpath because the xpath changes as the position of options are changed. Also, according to your code you can use specific id for this problem because class can be provieded for multiple elements but id is unique.
To click the first option use css selector:
driver.find_element_by_css_selector(".tbtow.exercise_frame>.each_question.mc_question>label:nth-child(1)>p")
Check classes spelling by yourself because I typed them from the picture you provided. Also, experiment with :nth-of-type(1) instead of :nth-child(1)
To change position use :nth-of-type(2), :nth-of-type(3) and so on.
So I've been trying to search for specific keywords on a webpage using selenium in python, but can't seem to figure out how to search for specific text in a specific area. As shown in the picture, when I search the word "Sim" in chrome, several spots are highlighted. The red region is the only place I am looking for code in. I've using the xpaths to identify the text, as nothing else is available for them.
This is the code so far:
else:
print("Nothing here yet 1")
if driver.find_elements_by_xpath("//*[contains(text(), 'Sim')]"):
login_to_reply = driver.find_element_by_xpath("//body/div[#id='app']/main/div[#id='content']/div/div/div/div/div/div/article/header[1]")
login_to_reply.click()
time.sleep(5)
if anyone could help and let me know what I'm not understanding, I would really appreciate that, thank you.
Based on the additional information in the comments, to search for keywords in the FIRST POST on the page you can use the following xpath:
(//article)[1]//div[#class='Post-body'][contains(normalize-space(),'point')]
The key bit is: (//article)[1] - it's locking the further identifiers to within the first [1] located article tag. The rest just reduces repetition within the dom and finds your text whoever the nested tags are strucutred.
Based on the link provided, that matches the top post only. You can see searching for keyword "point" only gets 1 hit even though it's in multiple posts...
The text 'point' can be swapped out for 'sim' or whatever you want to filter.
Looking at you code, i have some more suggestions:
1/
Your second xpath for "login to reply" is not great. Long copied xpaths like that are typically flakey and troublesome. You can use the same technique as above to click the reply within that article box:
(//article)[1]//button[span[text()='Reply']]
2/
You also need to be aware that this line won't work as you expect.
if driver.find_elements_by_xpath("//*[contains(text(), 'Sim')]"):
If the element is not found, it does not return false - it returns a NoSuchElement exception and fails (and stops) the script.
You need this to be a try/except block
It would need to look like this:
try:
driver.find_elements_by_xpath("(//article)[1]//div[#class='Post-body'][contains(normalize-space(),'point')]"):
login_to_reply = driver.find_element_by_xpath("(//article)[1]//button[span[text()='Reply']]")
login_to_reply.click()
time.sleep(5)
except:
print("Text was not found")
I've not run this but if it doesn't work let me know and i'll look again.
I should start by saying that I'm not a web developer but I have been using Selenium with Python for a few weeks and think I've gotten the basics down.
What I have is a page with a weekly calendar on it. Image as follows:
What happens is that you can click on any of the coloured boxes which will bring up a register for a class. It features items that you can click on which bring up new information. The problem I have is that I can't click on the items - or, rather, I don't know how to automate the click. I have automated clicking with Selenium before in other situations.
That looks as follows:
As you can see, the calendar still appears in the background. That is to say, the item we click on doesn't take us to a new page but, I suppose, runs some kind of method which shows the register and populates it with data.
My problem is this: I want to automate the process so that I can click on each of these items then scrape the information. In order to do that I need to be able to automate the clicking for each of the items.
So what have I done? When I've done this before, I've searched through the web html for the relevant part and then grabbed the xPath to the element I needed. But here I can't do that. Why not? Well, firstly, I just can't find that element!
Take a look at this close up of the first column:
It's divided into columns, but then I'd expect the clickable area to be an element within that. As you can see, it's not. Furthermore, the clickable area is just the coloured box itself, but if you look closely you can see the element goes outside of that area. I have gone very close with my mouse cursor to see exactly what's clickable, and it definitely is just the coloured box.
So I've not been able to get the element at all.
I thought I might be able to just find out where we went after I clicked the button, but when I got the link address, it just said it was the same page with no differences.
I appreciate I'm asking quite a broad question here, but the problem is that I don't really know where to start. If someone could give me at least that much, I would be grateful. Like if I could just click on each of these one at a time... I've found where the populated data is so I could grab that without a problem.
Well, here's to hoping.
Edit: I should add that there are some JavaScript items (tag type script, type='text/javascript'). I presume that the answer is in there somewhere, but there is a lot of Javascript and I'm not adept at reading it. It's hard for me to tell what script does what. If I could at least figure out what script runs when I click the item then I think I'd be onto something, but I have no idea. Even that would help me.
I had encountered similar problem when scraping for Instagram followers in mobile view where it was floating box when showing the accounts followers name. The approach I took was identifying the name of floating dialog box and clicking the element in it. It might different in your case of html.
Trying looking at this link. Selenium Scroll inside of popup div
Hard to say without the HTML. Maybe try Katalon Recorder (chrome extension) and see if that can detect the xpath for you? It might also be you have to use some kind of javascript to invoke the method for the element
I've been creating a tool that plays through an online game using python 2.7 and selenium, and am very stuck on one particular element I need to select.
The UI looks as follows:
1 2 3
a d g
b e h
c f i
The numbers one two and three represent a drop down menu, which when clicked open up the letters. Each option represents a different outcome. The problem is, at the start of each game the positions of both the numbers and letters are randomized. In the code, each button's css selector is labeled as for example "#action-1 > button:nth-child(1)", as in the "first button", but the "first button" will be different every game.
I've tried finding by link text, xpath, and css selector to no success.
If it helps, pressing "copy outer html" gives this:
<button class="ng-binding" ng-click="subBtn($event)" ng-class="{disabled : !state.chapterStart || state.btns.indexOf(btn.action) != -1}" ng-disabled="!state.chapterStart || state.btns.indexOf(btn.action) != -1">Wait and See What They Do</button>
The "Wait and See What They Do" part of it is what the button says and is how you know what to click, but I can't seem to find the element by that.
Copying the xpath results in //*[#id="action-1"]/button, which again isn't really helpful because telling it to click that would just be like saying "click the button that is in the first position", and it changes every time. I've added long time.sleep() commands to test, the page is definitely loading all the way so that is not the issue.
Anyways, I've been trying to figure this one out for way too long and it has me stumped. I'd be very grateful for any input you all can give. Thank you!
If you are looking to locate an element by the text it contains you can use XPath. You stated that you tried XPath but no specifics were given. Did you try the below? It should work given the HTML you provided.
//button[text()='Wait and See What They Do']
To read this XPath... find any descendant // that is a BUTTON tag that has an attribute [] where the text contained in the element is equal to the search string, text()=''.
Another example might be the below which is an alternate way to find your button. The problem with this way is that there may be many buttons on the page with that class so it may not be specific enough.
//button[#class='ng-binding']
I've found (and others have also) that XPaths are generally slower than other location methods. Because of this, I generally prefer By.Id, when available, then By.CssSelector. They are both significantly faster than XPath. I save XPath for things like finding text in an element or finding relative elements (CSS can do this some but is no where near as powerful as XPath).
XPath Examples
I'm using Qwebview with Pyside/Qt to view an HTML page on a GUI I'm working on.
I need the possibility to add a search text function, otherwise it is useless for the purpose the GUI is made.
I've searched but I didn't find anything useful for build a code that search the text and scrolls down the page as it is made in the common browsers.
The only function I found is findText but it returns a boolean and I cannot see how it can be useful.
Do somebody have an hint / advice / guide or code for this request?
Thank you.
Okay, so it turns out that i had an example of this using a QTextBrowser, which has a lot of this built into utility functions.
You can still do it with a QWebBrowser though.
Bind ctrl-f to open a search panel, and then make it so that the search box sends out two signals;
(presuming it's a QLineEdit), returnPressed, and textChanged.
Each of them then calls findText on the QWebPage object.
The important part is setting the correct flag in the findText call (which you'll want to set with checkboxes in your search functionality, i'd say).
You set the flags so that HighlightAllOccurrences is not set.
I cannot see any way to get details on a selection. Are you sure that when you do not set the HighlightAllOccurences flag it does not scroll to the next selection automatically?