1

Good afternoon, I'm new to Selenium, and in general in programming. For personal use, I decided to make an automatic calculator for converting different currencies through Selenium. I was able to parse data from a couple of sites, but with a Visa site https://www.visa.com.my/support/consumer/travel-support/exchange-rate-calculator.html a special story. If you look through Chrome at the original code of the page, it is impossible to find the fields for entering currency and the rest there. But through developer mode, after loading javascript, the id of the currency input field #input_amount_paid is visible in the debugging window, but again, even in developer mode, this selector does not search for the desired field. Please tell me how to find and fill in these fields? https://i.stack.imgur.com/i2w2z.jpg

My code:

from fixture import get_browser
from locators import VisaLocators
import time

browser = next(get_browser())
browser.get(VisaLocators.LINK)
browser.find_element(*VisaLocators.COOKIES).click()  # By.CSS_SELECTOR, '.wscrOk2:nth-child(2)'
time.sleep(1)
s = browser.find_element(*VisaLocators.AMOUNT)  # By.ID, 'input_amount_paid'
print(s.is_displayed())

I tried to set up expectations, hover the mouse cursor over the calculator section and click on it, via WebDriverWait(browser, 5).until(EC.element_to_be_clickable((By.ID , "..."))), but none of this solves the problem.

Антон
  • 13
  • 4

1 Answers1

0

Root cause: You need to handle the #shadow-root element first, as all the desired elements are located within the shadow root.

enter image description here

Refer the full working code below:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


driver = webdriver.Chrome()
driver.get('https://www.visa.com.my/support/consumer/travel-support/exchange-rate-calculator.html')
wait = WebDriverWait(driver, 30)
accept_button_element = wait.until(EC.element_to_be_clickable((By.XPATH, "//a[text()='Accept']")))
accept_button_element.click()

# store shadow root element
shadow_root = driver.find_element(By.XPATH, "//dm-calculator").shadow_root

enter_amount = shadow_root.find_element(By.ID, "input_amount_paid")
enter_amount.send_keys("20")

from_dropdown = shadow_root.find_element(By.ID, "autosuggestinput_from")
from_dropdown.click()
# clicks on the first item of the dropdown which is USD
shadow_root.find_element(By.ID, "listbox-item-0").click()

to_dropdown = shadow_root.find_element(By.ID, "autosuggestinput_to")
to_dropdown.click()
# clicks on the second item of the dropdown which is EUR
shadow_root.find_element(By.ID, "listbox-item-1").click()

# clicks on Calculate Conversion button
shadow_root.find_element(By.CLASS_NAME, 'vs-btn.vs-btn-primary').click()

Result:

enter image description here

Shawn
  • 4,064
  • 2
  • 11
  • 23