Unable to click through option boxes in Selenium

Question:

I am trying to make a Python script that will check appointment availability and inform me when an earlier date opens up.

I am stuck at the 4th selection page, for locations. I can’t seem to click the ‘regions’ to display the available actual locations.

This is what I have:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support import expected_conditions as EC

options = Options()
options.add_experimental_option("detach", True)

browser = webdriver.Chrome(options=options)
browser.get('url')

medical = browser.find_element(By.XPATH, "//button[@class='btn btn-primary next-button show-loading-text']")
medical.click()

timesensitive = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH,"//button[@class='btn btn-primary next-button show-loading-text']")))
timesensitive.click()

test = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH,"//button[@class='btn btn-primary next-button show-loading-text']")))
test.click()

region = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH,"//label[@class='btn btn-sm btn-default'][4]")))
region.click()

Asked By: Tostadito

||

Answers:

You miss the white space, it should be 'btn btn-sm btn-default '

region = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH,"//label[@class='btn btn-sm btn-default '][4]")))
region.click()
Answered By: JayPeerachai

You may stumble now and again on attribute values containing all sort of spaces at beginning/end you might miss. Here is one solution to avoid such pitfalls:

region = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH,"//label[contains(@class, 'btn btn-sm btn-default')][4]")))
region.click()

Also, considering you are waiting on all elements to load, why not define wait at the beginning, then just use it?

wait = WebDriverWait(driver, 10)

And then the code becomes:

[...]

timesensitive = wait.until(EC.presence_of_element_located((By.XPATH,"//button[@class='btn btn-primary next-button show-loading-text']")))
timesensitive.click()

test = wait.until(EC.presence_of_element_located((By.XPATH,"//button[@class='btn btn-primary next-button show-loading-text']")))
test.click()

region = wait.until(EC.presence_of_element_located((By.XPATH,"//label[contains(@class, 'btn btn-sm btn-default')][4]")))
region.click()

Also, here is a more robust way of selecting the desired region (obviously you know the name of it – ‘SE’):

wait.until(EC.presence_of_element_located((By.XPATH,'//label/input[@value="SE"]'))).click()

Selenium documentation can be found here.

Answered By: Barry the Platipus