Unable to Drag Range Slider Thumbs Using Selenium Actions Class

79 Views Asked by At

I'm currently working on automating a web application that contains a range slider with two thumbs using Selenium. The HTML structure of the slider is as follows:

0 10000 I'm attempting to automate the interaction with the range slider, specifically by dragging or click_and_hold and move to offset the left and right thumbs to set the desired range values. However, I'm encountering issues when trying to drag the thumbs using the Selenium Actions class.

Solution I attempted :

Solution 1: sliders = self.driver.find_elements(By.XPATH, "//input[@type='range']")

# Determine the range of the slider
slider_min = int(sliders[0].get_attribute("min"))
slider_max = int(sliders[0].get_attribute("max"))

# Calculate the number of steps and step size
num_steps = slider_max - slider_min
step_size = (int(max_value) - int(min_value)) / num_steps

# Calculate the left and right slider values based on scaling_factor
left_slider_value = slider_min + int((int(min_value) - slider_min) / step_size)
right_slider_value = slider_min + int((int(max_value) - slider_min) / step_size)

# Scroll to the sliders to make them visible
self.driver.execute_script("arguments[0].scrollIntoView(true);", sliders[0])
self.driver.execute_script("arguments[0].scrollIntoView(true);", sliders[1])

# Drag the left slider to the desired position
action = ActionChains(self.driver)
action.click_and_hold(sliders[0]).move_by_offset(left_slider_value, 0).release().perform()

# Drag the right slider to the desired position
action = ActionChains(self.driver)
action.click_and_hold(sliders[1]).move_by_offset(-right_slider_value, 0).release().perform()`

Solution 2: left_thumb = driver.find_element_by_css_selector(".thumb--left")

# Create an Actions object
actions = ActionChains(driver)

# Attempt to drag the left thumb
actions.drag_and_drop_by_offset(left_thumb, 100, 0).perform()

Despite using the Actions class, the left thumb and right thumb doesn't seem to move. I've tried various offsets and methods, but I can't get it to work.

Is there something specific I'm missing or any known issues related to automating range sliders like this? Any insights or guidance on how to effectively interact with this range slider using Selenium would be greatly appreciated.

1

There are 1 best solutions below

3
Yaroslavm On

In provided HTML structure slider input itself doesn't contain allocated separate thumb element, however, I can suggest 2 workarounds how to achieve your goal.

  1. Setting input value via JS would automatically move slider to needed value.

Pros: you can set direct value and assert it by demand.

Cons: It's not native user behaviour, so if input has separate thumb, it can be broken and test wouldn't fail.

slider = driver.find_element(By.CLASS_NAME, "thumb.thumb--left")
driver.execute_script('arguments[0].value = "1000"', slider)

or if element is not subscriptable

drag_script = "document.querySelector(arguments[0]).value = 3000;"
driver.execute_script(drag_script, locator)
  1. Click on slider space (so click will emulate slider move)

Pros: It's the same as user behaviour.

Cons: You should calculate click area if you need direct value which you want to set. And offset can be different, depends on screen resolution.

slider_right = driver.find_element(By.CLASS_NAME, "thumb.thumb--right")
actionChains.move_to_element_with_offset(slider_right, 20, 0).click().perform()

You can try it with your provided structure, using code below:

url = "https://inputnum.w3spaces.com/saved-from-Tryit-2023-09-05-v6vr9.html"
driver.get(url)
slider = driver.find_element(By.CLASS_NAME, "thumb.thumb--left")
slider_right = driver.find_element(By.CLASS_NAME, "thumb.thumb--right")
driver.execute_script('arguments[0].value = "1000"', slider)

actionChains.move_to_element_with_offset(slider_right, 20, 0).click().perform()

Test environment for your case:

drag_script = "document.querySelector(arguments[0]).value = 3000;"

wait = WebDriverWait(driver, 20)
url = "https://codepen.io/rendykstan/pen/VLqZGO"
driver.get(url)
iframe = wait.until(EC.presence_of_element_located((By.ID, 'result')))
driver.switch_to.frame(iframe)
driver.execute_script(drag_script, 'input')