I am new in selenium.
I want to run the automation test for calendar with python selenium, but the return does not same as my expect
The website for testing: https://letcode.in/calendar
I want to select the date in the right calendar. the right calendar
So I create the variable for the right calendar:
calendarInside = driver.find_element(By.XPATH,"/html/body/app-root/app-calender/section[1]/div/div/div[1]/div/div/div[1]/div[2]")
But when I filter all elements inside the calendarInside
with
allDays = calendarInside.find_elements(By.XPATH, "//div[@class='datepicker-date is-current-month']")
the return will include the elements from the left calendar.
How can I select and filter only the element in the right calendar?
The result show in both 2 calendars like image Result of code
The selenium version: selenium 4.9.1 Full code demo, you can run it to see the problem:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
def testCalendar():
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))
driver.maximize_window()
driver.implicitly_wait(10)
driver.get("https://letcode.in/calendar")
calendarInside = driver.find_element(By.XPATH,"/html/body/app-root/app-calender/section[1]/div/div/div[1]/div/div/div[1]/div[2]")
calendarInside.find_element(By.CLASS_NAME, "datetimepicker-clear-button").click()
calendarInside.find_element(By.CSS_SELECTOR, ".datetimepicker-dummy-input.is-datetimepicker-range").click()
dayExpected = [6, 25]
allDays = calendarInside.find_elements(By.XPATH, "//div[@class='datepicker-date is-current-month']")
for dayfrom in allDays:
print("dayfrom: " + str(dayfrom.text) + " - expected: " + str(dayExpected[0]))
if str(dayfrom.text) == str(dayExpected[0]):
dayfrom.click()
break
time.sleep(2)
allDays = calendarInside.find_elements(By.XPATH, "//div[@class='datepicker-date is-current-month']")
for dayto in allDays:
print("dayto: " + str(dayto.text) + " - expected: " + str(dayExpected[1]))
if str(dayto.text) == str(dayExpected[1]):
dayto.click()
break
time.sleep(5)
driver.quit()
def main():
testCalendar()
if __name__ == "__main__":
main()
How can I select and filter only the element in the right calendar? Could you give me some idea for that?
In full disclosure, I'm the author of the Browserist package. Browserist is lightweight, less verbose extension of the Selenium web driver that makes browser automation even easier. Simply install the package with pip install browserist
.
Allow me to simplify your code by unlocking the power of XPath conditions to find elements in the DOM.
from browserist import Browser
RIGHT_CALENDAR_XPATH = "/html/body/app-root/app-calender/section[1]/div/div/div[1]/div/div/div[1]/div[2]/nwb-date-picker"
def open_calendar(browser: Browser) -> None:
browser.click.button(f"{RIGHT_CALENDAR_XPATH}/div[2]/div[1]/div/input[1]")
def select_date_in_open_calendar(date: int, browser: Browser) -> None:
browser.click.button(f"{RIGHT_CALENDAR_XPATH}//div[contains(@class, 'datepicker-date is-current-month')]/button[contains(text(), '{date}')]")
with Browser() as browser:
browser.open.url("https://letcode.in/calendar")
open_calendar(browser)
select_date_in_open_calendar(5, browser)
select_date_in_open_calendar(26, browser)
Notes:
is-current-month
class – to avoid conflicts of multiple fields with the same date, e.g. 1 or 30, from respectively previous or next month./button[contains(text(), '5')]
.expected_conditions
, WebDriverWait
, or driver.implicitly_wait(10)
– it's already built in so you don't have to worry about it. Instead, Browserist awaits an element to be fully loaded before it interacts with it. More on this concept here.Here's what I get (slowed down as Browserist finishes the job almost in a blink of an eye). I hope this is helpful. Let me know if you have questions?