Selenium ActionChains when a required element does not exist yet - python

Is it possible to create an action chain in selenium if one of the required elements will not exist until the action chain begins executing?
For example, I am trying to perform a drag and drop in selenium. The catch is that the target of the drop only exists while a drag is occurring. The intuitive solution for a drag and drop seems to be doing:
source = driver.find_element(...)
target = driver.find_element(...)
ActionChains(driver).drag_and_drop(source, target)
This will not work because target does not exist until a drag has begun.
I have tried doing something along the lines of:
source = driver.find_element(...)
drag_and_drop = ActionChains(driver)
drag_and_drop.click_and_hold(source)
drag_and_drop.move_by_offset(10, 10)
drag_and_drop.perform()
target = driver.find_element(...)
drag_and_drop.move_to_element(target)
drag_and_drop.release()
drag_and_drop.perform()
This also does not work. It seems like the mouse is released after the first perform which would cause the target to disappear. This seems to indicate that a single action chain with a single perform() call would be needed. I have tried researching to see if there is any way to lazily find an element when its step of the action chain is needed, but I could not find any way to do that.
Is there any way to achieve something like this in selenium?

This is actually a case of misdiagnosing the problem. The root issue actually lies in selenium not currently supporting native HTML5 drag and drop, which is better explained in this answer. So whether or not the required element exists, neither of the examples given would work for that purpose, even if they seem like they should.
With the issue of the element not existing at the start of the action chain the solution is actually to break it up into multiple sections with multiple perform() calls as shown in the second example. Again, the conclusion drawn in the question that multiple perform() calls does not work was inaccurate and a result of misunderstanding the true problem.

Related

Selenium Python not finding the element

I'm trying to click on some element but it's not working:
driver.find_element_by_xpath("//span[text()='ENG']")
When I add:
driver.maximize_window()
before click action, it works, other codes are not working again.
I had similar problem
When I was looking for an element, it was not yet available in the code.
Fixed by adding
driver.implicitly_wait(30) ## 30 is the time he will wait
before searching for the element.
This line makes the code wait until the entire page is loaded before looking for an element.
I'm trying to click on some element via driver.find_element_by_xpath("//span[text()='ENG']"), but it's not working,
You need to post logs or be more specific. Are you getting an error on the call to find_element_by_xpath(), or when you call click as you mention below?
when I add driver.maximize_window() before click action, it works,
other codes are not working again, please advise which can be the
reason
The relevant code needs to be provided. I believe you're saying that when you call maximize_window() before you locate the element, it works, but if you don't call maximize window, it fails. This could be for a variety of reasons, but it sounds Javascript related. A similar question like this this could help. If maximize window doesn't actually help the issue, I would look into implicit waits or WebDriverWaits.

How do I tap coordinates inside of a specific element with selenium TouchActions python?

The Selenium ActionChains module includes the ability to move to an element with offset provided an x and y coordinate like so:
ActionChains(browser).move_to_element_with_offset(x-offset, y-offser).click().perform()
Which is useful to test responsiveness of elements nested inside other elements such as a react element.
The Selenium TouchActions module includes something similar except the coordinates are relative to the viewport. My TouchActions script looks like this:
TouchActions(browser).tap_and_hold(x-offset, y-offset).release(x-offset, y-offset).perform()
This script does not activate the expected event for me; however, this script does:
element = browser.find_element_by_XPath(//img)
TouchActions(browser).tap(element).perform()
The tap occurs at the center of the element, which is useful; however, I need the ability to repeat the tap again at different parts of the element to test for the event.
ADDITIONAL NOTE:
The expected events can be fired manually.
It turns out that the implementation of the app i was working on had a feature that was accessible via the native os version, but not via its web version.
This question could have been solved easier if i had provided details of the specific application I was trying to test.
The provided uses of Selenium in the question work fine. Here's the documentation

How can I avoid inconsistent behavior with Selenium StaleElementReferenceException (Python)?

I'm working on a bit of automation that basically opens YouTube, plays a particular video, then opens the "Stats for Nerds" dialog and grabs the info from it. This was working yesterday. Today, I added lines to set the video to 1080p, then go into full screen, and now it fails to work.
The following line works:
driver.find_element_by_id("movie_player").click()
While this set fails, throwing a StaleElementReferenceException:
element = driver.find_element_by_id("movie_player")
actions.move_to_element(element)
actions.context_click(element)
actions.perform()
Nothing I have done can avoid this. I've tried putting it in a try block, with and without some waits thrown in. Somehow the element is going stale in the very short time between finding and setting the element, and performing the context_click action.
Is there any way of getting around this?
Edit: I'll keep checking back in to see if someone knows a better way to do this, but for now, in the interest of expediency, I've just kludged it by using pymouse to actually take control of the mouse and right click.
I suspect the DOM changes if you mouse over the button. To workaround it, "refind" the element:
element = driver.find_element_by_id("movie_player")
actions.move_to_element(element).perform()
element = driver.find_element_by_id("movie_player")
actions.context_click(element).perform()

Python Selenium WebDriverWait and Click inconsistently giving StaleElementReferenceException()

Ok, here goes my attempt to explain this problem that I haven't even figured out for myself yet. I'm using Selenium with the python-bindings and seem to have an issue with a page element randomly not being found when when using WebDriverWait followed by a click() event. Here is my code:
yearOption = WebDriverWait(self.br, 40).until(lambda d: d.find_element_by_xpath("//select[#name='ctl00$holdSection$rptCommissionYears']/option[#value='%s']" % year), self.br)
print yearOption.text
yearOption.click()
This command set is in a for loop and will randomly fail on the .click() event producing the error: StaleElementReferenceException() after the yearOption.text is printed. This is completely odd to me since the WebDriverWait line obviously found the element, and I haven't reloaded or changed the browser state before clicking the element...
Any ideas why I would be getting this error? Remember, it doesn't happen consistently, infact--sometimes, my entire script will execute successfully with no errors.
I have run into a similar issue before, and I am 99% sure that your problem is the same.
If you check your loop is:
Look for this element
Click
Look for same element
CLick
Normaly after a Click, some page reload or changes occur. This may affect to the element that you are searching for. And if you don't take care, you may end up looking for the element before is reloaded, and when you click it, the element ID already changed, therefore giving you a Stale exception.
Lets go one by one:
Page loads and you element has ID=1
You find it.
You click it and reload/changes start to happen
You enter another loop and find the element. Notice that this even
can happen really fast as there is no wait after click, and thus
find can exit giving you ID=1 element again. You try to click the
element ID=1, but since it was reloaded, it does not exist anymore.
You can fix this in different ways:
If speed is not an issue, you can add an explicit wait after click
of a few seconds, giving enough time to javascript to finish.
You can save the ID of the element, and every time you look for it,
you check that is different, and if it is not, you wait and retry.
Giving this, if that is not your problem, you can always share more of your code and your testing target and I would be happy to help.

AuiNotebook - Get clicked tab

I am currently using some wxPython's AuiNotebook in one of my projects and I have a problem that can't manage to solve. I think there should be a simple solution but can't manage to find it.
I have created a new class derived from wx.lib.agw.aui.AuiNotebook and I am trying to get the index of a tab at the moment it's clicked. I wrote something like that:
class NewNotebook(wx.lib.agw.aui.AuiNotebook):
# __init__ function an stuff...
def OnTabClicked(self, evt):
index = self.GetSelection()
print index
wx.lib.agw.aui.AuiNotebook.OnTabClicked(self, evt)
The aim was to capture the index of the tab clicked on and in some cases, have a special behavior, or just perform a regular click otherwise. However, I think that AuiNotebook.OnTabClicked actually changes the selection among different things. It would explain why index contains the value of the tab that was selected before the click.
I did not a find a way to get the selection of the new tab though. I looked for some information in the captured event but still could not find the one I wanted.
So, does someone know how I can get the selected tab before I call AuiNotebook.OnTabClicked?
There doesn't seem to be a builtin way to do this. The closest I found was something I helped with on the wxPython mailing list, but that had to do with double-clicking.
Here's one workaround that came to me though. When you first show the frame, set some kind of class property to the currently shown tab (i.e. self.currentTab = 0). Then catch the EVT_AUINOTEBOOK_PAGE_CHANGING or EVT_AUINOTEBOOK_PAGE_CHANGED event and update the property. For me, when I catch EVT_AUINOTEBOOK_PAGE_CHANGING, I always get the index of the tab I'm clicking on, at least on Windows.

Categories