1

I have written a full selenium script that's working but not all the time as whem I try to select meals (this is last sections of the page), I sometimes get two errors.

One error is a timeout exception as it waits for a meal drop down to have an option selected, wait for it to be clickable again after it loads its selected option before moving onto the next option. I assume for this I need to set the wait = WebDriverWait(driver, 20) to longer than 20 seconds just in case the drop down options are taking longer to load.

Another issue I am having an seems to be occurring a lot in the meals page is this 'Element is no longer attached to the DOM' issue. Again this usually happens when I am on the meals page. Doing some research it seems to be possible that a javascript could be causing this issue but not too sure. Could it be to fix this issue I need to include more waits or maybe I should be looking to refresh pages after navigating from one page to another?

Below I only pasted the relevant code. If you want to view the whole code and try it yourself on the application, then send me a comment.

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

...

driver = webdriver.Firefox()
#driver = webdriver.Chrome()
driver.get("http://www.jet2.com")
driver.maximize_window()

wait = WebDriverWait(driver, 20)
actions = ActionChains(driver)

...

# proceed to the next page (meals)
submit_seat_selection = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#AllInboundPassengersSeatedOk button.submitseatselection")))
submit_seat_selection.click()
meals = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_InFlightMeal_removeMealButton")))

#Meal details

pax_one_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown"))
pax_one_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown")))
pax_one_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn"))
pax_one_ib_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn")))

pax_two_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown"))
pax_two_ob_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown")))
pax_two_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn"))
pax_two_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn")))

pax_three_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown"))
pax_three_ob_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown")))
pax_three_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn"))
pax_three_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn")))

pax_four_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown"))
pax_four_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown")))
pax_four_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn"))
pax_four_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn")))

UPDATE:

Below is the whole code as requested:

    from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from datetime import datetime, timedelta
import settings

# Search Flights
FROM = "Leeds Bradford"
TO = "Antalya"

# PAX Details
PAX1_FORENAME = "Dad"
PAX2_FORENAME = "Mum"
PAX3_FORENAME = "Son"
PAX4_FORENAME = "Daughter"
PAX5_FORENAME = "Baby"

PAX_SURNAME = "Test"

#Payment Details
NAME_ON_CARD = "Mr Test"
CARD_NUMBER = "1000070000000001"
SECURITY_CODE = "111"

#Contact Details
CONTACT_FIRST_NAME = "Dad"
CONTACT_LAST_NAME = "Test"
POSTCODE = "LS11 9AW"

MOBILE_PHONE = "07766554433"
DESTINATION_PHONE = "01122334455"
HOME_PHONE = "01234567890"

EMAIL = settings.EMAIL


def select_date(calendar, mininum_date=None):
    try:
        # check if "Your Date" is there
        your_date_elm = calendar.find_element_by_class_name("your-date")

        your_date = your_date_elm.get_attribute("data-date")
        print("Found 'Your Date': " + your_date)
        your_date_elm.click()

        # check if your_date against the minimum date if given
        your_date = datetime.strptime(your_date, "%Y-%m-%d")
        if mininum_date and your_date < mininum_date:
            raise NoSuchElementException("Minimum date violation")
        return your_date
    except NoSuchElementException:
        flight_date = None
        flight_date_elm = None
        while True:
            print("Processing " + calendar.find_element_by_css_selector("div.subheader > p").text)

            try:
                if mininum_date:
                    flight_date_elms = calendar.find_elements_by_class_name("flights")
                    flight_date_elm = next(flight_date_elm for flight_date_elm in flight_date_elms
                                           if datetime.strptime(flight_date_elm.get_attribute("data-date"), "%Y-%m-%d") >= mininum_date)
                else:
                    flight_date_elm = calendar.find_element_by_class_name("flights")
            except (StopIteration, NoSuchElementException):
                calendar.find_element_by_partial_link_text("Next month").click()

            # if found - print out the date, click and exit the loop
            if flight_date_elm:
                flight_date = flight_date_elm.get_attribute("data-date")
                print("Found 'Flight Date': " + flight_date)
                flight_date_elm.click()
                break

        return datetime.strptime(flight_date, "%Y-%m-%d")


driver = webdriver.Firefox()
#driver = webdriver.Chrome()
driver.get("http://www.jet2.com")
driver.maximize_window()

wait = WebDriverWait(driver, 90)
actions = ActionChains(driver)

# wait for the page to load
wait.until(EC.presence_of_element_located((By.ID, "departure-airport-input")))

# fill out the form
return_flight = driver.find_element_by_id('return-flight-selector').click()

depart_from = driver.find_element_by_id("departure-airport-input").send_keys(FROM)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ui-id-1 .ui-menu-item"))).click()

go_to = driver.find_element_by_id("destination-airport-input").send_keys(TO)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ui-id-2 .ui-menu-item"))).click()

# select depart date
datepicker = driver.find_element_by_id("departure-date-selector")
actions.move_to_element(datepicker).click().perform()

# find the calendar, month and year picker and the current date
calendar = driver.find_element_by_id("departureDateContainer")
month_picker = Select(calendar.find_element_by_class_name("ui-datepicker-month"))
year_picker = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
current_date = calendar.find_element_by_class_name("ui-datepicker-current-day")

# printing out current date
month = month_picker.first_selected_option.text
year = year_picker.first_selected_option.text
print("Current departure date: {day} {month} {year}".format(day=current_date.text, month=month, year=year))

# see if we have an available date in this month
try:
    next_available_date = current_date.find_element_by_xpath("following::td[@data-handler='selectDay' and ancestor::div/@id='departureDateContainer']")
    print("Found an available departure date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
    next_available_date.click()
except NoSuchElementException:
# looping over until the next available date found
        while True:
# click next, if not found, select the next year
            try:
                calendar.find_element_by_class_name("ui-datepicker-next").click()
            except NoSuchElementException:
# select next year
                year = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
                year.select_by_visible_text(str(int(year.first_selected_option.text) + 1))

# reporting current processed month and year
                month = Select(calendar.find_element_by_class_name("ui-datepicker-month")).first_selected_option.text
                year = Select(calendar.find_element_by_class_name("ui-datepicker-year")).first_selected_option.text
                print("Processing {month} {year}".format(month=month, year=year))

            try:
                next_available_date = calendar.find_element_by_xpath(".//td[@data-handler='selectDay']")
                print("Found an available departure date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
                next_available_date.click()
                break
            except NoSuchElementException:
                continue



# select return date
datepicker = driver.find_element_by_id("return-date-selector")
actions.move_to_element(datepicker).click().perform()

# find the calendar, month and year picker and the current date
calendar = driver.find_element_by_id("returnDateContainer")
month_picker = Select(calendar.find_element_by_class_name("ui-datepicker-month"))
year_picker = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
current_date = calendar.find_element_by_class_name("ui-datepicker-current-day")

# printing out current date
month = month_picker.first_selected_option.text
year = year_picker.first_selected_option.text
print("Current return date: {day} {month} {year}".format(day=current_date.text, month=month, year=year))

# see if we have an available date in this month
try:
    next_available_date = current_date.find_element_by_xpath("following::td[@data-handler='selectDay' and ancestor::div/@id='returnDateContainer']")
    print("Found an available return date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
    next_available_date.click()
except NoSuchElementException:
# looping over until the next available date found
        while True:
# click next, if not found, select the next year
            try:
                calendar.find_element_by_class_name("ui-datepicker-next").click()
            except NoSuchElementException:
# select next year
                year = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
                year.select_by_visible_text(str(int(year.first_selected_option.text) + 1))

# reporting current processed month and year
                month = Select(calendar.find_element_by_class_name("ui-datepicker-month")).first_selected_option.text
                year = Select(calendar.find_element_by_class_name("ui-datepicker-year")).first_selected_option.text
                print("Processing {month} {year}".format(month=month, year=year))

            try:
                next_available_date = calendar.find_element_by_xpath(".//td[@data-handler='selectDay']")
                print("Found an available return date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
                next_available_date.click()
                break
            except NoSuchElementException:
                continue

#select adults
adults = Select(driver.find_element_by_id("adults-number"))
adults.select_by_visible_text("2")

#select children
children = Select(driver.find_element_by_id("children-number"))
children.select_by_visible_text("2")

#children ages
child_one = Select(driver.find_element_by_id("childSelect1"))
child_one.select_by_visible_text("4")

child_two = Select(driver.find_element_by_id("childSelect2"))
child_two.select_by_visible_text("6")

confirm = driver.find_element_by_link_text("Confirm")
confirm.click()

#select infants
infants = Select(driver.find_element_by_id("infants-number"))
infants.select_by_visible_text("1")

#search flights
search_flight = driver.find_element_by_id("search-flights").click()

# get the outbound date
outbound = wait.until(EC.visibility_of_element_located((By.ID, "outboundsearchresults")))
outbound_date = select_date(outbound)

# get the inbound date
inbound = driver.find_element_by_id("inboundsearchresults")
inbound_minimum_date = outbound_date + timedelta(days=7)
inbound_date = select_date(inbound, mininum_date=inbound_minimum_date)
print(outbound_date, inbound_date)

# continue after flights selected
proceed_to_pax = driver.find_element_by_id('navigateActionNext').click()
pax_page = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_passengerList_PassengerGridView_ctl08_butAddBagsForAll")))

#select currency
currency = Select(driver.find_element_by_id("ctl00_MainContent_dynamicCurrencyDropDown"))
currency.select_by_value("1")

#Passenger details
pax_one_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_TitleDropDownList"))
pax_one_title.select_by_visible_text("Mr")
pax_one_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_ForeNameTextBox").send_keys(PAX1_FORENAME)
pax_one_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_SurNameTextBox").send_keys(PAX_SURNAME)

pax_two_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_TitleDropDownList"))
pax_two_title.select_by_visible_text("Mrs")
pax_two_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_ForeNameTextBox").send_keys(PAX2_FORENAME)
pax_two_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_SurNameTextBox").send_keys(PAX_SURNAME)

pax_three_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_TitleDropDownList"))
pax_three_title.select_by_visible_text("Mr")
pax_three_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_ForeNameTextBox").send_keys(PAX3_FORENAME)
pax_three_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_SurNameTextBox").send_keys(PAX_SURNAME)

pax_four_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_TitleDropDownList"))
pax_four_title.select_by_visible_text("Ms")
pax_four_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_ForeNameTextBox").send_keys(PAX4_FORENAME)
pax_four_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_SurNameTextBox").send_keys(PAX_SURNAME)

pax_five_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_TitleDropDownList"))
pax_five_title.select_by_visible_text("Mstr")
pax_five_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_ForeNameTextBox").send_keys(PAX5_FORENAME)
pax_five_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_SurNameTextBox").send_keys(PAX_SURNAME)

#pax baggage
pax_one_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_baggageOutDropDown"))
pax_one_bags.select_by_value("1")

pax_two_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_baggageOutDropDown"))
pax_two_bags.select_by_value("1")

pax_three_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_baggageOutDropDown"))
pax_three_bags.select_by_value("1")

pax_four_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_baggageOutDropDown"))
pax_four_bags.select_by_value("1")

pax_one_golf = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_GolfDropDown"))
pax_one_golf.select_by_value("1")

pax_two_bike = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_BikesDropDown"))
pax_two_bike.select_by_value("1")

#infant carer
infant_one_carer = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_InfantCarerDropDown"))
infant_one_carer.select_by_visible_text("Mr Dad Test")

#checkin
#online = driver.find_element_by_id("ctl00_MainContent_passengerList_checkinOnline").click()
airport = driver.find_element_by_id("ctl00_MainContent_passengerList_checkinAirport").click()

#continue to seats
continue_pax = driver.find_element_by_id("pageContinue").click()
#modal_outer = wait.until(EC.invisibility_of_element_located((By.ID, "ctl00_MainContent_PageTransitionDialog_messageWrapper")))
#continue_again = wait.until(EC.element_to_be_clickable((By.ID, "pageContinue"))).click();
seats_page = wait.until(EC.visibility_of_element_located((By.ID, "findyourseat")))

#seats selection - outbound

for outbound_passenger in driver.find_elements_by_css_selector("ol[data-flightbound='Outbound'] li[data-personid]"):
    outbound_passenger.click()

#driver.find_elements_by_css_selector("ol.passengerlist li[data-personid]"):

    outbound_has_infant = outbound_passenger.get_attribute("data-hasinfant")

# choose seats
    if outbound_has_infant:
        # select a non-selected infant seat
        outbound_seat = driver.find_element_by_css_selector(".outbound .planebody a.seat.infant:not(.reserved):not(.selected)")
    else:
        # select a non-reserved non-selected seat
        outbound_seat = driver.find_element_by_css_selector(".outbound .planebody a.seat:not(.reserved):not(.selected)")

    print("Passenger: %s, choosing seat: %s" % (outbound_passenger.text.strip(), outbound_seat.get_attribute("data-seat")))
    outbound_seat.click()

outbound_plan = wait.until(EC.invisibility_of_element_located((By.CLASS_NAME, "outbound")))
inbound_plan = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "inbound")))

#seats selection - inbound

for inbound_passenger in driver.find_elements_by_css_selector("ol[data-flightbound='Inbound'] li[data-personid]"):
    inbound_passenger.click()

#driver.find_elements_by_css_selector("ol.passengerlist li[data-personid]"):

    inbound_has_infant = inbound_passenger.get_attribute("data-hasinfant")

    # choose seats
    if inbound_has_infant:
        # select a non-selected infant seat
        inbound_seat = driver.find_element_by_css_selector(".inbound .planebody a.seat.infant:not(.reserved):not(.selected)")
    else:
        # select a non-reserved non-selected seat
        inbound_seat = driver.find_element_by_css_selector(".inbound .planebody a.seat:not(.reserved):not(.selected)")

    print("Passenger: %s, choosing seat: %s" % (inbound_passenger.text.strip(), inbound_seat.get_attribute("data-seat")))
    inbound_seat.click()

# proceed to the next page (meals)
submit_seat_selection = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#AllInboundPassengersSeatedOk button.submitseatselection")))
submit_seat_selection.click()
meals = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_InFlightMeal_removeMealButton")))

#Meal details

pax_one_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown"))
pax_one_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown")))
pax_one_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn"))
pax_one_ib_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn")))

pax_two_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown"))
pax_two_ob_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown")))
pax_two_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn"))
pax_two_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn")))

pax_three_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown"))
pax_three_ob_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown")))
pax_three_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn"))
pax_three_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn")))

pax_four_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown"))
pax_four_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown")))
pax_four_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn"))
pax_four_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn")))

# Select Insurance

yes_insurance = driver.find_element_by_id('ctl00_MainContent_TravelInsuranceView_insuranceRequiredYes').click()
single_trip = driver.find_element_by_xpath('//input[@id="ctl00_MainContent_TravelInsuranceView_insuranceProduct1" and not(@disabled)]').click()
driver.find_element_by_xpath('//span[@id="insurance-button-submit" and (@disabled="false")]')
confirm_insurance = driver.find_element_by_id('ctl00_MainContent_TravelInsuranceView_InsuranceSubmitButton').click()

nearly_there = wait.until(EC.invisibility_of_element_located((By.ID, "ct100_MainContent_PageTransitionDialog_messageWrapper")))
checkout_btn = wait.until(EC.element_to_be_clickable((By.NAME, "ctl00$MainContent$forwardButton"))).click()

# Proceed to Payment Page

payment_page = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_rbCreditcard")))

# Payment details

payment_method = driver.find_element_by_id('ctl00_MainContent_rbCreditcard').click()
wait.until(EC.invisibility_of_element_located((By.ID, "PleaseWaitDialog")))

name_on_card = driver.find_element_by_id("nameOnCard").send_keys(NAME_ON_CARD)

card_type = Select(driver.find_element_by_id("cardType"))
card_type.select_by_visible_text("Visa")
wait.until(EC.invisibility_of_element_located((By.ID, "PleaseWaitDialog")))

card_number = driver.find_element_by_id("cardNumber").send_keys(CARD_NUMBER)

exp_month = Select(driver.find_element_by_id("month"))
exp_month.select_by_index(1)
exp_year = Select(driver.find_element_by_id("year"))
exp_year.select_by_index(2)

security_code = driver.find_element_by_id("cardVerificationNumber").send_keys(SECURITY_CODE)

# Contact details

title = Select(driver.find_element_by_id("ctl00_MainContent_addressView_contactTitleDropDown"))
title.select_by_visible_text("Mr")

contact_first_name = driver.find_element_by_id("ctl00_MainContent_addressView_contactFirstNameTextBox").send_keys(CONTACT_FIRST_NAME)
contact_last_name = driver.find_element_by_id("ctl00_MainContent_addressView_contactLastNameTextBox").send_keys(CONTACT_LAST_NAME)

country = Select(driver.find_element_by_id("ctl00_MainContent_addressView_countryDropDown"))
country.select_by_visible_text("United Kingdom")

find_address = driver.find_element_by_id('ctl00_MainContent_addressView_CheckPostcodeButton').click()
postcode_find = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_postcodeLookupDiv")))
postcode = driver.find_element_by_id("ctl00_MainContent_ThePostCodeTextBox").send_keys(POSTCODE)
search_again = driver.find_element_by_id('FindAgainButton').click()
address_shown = wait.until(EC.visibility_of_element_located((By.XPATH, '//option')))
address_pick = Select(driver.find_element_by_id("ctl00_MainContent_PostCodeListBox"))
address_pick.select_by_value("50774613")
found_button = driver.find_element_by_id('ctl00_MainContent_FoundButton').click()
postcode_disappear = wait.until(EC.invisibility_of_element_located((By.ID, "ctl00_MainContent_postcodeLookupDiv")))

mobile_phone = driver.find_element_by_id("ctl00_MainContent_addressView_leadPhoneDestTextBox").send_keys(MOBILE_PHONE)
destination_phone = driver.find_element_by_id("ctl00_MainContent_addressView_destPhoneTextBox").send_keys(DESTINATION_PHONE)
home_phone = driver.find_element_by_id("ctl00_MainContent_addressView_leadPhoneTextBox").send_keys(HOME_PHONE)

email = driver.find_element_by_id("ctl00_MainContent_addressView_emailAddTextBox").send_keys(EMAIL)
confirm_email = driver.find_element_by_id("ctl00_MainContent_addressView_confirmEmailTextBox").send_keys(EMAIL)

news_checkbox = driver.find_element_by_id('ctl00_MainContent_newsCheckBox').click()
travel_reason = Select(driver.find_element_by_id("ctl00_MainContent_reasonForTravelDropDown"))
travel_reason.select_by_visible_text("Holiday")
first_time = driver.find_element_by_id('ctl00_MainContent_FirstTimeUserRadio_1').click()

tandc = driver.find_element_by_id('ctl00_MainContent_chkAcceptTandCs').click()
#complete_booking = driver.find_element_by_id('ctl00_MainContent_continueButton')
#complete_booking.click()
BruceyBandit
  • 3,978
  • 19
  • 72
  • 144
  • On which of the lines the error(s) happen? Is it consistent? Thanks. – alecxe Feb 17 '16 at 01:04
  • Just having a check now if consistent on a line. FYI, It's pretty much finished. Need to complete checkout at work to test a dummy payment and it should be good to go. This is helpful for other users now so that they're don't have to manually create bookings anymore and just run the script. So in advance alecxe, thanks for all your help with this application. Still have few more apps to go but this was the hardest app – BruceyBandit Feb 17 '16 at 01:34
  • It's not really consistent, just tried now and not had an issue, though I did set the WebDriverWait to 90. The timeout error appeared on this line: wait.until(EC.element_to_be_clickable((By.ID, `"ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn")))` – BruceyBandit Feb 17 '16 at 01:37
  • Ok it broke on the meal page again with the no longer attached to the DOM error. I will post the error message in the question along with the lines of code it points to. This error came after testing it for the third time. The first two times went through fine. – BruceyBandit Feb 17 '16 at 01:51
  • Its wired, `StaleElementReferenceException` is being thrown when you are trying to interact with WebElement you located but disappeared from the DOM before the interaction. You are trying to locate the element by selector (`wait.until` is locating the elements). If the WebElement is not in the DOM you should had `TimeoutException`. – Guy Feb 17 '16 at 06:08
  • @guy It is weird, it's doing my heading as I get to the meals page and its about 50/50 on whether I get the error or manage to get through scott free – BruceyBandit Feb 17 '16 at 12:40

1 Answers1

1

It looks like the error happens inside the Expected Condition between the is_displayed() and is_enabled() checks. The "Stale Element Reference Error" is not handled when the enabledness is checked. Let's try with a custom Expected Condition:

from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException

class custom_element_to_be_clickable(object):
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        try:
            element = driver.find_element(self.locator)
            return element.is_displayed() and element.is_enabled()
       except NoSuchElementException, StaleElementReferenceException:
            return False

Use this instead of EC.element_to_be_clickable.

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • So just to make sure, I should change `wait.until(EC.element_to_be_clickable((By.ID,...)))` to either `wait.until(element.is_displayed((By.ID,...)))` OR `wait.until(element.is_enabled((By.ID,...)))`? Should I change all `EC.element_to_be_clickable.` so they all the same or just the ones in meals page is enough as the error seems to only happen on that page? – BruceyBandit Feb 18 '16 at 04:39
  • @BruceyBandit to make things clear, use the `custom_element_to_be_clickable()` I've presented in the answer: `wait.until(custom_element_to_be_clickable((By.ID,...)))`. – alecxe Feb 18 '16 at 04:42
  • Hi alecxe, just tried the condition you supplied to me but it seems to not notice it. Let's say I load the page and use it to wait for the button to become clickable so that I know the page has load, instead it just keeps givng me a timeout error, as if it couldn't tell if the button is clickable using the customer element to be clickable function – BruceyBandit Feb 18 '16 at 07:04
  • @BruceyBandit could you provide me with the complete code you have so far? I'll try applying the EC myself and see if I'll see the same issue. Thanks. – alecxe Feb 19 '16 at 17:22
  • I've pasted the whole code above. My current code is actually on my work computer but if you can test you function here and get it working, I'll apply it in the current code when I'm back at work tomorrow. I can test it on the code at home in the mean time to see if working or not before applying it to work code. Thank you very much – BruceyBandit Feb 20 '16 at 08:45
  • @BruceyBandit interesting, I've just executed your code as is and it failed only on the "select insurance" step passing the "meals" step without any problems..are you sure you have issues in meal selection and what are they? Thanks. – alecxe Feb 21 '16 at 12:39
  • I will start running my selenium scripts after tomorrow or day after as made some changes and will give you an updated code. Because it failed on insurance step, it might be something incorrect with my if statement, but give me time and I'll update you in a few days – BruceyBandit Mar 02 '16 at 02:20
  • @BruceyBandit many thanks for the bounty. Yeah, give me your final code and we'll see if this problem is still there and how can we approach it. Thanks. – alecxe Mar 02 '16 at 03:14