From 07a149bde4d499212f9b57373b0284f4945bff57 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Mon, 1 Dec 2025 09:43:01 -0500 Subject: [PATCH] [IMP] script selenium lib: support specific directory for selenium grid - fix algorithm scrollto_element, center it, not scroll if already in view if not too low --- script/selenium/selenium_lib.py | 72 ++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/script/selenium/selenium_lib.py b/script/selenium/selenium_lib.py index 16e66c5..d268544 100644 --- a/script/selenium/selenium_lib.py +++ b/script/selenium/selenium_lib.py @@ -4,18 +4,15 @@ import datetime import getpass -import json import logging import os import random import re -import shutil import subprocess import sys import tempfile import time import tkinter as tk -from subprocess import getoutput from tkinter import filedialog from pykeepass import PyKeePass @@ -79,7 +76,10 @@ class SeleniumLib(object): self.config_file = config_file.ConfigFile() self.kdbx = None self.video_recorder = None - self.default_download_dir_path = tempfile.mkdtemp() + if config.use_download_path_default: + self.default_download_dir_path = "/home/seluser/Downloads" + else: + self.default_download_dir_path = tempfile.mkdtemp() if self.config.video_suffix: self.filename_recording = ( f"video_{self.config.video_suffix}_" @@ -136,9 +136,10 @@ class SeleniumLib(object): firefox_options.set_preference( "browser.download.manager.showWhenStarting", False ) - firefox_options.set_preference( - "browser.download.dir", self.default_download_dir_path - ) + if self.default_download_dir_path: + firefox_options.set_preference( + "browser.download.dir", self.default_download_dir_path + ) firefox_options.set_preference( "browser.helperApps.neverAsk.saveToDisk", "application/octet-stream,application/pdf,application/x-pdf", @@ -248,9 +249,10 @@ class SeleniumLib(object): firefox_options.set_preference( "browser.download.manager.showWhenStarting", False ) - firefox_options.set_preference( - "browser.download.dir", self.default_download_dir_path - ) + if self.default_download_dir_path: + firefox_options.set_preference( + "browser.download.dir", self.default_download_dir_path + ) firefox_options.set_preference( "browser.helperApps.neverAsk.saveToDisk", "application/octet-stream,application/pdf,application/x-pdf", @@ -813,35 +815,59 @@ class SeleniumLib(object): def scrollto_element( self, element, - offset_middle=True, smooth_scroll=True, smooth_speed=50, smooth_fps=1 / 25, viewport_ele=None, ): + window_y = self.driver.execute_script( + "return window.scrollY || window.pageYOffset;" + ) + window_height = self.driver.get_window_size().get("height") + element_height = element.rect["height"] + viewport_height = self.driver.execute_script( + "return window.innerHeight || document.documentElement.clientHeight;" + ) if viewport_ele: scroll_origin = ScrollOrigin.from_element(viewport_ele, 10, 10) else: scroll_origin = ScrollOrigin.from_viewport(10, 10) delta_y = element.rect["y"] - if offset_middle: - # TODO check size windows and divide by 2 - delta_y -= 400 + target_distance = ( + delta_y - (viewport_height - element_height) / 2 - window_y + ) + if window_y < delta_y < window_y + viewport_height - 50: + # No need to scroll + return print(f"scroll to xpath at y:{delta_y} position") if smooth_scroll: actual_pos = 0 - while delta_y > actual_pos: - actual_pos += smooth_speed - print(actual_pos) + # Detect go top or bot + if delta_y > window_y: + step = abs(int(smooth_speed)) # to the top + condition = lambda a, d: a < d + go_down = True + else: + step = -abs(int(smooth_speed)) # to the bot + condition = lambda a, d: a > d + go_down = False + while condition(actual_pos, target_distance): + # TODO detect when cannot scroll, stop scrolling + actual_pos += step + if go_down and actual_pos > target_distance: + step = actual_pos - target_distance + elif not go_down and actual_pos < target_distance: + step = actual_pos - target_distance + ActionChains(self.driver).scroll_from_origin( - scroll_origin, 0, int(smooth_speed) + scroll_origin, 0, int(step) ).perform() print(f"Wait {smooth_fps} seconds") time.sleep(smooth_fps) print("end") else: ActionChains(self.driver).scroll_from_origin( - scroll_origin, 0, int(delta_y) + scroll_origin, 0, int(target_distance) ).perform() # action = ActionChains(self.driver) @@ -1708,6 +1734,14 @@ def fill_parser(parser): "--use_network", help="Specify the adress, example: http://localhost:4444", ) + group_browser.add_argument( + "--use_download_path_default", + action="store_true", + help="Actually, the download path is a temporary directory. " + "This will enable default path to /home/seluser/Downloads, " + "need this with Selenium Grid by network. " + "Will delete all file into /home/seluser/Downloads at startup.", + ) group_browser.add_argument( "--window_size", help="Example 1920,1080",