I'm trying to check if the checkbox is selected using is_selected()
method. I understand that since the element I am trying to validate is not a legit checkbox, it's not right to validate it this way. It's pretty obvious because it's wrapped in an anchor(<a>
) and italic tag(<i>
). I've tried different variants of XPaths such as:
//input[@name='non_stop']/preceding-sibling::i
//input[@name='non_stop']/parent::a
//a[@title='Non Stop Flights']/i[contains(@class, 'ico ico-checkbox')] (possibly the most wrong one here)
But is there a workaround to verify this? Here's my code:
driver = webdriver.Chrome()
driver.get("https://www.yatra.com/")
non_stop_flights = driver.find_element(
By.XPATH, "//input[@name='non_stop']/preceding-sibling::i")
print("Before clicking")
print(non_stop_flights.is_selected()) # Expecting False here
non_stop_flights.click()
sleep(3)
print("After clicking")
print(non_stop_flights.is_selected()) # Expecting True here
But I am still getting False as the output in the last line. How to make it recognize that the checkbox has been checked?
The problem is that the non-stop INPUT isn't actually storing checked state. It's being stored in the I tag right above it but inside the A tag.
<a for="BE_flight_non_stop" title="Non Stop Flights" class="custom-check">
-> <i class="ico ico-checkbox"></i>
<input data-trackcategory="Home Page" data-trackaction="Booking Engine" data-trackvalue="Non Stop Flight - Checked/Unchecked" type="checkbox" name="non_stop" id="BE_flight_non_stop" class="eventTrackable js-prodSpecEvtCat">
Non Stop Flights
</a>
The checked state is tracked using a class on the I tag...
Not checked
<i class="ico ico-checkbox"></i>
Checked
<i class="ico ico-checkbox ico-checkbox-checked"></i>
^^^^^^^^^^^^^^^^^^^^ checked state
With this info, we can make a quick method to determine the checked state of these fields
def is_checked(e):
"""
Returns a True if the checkbox is checked, False otherwise.
Parameters:
e (WebElement): The I tag for the checkbox
"""
return "ico-checkbox-checked" in e.get_attribute("class")
and then call it from your original (modified) script
driver = webdriver.Chrome()
driver.get("https://www.yatra.com/")
non_stop_flights = driver.find_element(By.CSS_SELECTOR, "a[title='Non Stop Flights'] i")
print("Before clicking")
print(is_checked(non_stop_flights)) # Expecting False here
non_stop_flights.click()
print("After clicking")
print(is_checked(non_stop_flights)) # Expecting True here
and it works as expected.