Might be a bit of an edge use case, but I need to identify and then click on an object on a login page. The page itself is dynamically generated and all of the (4) buttons are labeled as such:
button tabindex="0" type="button">
With the full breakdown of the button I'm trying to click being:
<button tabindex="0" type="button"><span ><div params="[object Object]"><div ><svg focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"></path></svg></div><div >Q&A</div></div><div >Security Questions</div></span><span ></span></button>
I've tried mapping the XPATH, using CSS Selectors, trying to find the strings of text embedded in in the button, and even trying to find the SVG by using the following:
driver.find_element(by=By.XPATH , value = '//path[@d="
Any ideas how I can get Selenium to identify this object without any static identifiers?
Here's everything I've got so far:
#I know most of these are extraneous references :/
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import presence_of_element_located
from selenium.webdriver.support import expected_conditions as EC
import time
import sys
url = 'https://***.com'
chrome_driver_path = '/Users/***/chromedriver'
chrome_options = Options()
chrome_options.add_argument('--headless')
webdriver = webdriver.Chrome(
executable_path=chrome_driver_path, options=chrome_options
)
with webdriver as driver:
wait = WebDriverWait(driver, 10)
driver.get(url)
wait.until(presence_of_element_located((By.ID, "password")))
inputUsername = driver.find_element_by_id("loginID")
inputPassword = driver.find_element_by_id("password")
findLoginButton = driver.find_element_by_id("submit-button")
inputUsername.send_keys('[username]')
inputPassword.send_keys('[password]')
findLoginButton.click()
# element1 = driver.find_element_by_css_selector("div.MuiBox-root.jss135.jss107.jss134")
# wait.until(presence_of_element_located(element1))
# element1.click()
driver.find_element(by=By.XPATH , value = '//path[@d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"]')
#CSS_SELECTOR,value="#root > div > div > ^MuiBox-root^ > ^MuiBox-root^ > form > div > div.MuiCollapse-container.MuiCollapse-entered > div > div > div > button:nth-child(5)]")
#find_element_by_xpath("/html/body/div/div/div/div[2]/div[2]/form/div/div[1]/div/div/div/button[4]").click()
driver.close()
CodePudding user response:
To click on the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using XPATH and the innerText Security Questions:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(@class, 'MuiButtonBase-root')]/span[@class='MuiButton-label']//div[text()='Security Questions']"))).click()
Using XPATH and the innerText Q&A:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(@class, 'MuiButtonBase-root')]/span[@class='MuiButton-label']//div[text()='Q&A']"))).click()
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC
CodePudding user response:
I think your problem is that your locator is wrong, which is why your element isn't being found.
Try this:
driver.find_element(by=By.XPATH, "//button[contains(.//div, 'Security Questions')]")
This Xpath will return a button element that contains a div with the text "Security Questions."