Skip to content

Commit 68595d2

Browse files
emanloveaaltat
authored andcommitted
Initial commit of additional patching for selenium 3 move_to bug.
First, I'll note my workaround is slightly different. Instead of catching attribute errors, I pass in both the driver and the element(s) checking first if this is indeed an EventFiringWebDriver and not Selenium 4 or greater. I did this because I didn't see the other try/catch method till after I wrote this. I can modify these to go that path. My one concern is that in all the additional places discovered which are affected I was worried that we might need multiple try/catch within a single method or one a large block of code. The other concern was that we may get a AttributError for other reasons. I added in acceptance tests (but no unit tests yet) for the additional changes. I copied pasted into the current selenium_move_to_workaround.robot test suite. This feels a little hackish to me and I would like to either copy paste into multiple test suites under a folder (still hackish). Or what I would really like to do is to use the existing test suites and accomplish this with tags and some mechanism to run with a differnt open browser setup. This may be too complicated for now (mostly in time to figure out that solution) so open for ideas here .. I have not yet tested with selenium 4 due to a bug I encountered when running the acceptance tests. Need to look at that now. Welcome any feedback...
1 parent 2ecf366 commit 68595d2

File tree

4 files changed

+148
-25
lines changed

4 files changed

+148
-25
lines changed

atest/acceptance/2-event_firing_webdriver/resource_event_firing_webdriver.robot

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@ ${REMOTE_URL}= ${NONE}
55
${DESIRED_CAPABILITIES}= ${NONE}
66
${ROOT}= http://${SERVER}/html
77
${FRONT_PAGE}= ${ROOT}/
8+
9+
*** Keyword ***
10+
11+
Go To Page "${relative url}"
12+
[Documentation] Goes to page
13+
Go To ${ROOT}/${relative url}
14+

atest/acceptance/2-event_firing_webdriver/selenium_move_to_workaround.robot

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,82 @@ Selenium move_to workaround Mouse Out
2222
Selenium move_to workaround Mouse Over
2323
[Documentation] LOG 1:5 DEBUG Workaround for Selenium 3 bug.
2424
Mouse Over id:some_id
25+
26+
Click Element
27+
[Documentation] LOG 2 Clicking element 'singleClickButton'.
28+
[Setup] Initialize Page For Click Element
29+
Click Element singleClickButton
30+
Element Text Should Be output single clicked
31+
32+
Double Click Element
33+
[Documentation] LOG 2 Double clicking element 'doubleClickButton'.
34+
[Setup] Initialize Page For Click Element
35+
[Tags] Known Issue Safari Known Issue Firefox
36+
Double Click Element doubleClickButton
37+
Element Text Should Be output double clicked
38+
39+
Click Element Action Chain
40+
[Tags] NoGrid
41+
[Documentation]
42+
... LOB 1:1 INFO Clicking 'singleClickButton' using an action chain.
43+
... LOG 2:5 DEBUG GLOB: *actions {"actions": [{*
44+
[Setup] Initialize Page For Click Element
45+
Click Element singleClickButton action_chain=True
46+
Element Text Should Be output single clicked
47+
48+
Mouse Down
49+
[Tags] Known Issue Safari
50+
[Setup] Go To Page "mouse/index.html"
51+
Mouse Down el_for_mousedown
52+
Textfield Value Should Be el_for_mousedown mousedown el_for_mousedown
53+
Run Keyword And Expect Error
54+
... Element with locator 'not_there' not found.
55+
... Mouse Down not_there
56+
57+
Mouse Up
58+
[Tags] Known Issue Safari Known Issue Firefox
59+
[Setup] Go To Page "mouse/index.html"
60+
Mouse Up el_for_mouseup
61+
Textfield Value Should Be el_for_mouseup mouseup el_for_mouseup
62+
Run Keyword And Expect Error
63+
... Element with locator 'not_there' not found.
64+
... Mouse Up not_there
65+
66+
Open Context Menu
67+
[Tags] Known Issue Safari
68+
[Setup] Go To Page "javascript/context_menu.html"
69+
Open Context Menu myDiv
70+
71+
Drag and Drop
72+
[Tags] Known Issue Internet Explorer Known Issue Safari
73+
[Setup] Go To Page "javascript/drag_and_drop.html"
74+
Element Text Should Be id=droppable Drop here
75+
Drag and Drop id=draggable id=droppable
76+
Element Text Should Be id=droppable Dropped!
77+
78+
Drag and Drop by Offset
79+
[Tags] Known Issue Firefox Known Issue Internet Explorer Known Issue Safari
80+
[Setup] Go To Page "javascript/drag_and_drop.html"
81+
Element Text Should Be id=droppable Drop here
82+
Drag and Drop by Offset id=draggable ${1} ${1}
83+
Element Text Should Be id=droppable Drop here
84+
Drag and Drop by Offset id=draggable ${100} ${20}
85+
Element Text Should Be id=droppable Dropped!
86+
87+
Mouse Down On Link
88+
[Tags] Known Issue Safari
89+
[Setup] Go To Page "javascript/mouse_events.html"
90+
Mouse Down On Image image_mousedown
91+
Text Field Should Contain textfield onmousedown
92+
Mouse Up image_mousedown
93+
Input text textfield ${EMPTY}
94+
Mouse Down On Link link_mousedown
95+
Text Field Should Contain textfield onmousedown
96+
Mouse Up link_mousedown
97+
98+
*** Keywords ***
99+
Initialize Page For Click Element
100+
[Documentation] Initialize Page
101+
Go To Page "javascript/click.html"
102+
Reload Page
103+
Element Text Should Be output initial output

src/SeleniumLibrary/keywords/element.py

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from typing import List, Optional, Tuple, Union
1818

1919
from SeleniumLibrary.utils import is_noney
20+
from SeleniumLibrary.utils.events.event import _unwrap_eventfiring_elements
2021
from robot.utils import plural_or_not, is_truthy
2122
from selenium.webdriver.common.action_chains import ActionChains
2223
from selenium.webdriver.common.keys import Keys
@@ -641,6 +642,7 @@ def _click_with_action_chain(self, locator):
641642
self.info(f"Clicking '{locator}' using an action chain.")
642643
action = ActionChains(self.driver)
643644
element = self.find_element(locator)
645+
element = _unwrap_eventfiring_elements(self.driver, element)
644646
action.move_to_element(element)
645647
action.click()
646648
action.perform()
@@ -656,6 +658,7 @@ def _click_with_modifier(self, locator, tag, modifier):
656658
element = self.find_element(locator, tag=tag[0], required=False)
657659
if not element:
658660
element = self.find_element(locator, tag=tag[1])
661+
element = _unwrap_eventfiring_elements(self.driver, element)
659662
action.click(element)
660663
for item in modifier:
661664
action.key_up(item)
@@ -675,14 +678,15 @@ def click_element_at_coordinates(self, locator, xoffset, yoffset):
675678
f"Clicking element '{locator}' at coordinates x={xoffset}, y={yoffset}."
676679
)
677680
element = self.find_element(locator)
681+
element = _unwrap_eventfiring_elements(self.driver,element)
678682
action = ActionChains(self.driver)
679683
# Try/except can be removed when minimum required Selenium is 4.0 or greater.
680-
try:
681-
action.move_to_element(element)
682-
except AttributeError:
683-
self.debug("Workaround for Selenium 3 bug.")
684-
element = element.wrapped_element
685-
action.move_to_element(element)
684+
#try:
685+
action.move_to_element(element)
686+
#except AttributeError:
687+
# self.debug("Workaround for Selenium 3 bug.")
688+
# element = element.wrapped_element
689+
# action.move_to_element(element)
686690
action.move_by_offset(xoffset, yoffset)
687691
action.click()
688692
action.perform()
@@ -696,6 +700,7 @@ def double_click_element(self, locator: str):
696700
"""
697701
self.info(f"Double clicking element '{locator}'.")
698702
element = self.find_element(locator)
703+
element = _unwrap_eventfiring_elements(self.driver, element)
699704
action = ActionChains(self.driver)
700705
action.double_click(element).perform()
701706

@@ -721,13 +726,14 @@ def scroll_element_into_view(self, locator: str):
721726
New in SeleniumLibrary 3.2.0
722727
"""
723728
element = self.find_element(locator)
729+
element = _unwrap_eventfiring_elements(self.driver, element)
724730
# Try/except can be removed when minimum required Selenium is 4.0 or greater.
725-
try:
726-
ActionChains(self.driver).move_to_element(element).perform()
727-
except AttributeError:
728-
self.debug("Workaround for Selenium 3 bug.")
729-
element = element.wrapped_element
730-
ActionChains(self.driver).move_to_element(element).perform()
731+
#try:
732+
ActionChains(self.driver).move_to_element(element).perform()
733+
#except AttributeError:
734+
# self.debug("Workaround for Selenium 3 bug.")
735+
# element = element.wrapped_element
736+
# ActionChains(self.driver).move_to_element(element).perform()
731737

732738
@keyword
733739
def drag_and_drop(self, locator: str, target: str):
@@ -741,6 +747,7 @@ def drag_and_drop(self, locator: str, target: str):
741747
| `Drag And Drop` | css:div#element | css:div.target |
742748
"""
743749
element = self.find_element(locator)
750+
element = _unwrap_eventfiring_elements(self.driver, element)
744751
target = self.find_element(target)
745752
action = ActionChains(self.driver)
746753
action.drag_and_drop(element, target).perform()
@@ -759,6 +766,7 @@ def drag_and_drop_by_offset(self, locator: str, xoffset: int, yoffset: int):
759766
| `Drag And Drop By Offset` | myElem | 50 | -35 | # Move myElem 50px right and 35px down |
760767
"""
761768
element = self.find_element(locator)
769+
element = _unwrap_eventfiring_elements(self.driver, element)
762770
action = ActionChains(self.driver)
763771
action.drag_and_drop_by_offset(element, xoffset, yoffset)
764772
action.perform()
@@ -777,6 +785,7 @@ def mouse_down(self, locator: str):
777785
"""
778786
self.info(f"Simulating Mouse Down on element '{locator}'.")
779787
element = self.find_element(locator)
788+
element = _unwrap_eventfiring_elements(self.driver, element)
780789
action = ActionChains(self.driver)
781790
action.click_and_hold(element).perform()
782791

@@ -789,17 +798,18 @@ def mouse_out(self, locator: str):
789798
"""
790799
self.info(f"Simulating Mouse Out on element '{locator}'.")
791800
element = self.find_element(locator)
801+
element = _unwrap_eventfiring_elements(self.driver, element)
792802
size = element.size
793803
offsetx = (size["width"] / 2) + 1
794804
offsety = (size["height"] / 2) + 1
795805
action = ActionChains(self.driver)
796806
# Try/except can be removed when minimum required Selenium is 4.0 or greater.
797-
try:
798-
action.move_to_element(element)
799-
except AttributeError:
800-
self.debug("Workaround for Selenium 3 bug.")
801-
element = element.wrapped_element
802-
action.move_to_element(element)
807+
#try:
808+
action.move_to_element(element)
809+
#except AttributeError:
810+
# self.debug("Workaround for Selenium 3 bug.")
811+
# element = element.wrapped_element
812+
# action.move_to_element(element)
803813
action.move_by_offset(offsetx, offsety)
804814
action.perform()
805815

@@ -812,14 +822,15 @@ def mouse_over(self, locator: str):
812822
"""
813823
self.info(f"Simulating Mouse Over on element '{locator}'.")
814824
element = self.find_element(locator)
825+
element = _unwrap_eventfiring_elements(self.driver,element)
815826
action = ActionChains(self.driver)
816827
# Try/except can be removed when minimum required Selenium is 4.0 or greater.
817-
try:
818-
action.move_to_element(element).perform()
819-
except AttributeError:
820-
self.debug("Workaround for Selenium 3 bug.")
821-
element = element.wrapped_element
822-
action.move_to_element(element).perform()
828+
#try:
829+
action.move_to_element(element).perform()
830+
#except AttributeError:
831+
# self.debug("Workaround for Selenium 3 bug.")
832+
# element = element.wrapped_element
833+
# action.move_to_element(element).perform()
823834

824835
@keyword
825836
def mouse_up(self, locator: str):
@@ -830,12 +841,14 @@ def mouse_up(self, locator: str):
830841
"""
831842
self.info(f"Simulating Mouse Up on element '{locator}'.")
832843
element = self.find_element(locator)
844+
element = _unwrap_eventfiring_elements(self.driver, element)
833845
ActionChains(self.driver).release(element).perform()
834846

835847
@keyword
836848
def open_context_menu(self, locator: str):
837849
"""Opens the context menu on the element identified by ``locator``."""
838850
element = self.find_element(locator)
851+
element = _unwrap_eventfiring_elements(self.driver, element)
839852
action = ActionChains(self.driver)
840853
action.context_click(element).perform()
841854

@@ -924,6 +937,7 @@ def press_keys(self, locator: Optional[str] = None, *keys: str):
924937
if not is_noney(locator):
925938
self.info(f"Sending key(s) {keys} to {locator} element.")
926939
element = self.find_element(locator)
940+
element = _unwrap_eventfiring_elements(self.driver, element)
927941
ActionChains(self.driver).click(element).perform()
928942
else:
929943
self.info(f"Sending key(s) {keys} to page.")
@@ -977,6 +991,7 @@ def mouse_down_on_link(self, locator: str):
977991
using ``id``, ``name``, ``href`` and the link text.
978992
"""
979993
element = self.find_element(locator, tag="link")
994+
element = _unwrap_eventfiring_elements(self.driver, element)
980995
action = ActionChains(self.driver)
981996
action.click_and_hold(element).perform()
982997

@@ -1019,6 +1034,7 @@ def mouse_down_on_image(self, locator: str):
10191034
using ``id``, ``name``, ``src`` and ``alt``.
10201035
"""
10211036
element = self.find_element(locator, tag="image")
1037+
element = _unwrap_eventfiring_elements(self.driver, element)
10221038
action = ActionChains(self.driver)
10231039
action.click_and_hold(element).perform()
10241040

src/SeleniumLibrary/utils/events/event.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,30 @@
1515
# limitations under the License.
1616

1717
import abc
18-
18+
from selenium.webdriver.support.event_firing_webdriver import EventFiringWebDriver
1919

2020
class Event:
2121
@abc.abstractmethod
2222
def trigger(self, *args, **kwargs):
2323
pass
24+
25+
def _unwrap_eventfiring_elements(ef_driver,elements):
26+
""" Workaround for Selenium 3 bug.
27+
28+
References:
29+
https://github.com/SeleniumHQ/selenium/issues/7877
30+
https://github.com/SeleniumHQ/selenium/pull/8348
31+
https://github.com/SeleniumHQ/selenium/issues/7467
32+
https://github.com/SeleniumHQ/selenium/issues/6604
33+
34+
"""
35+
if not isinstance(ef_driver,EventFiringWebDriver) or selenium_major_version() >= 4:
36+
return elements
37+
unwrapped_elements = ef_driver._unwrap_element_args(elements)
38+
return unwrapped_elements
39+
40+
def selenium_major_version():
41+
import selenium
42+
selenium_version = selenium.__version__
43+
(major,*sub_versions)=selenium_version.split('.')
44+
return int(major)

0 commit comments

Comments
 (0)