web-dev-qa-db-fra.com

Molette de la souris avec le WebDriver Selenium, sur un élément sans barre de défilement?

J'essaie de piloter une partie d'une carte Web similaire à Google Maps, où le zoom avant/arrière est effectué en faisant défiler la souris. Idéalement, j'aimerais pouvoir faire quelque chose comme ceci:

someElement.scroll(-50)

Les méthodes les plus proches que j'ai vues dans la documentation étaient click et send_keys, mais aucune de celles-ci ne défile. J'ai également essayé d'envoyer des parchemins à la page via Javascript, par exemple. driver.execute_script("scroll(0,-50)") Cela ne semble cependant pas faire grand chose.

Comment puis-je faire ceci?

9
Claire Nielsen

Pour reproduire/tester une molette de souris, vous devez émettre les événements mouseover, mousemove et wheel vers l'élément supérieur avec une injection de script.

Voici un exemple de travail avec Google Map:

from Selenium import webdriver
from Selenium.common.exceptions import WebDriverException

def wheel_element(element, deltaY = 120, offsetX = 0, offsetY = 0):
  error = element._parent.execute_script("""
    var element = arguments[0];
    var deltaY = arguments[1];
    var box = element.getBoundingClientRect();
    var clientX = box.left + (arguments[2] || box.width / 2);
    var clientY = box.top + (arguments[3] || box.height / 2);
    var target = element.ownerDocument.elementFromPoint(clientX, clientY);

    for (var e = target; e; e = e.parentElement) {
      if (e === element) {
        target.dispatchEvent(new MouseEvent('mouseover', {view: window, bubbles: true, cancelable: true, clientX: clientX, clientY: clientY}));
        target.dispatchEvent(new MouseEvent('mousemove', {view: window, bubbles: true, cancelable: true, clientX: clientX, clientY: clientY}));
        target.dispatchEvent(new WheelEvent('wheel',     {view: window, bubbles: true, cancelable: true, clientX: clientX, clientY: clientY, deltaY: deltaY}));
        return;
      }
    }    
    return "Element is not interactable";
    """, element, deltaY, offsetX, offsetY)
  if error:
    raise WebDriverException(error)

options = webdriver.ChromeOptions()
options.add_argument("--disable-infobars --disable-extensions --window-size=1366,768")
driver = webdriver.Chrome(chrome_options=options)
driver.get("https://www.google.co.uk/maps")

# get element
Elm = driver.find_element_by_css_selector("#scene > div.widget-scene > canvas")

# zoom in with mouse wheel
wheel_element(Elm, -120)

# zoom out with mouse wheel
wheel_element(Elm, 120)

Vous pouvez également envoyer les raccourcis de zoom +/- avec Google Map:

# get element
Elm = driver.find_element_by_css_selector("#scene > div.widget-scene > canvas")

# zoom in with shortcut
Elm.send_keys("+")

# zoom out with shortcut
Elm.send_keys("-")
8
Florent B.

Sur google map, il y a un bouton de zoom avant/arrière. Vous pouvez l'utiliser à la place du défilement de la souris.

// Cliquer sur le zoom avant

driver.find_element_by_id('widget-zoom-in').click()

// Cliquer sur le zoom arrière

driver.find_element_by_id('widget-zoom-out').click()
0
Murthi

Vous pouvez l'essayer avec la classe PyRobot, commencez par vous concentrer sur les points sur lesquels vous souhaitez effectuer un zoom avant/arrière, puis utilisez la classe PyRobot pour effectuer une opération de zoom avant/arrière à l'aide des touches du clavier. 

0
Sonali Khaladkar

La bonne réponse de Florents pourrait être améliorée légèrement en externalisant l'extrait de code JS dans un fichier séparé et en l'enveloppant dans le format de module JS de style ancien avec des noms de paramètres lisibles.

Un fichier appelé par exemple simulate_wheel.js avec:

/* global arguments */
(function (element, deltaY, offsetX, offsetY) {
    var box = element.getBoundingClientRect();
    var clientX = box.left + (offsetX || box.width / 2);
    var clientY = box.top + (offsetY || box.height / 2);
    var target = element.ownerDocument.elementFromPoint(clientX, clientY);

    for (var e = target; e; e = e.parentElement) {
        if (e === element) {
            target.dispatchEvent(new MouseEvent("mouseover", {
                view: window,
                bubbles: true,
                cancelable: true,
                clientX: clientX,
                clientY: clientY
            }));
            target.dispatchEvent(new MouseEvent("mousemove", {
                view: window,
                bubbles: true,
                cancelable: true,
                clientX: clientX,
                clientY: clientY
            }));
            target.dispatchEvent(new WheelEvent("wheel", {
                view: window,
                bubbles: true,
                cancelable: true,
                clientX: clientX,
                clientY: clientY,
                deltaY: deltaY
            }));
            return "";
        }
    }
    return "Element is not interactable";
}).apply(null, arguments);

Qui peut ensuite être lu et utilisé ce qui suit

# Load it using the module loader, the module in this example is called "helper_js"
# Alternatively, simple read functions could be used
import pkgutil
wheel_js = pkgutil.get_data("helper_js", "simulate_wheel.js").decode("utf8")

def simulate_wheel(element, deltaY=120, offsetX=0, offsetY=0):
    error = element._parent.execute_script(wheel_js, element, deltaY, offsetX, offsetY)
    if error:
        raise WebDriverException(error)

Ceci est similaire à la situation dans les liaisons Selenium pour Python .

0
phk