python-3.xseleniumselenium-webdrivermaximostaleelementreferenceexception

StaleElementException error in Selenium Python


I am working on a web automation project. The project is personally for myself as I have to constantly click and fill out text fields on a web app (IBM Maximo Asset Management). The login, and then clicking the link where I want to go initially work fine, but it's when I start clicking on text fields on each new row that I get errors. It's as if adding a new row changes the whole DOM, but it only creates another table in the DOM while others remain unchanged. I would love to have a collaborator if possible to get me through this problem.

You will see in some places I have had to use full XPATHs due to the automation just breaking, such as:

if driver.find_element(
                By.XPATH,
                "/html/body/form/div/table[2]/tbody/tr/td/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[2]/td/div/table/tbody/tr/td/div/table/tbody/tr/td/table/tbody/tr/td/div/table/tbody/tr/td/table/tbody/tr[2]/td/table/tbody/tr[2]/td/div/table/tbody/tr[3]/td/table/tbody/tr[3]/td/table/tbody/tr[4]/td[10]").text == "WSCH":

Without full XPATH, the code just can't find this element. Should I code using full XPATH for all elements then? Suggestions please.

I feel like I should do it for the entire code, but it would make it really hard to change if the web app is changed or updated.

This is my entire code.

import datetime
import time

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.ui import WebDriverWait

# from selenium.webdriver.common.action_chains import ActionChains

options = webdriver.ChromeOptions()

prefs = {"download.default_directory": "C:\\Users\\Administrator\\Desktop\\NewWO\\NEW"}

options.add_experimental_option("prefs", prefs)

PATH = "C:\\Users\\Administrator\\Desktop\\chromedriver_win32\\chromedriver.exe"

driver = webdriver.Chrome(PATH, options=options)

# Wait 3 seconds for the "chromedriver.exe" to load

time.sleep(3)

action = ActionChains(driver)

# Open IBM MAXIMO Asset Management Web App

driver.get("http://10.1.84.87/maximo/webclient/login/login.jsp?appservauth=true")

driver.maximize_window()

# Wait 2 seconds for login elements to load

time.sleep(4)

# Login to IBM Maximo Asset Management

# Pass login parameters

with open("C:\\Users\\Administrator\\Desktop\\WO_Automation\\pass.txt", "r") as p:

    maximo_pass_supervisor = p.read()

id_box = driver.find_element(By.ID, 'j_username')

id_box.send_keys("07780141")

pass_box = driver.find_element(By.ID, 'j_password')

pass_box.send_keys(maximo_pass_supervisor)

pass_box.submit()

# Click on "Work Order Tracking" link after login

element_wo_tracking = WebDriverWait(driver, 600).until(
    ec.visibility_of_element_located((By.LINK_TEXT, "Work Order Tracking")))

wo_track = driver.find_element(By.LINK_TEXT, "Work Order Tracking")

wo_track.click()

time.sleep(3)

# Create a list of arguments to be entered into fields based on the 'description.txt' file

pm_actuals = []

with open("C:\\Users\\Administrator\\Desktop\\PM.txt", "r") as pm_number:

    pm = pm_number.readlines()[11:12]

    for line in pm:

        line = line.upper().strip().split(",")

        pm_actuals.append(line)


# A function to send text to an element one character at a time with a delay of 0.1s

def slow_type(el, text, delay=0.1):

    for character in text:

        el.send_keys(character)

        time.sleep(delay)


# Check for PM availability

pm_availability = []

for pm in range(0, len(pm_actuals[0])):

    time.sleep(1)

    ignore_exceptions = (NoSuchElementException, StaleElementReferenceException,)

    element_search_text_wo = WebDriverWait(driver, 120, 5, ignore_exceptions).until(
        ec.element_to_be_clickable((By.XPATH, "//input[@id='m6a7dfd2f_tfrow_[C:1]_txt-tb']")))

    search_text_wo = driver.find_element(By.XPATH, "//input[@id='m6a7dfd2f_tfrow_[C:1]_txt-tb']")

    search_text_wo.clear()

    slow_type(search_text_wo, pm_actuals[0][pm].replace(" ", "", 1))

    search_text_wo.send_keys(Keys.RETURN)

    element_len_elements_list = WebDriverWait(driver, 120, 5, ignore_exceptions).until(
        ec.visibility_of_any_elements_located((By.XPATH, "//*[contains(@id, 'm6a7dfd2f_tbod_tdrow-tr[R:')]")))

    len_elements_list = driver.find_elements(By.XPATH, "//*[contains(@id, 'm6a7dfd2f_tbod_tdrow-tr[R:')]")

    if len(len_elements_list) != 0:

        # Check if PM status is WSCH

        if driver.find_element(
                By.XPATH,
                "/html/body/form/div/table[2]/tbody/tr/td/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[2]/td/div/table/tbody/tr/td/div/table/tbody/tr/td/table/tbody/tr/td/div/table/tbody/tr/td/table/tbody/tr[2]/td/table/tbody/tr[2]/td/div/table/tbody/tr[3]/td/table/tbody/tr[3]/td/table/tbody/tr[4]/td[10]").text == "WSCH":

            pm_availability.append(pm_actuals[0][pm].replace(" ", "", 1))

            continue

        # If PM status is not WSCH, continue searching

        else:

            continue

    else:

        continue

# Exceptions to ignore

ignore_exceptions = (NoSuchElementException, StaleElementReferenceException,)

# Start PM routing

counter = 0

while len(pm_availability) != 0:

    for i in range(0, len(pm_availability)):

        element_search_text_wo = WebDriverWait(driver, 120, 5, ignore_exceptions).until(
            ec.element_to_be_clickable((By.XPATH, "//input[@id='m6a7dfd2f_tfrow_[C:1]_txt-tb']")))

        search_text_wo = driver.find_element(By.XPATH, "//input[@id='m6a7dfd2f_tfrow_[C:1]_txt-tb']")

        search_text_wo.clear()

        slow_type(search_text_wo, pm_availability[i])

        search_text_wo.send_keys(Keys.RETURN)

        # Start PM routing procedure if the status is WSCH

        # Select the PM

        element_first_row_search = WebDriverWait(driver, 600, 5, ignore_exceptions).until(
            ec.presence_of_element_located(
                (By.XPATH,
                 "/html/body/form/div/table[2]/tbody/tr/td/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[2]/td/div/table/tbody/tr/td/div/table/tbody/tr/td/table/tbody/tr/td/div/table/tbody/tr/td/table/tbody/tr[2]/td/table/tbody/tr[2]/td/div/table/tbody/tr[3]/td/table/tbody/tr[3]/td/table/tbody/tr[4]/td[3]/span[@id='m6a7dfd2f_tdrow_[C:1]_ttxt-lb[R:0]']")))

        first_row = driver.find_element(
            By.XPATH, "/html/body/form/div/table[2]/tbody/tr/td/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[2]/td/div/table/tbody/tr/td/div/table/tbody/tr/td/table/tbody/tr/td/div/table/tbody/tr/td/table/tbody/tr[2]/td/table/tbody/tr[2]/td/div/table/tbody/tr[3]/td/table/tbody/tr[3]/td/table/tbody/tr[4]/td[3]/span[@id='m6a7dfd2f_tdrow_[C:1]_ttxt-lb[R:0]']")

        first_row.click()

        time.sleep(3)

        # Go to ACTUALS tab

        element_actuals_tab = WebDriverWait(driver, 120, 5, ignore_exceptions).until(
            ec.element_to_be_clickable((By.XPATH, "//*[@id='m272f5640-tab']")))

        actuals_tab = driver.find_element(By.XPATH, "//*[@id='m272f5640-tab']")

        actuals_tab.click()

        # Create a list of all labor information

        pm_labor = []

        with open("C:\\Users\\Administrator\\Desktop\\PM.txt", "r") as pm_info:

            pm = pm_info.readlines()[14:]

            for line in pm:

                line = line.upper().strip().split(",")

                pm_labor.append(line)

        # Create a list of duration to calculate the PM start and end times

        duration = []

        with open("C:\\Users\\Administrator\\Desktop\\PM.txt", "r") as pm_duration:

            pm = pm_duration.readlines()[8:9]

            for line in pm:

                line = line.upper().strip().split(".")

                duration.append(line)

        # Create a list for the start_time_pm values

        starting_time = []

        with open("C:\\Users\\Administrator\\Desktop\\PM.txt", "r") as pm_start:

            start = pm_start.readlines()[3:5]

            for line in start:

                line = line.upper().strip().split("=")

                starting_time.append(line)

        # Start time for all PMs will be 0700 hours

        start_time_pm = datetime.timedelta(hours=int(starting_time[0][1]),
                                           minutes=int(starting_time[1][1]), seconds=0)

        # Create a list of times based on the duration of PM in PM.txt file

        start_time = []

        end_time = []

        # Iterate the time starting from 0700 hours to create PM time slots

        while start_time_pm < datetime.timedelta(hours=14, minutes=0):

            end_time_pm = start_time_pm + datetime.timedelta(hours=int(duration[0][0])) + \
                          datetime.timedelta(minutes=int(duration[0][1]))

            # If end time is 1415 hours or less, append the time values to the lists

            if end_time_pm <= datetime.timedelta(hours=14, minutes=15):

                start_time.append(str(start_time_pm))

                end_time.append(str(end_time_pm))

                start_time_pm = start_time_pm + datetime.timedelta(hours=int(duration[0][0])) + \
                                datetime.timedelta(minutes=int(duration[0][1])) + \
                                datetime.timedelta(minutes=15)

            # If end time is 1400 hours or more, break out of the loop

            elif end_time_pm >= datetime.timedelta(hours=14, minutes=0):

                break

            else:

                continue

        time.sleep(2)

        # Add labor information

        for labor_row in range(0, len(pm_labor)):

            try:

                # Click on new labor for a new row to enter labor information

                element_new_labor = WebDriverWait(driver, 60, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((By.XPATH, "//*[@id='m4dfd8aef_bg_button_addrow-pb']")))

                new_labor = driver.find_element(By.XPATH, "//*[@id='m4dfd8aef_bg_button_addrow-pb']")

                new_labor.click()

                time.sleep(2)

                # Add labor ID from pm_labour list

                element_labor_id = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((
                        By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:2]_txt-tb[R:" + str(labor_row) + "]']")))

                labor_id = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:2]_txt-tb[R:" + str(labor_row) + "]']")

                labor_id.clear()

                slow_type(labor_id, pm_labor[labor_row][0].replace(" ", "", 1))

                time.sleep(2)

                # Add start date for PM from pm_labour list

                element_start_date = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((
                        By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:6]_txt-tb[R:" + str(labor_row) + "]']")))

                start_date = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:6]_txt-tb[R:" + str(labor_row) + "]']")

                start_date.clear()

                slow_type(start_date, pm_labor[labor_row][1].replace(" ", "", 1))

                time.sleep(2)

                # Add end date for PM from pm_labour list

                element_end_date = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((
                        By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:7]_txt-tb[R:" + str(labor_row) + "]']")))

                end_date = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:7]_txt-tb[R:" + str(labor_row) + "]']")

                end_date.clear()

                slow_type(end_date, pm_labor[labor_row][1].replace(" ", "", 1))

                time.sleep(2)

                # Add start time for PM from start_time list

                element_start_time = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable(
                        (By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:8]_txt-tb[R:" + str(labor_row) + "]']")))

                start_time_text = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:8]_txt-tb[R:" + str(labor_row) + "]']")

                start_time_text.clear()

                slow_type(start_time_text, start_time[counter])

                time.sleep(2)

                # Add end time for PM from end_time list

                element_end_time = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable(
                        (By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:9]_txt-tb[R:" + str(labor_row) + "]']")))

                end_time_text = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:9]_txt-tb[R:" + str(labor_row) + "]']")

                end_time_text.clear()

                slow_type(end_time_text, end_time[counter])

                time.sleep(3)

            except StaleElementReferenceException:

                # Delete row if exception is thrown and continue with loop

                element_delete_row = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable(
                        (By.XPATH,
                         "//*[@id='m900f2d81_tdrow_[C:9]_toggleimage-ti[R:" + str(labor_row) + "]']")))

                driver.find_element(
                    By.XPATH,
                    "//*[@id='m900f2d81_tdrow_[C:9]_toggleimage-ti[R:" + str(labor_row) + "]']").click()

                if labor_row == 0:

                    labor_row = 0

                    continue

                else:

                    labor_row += 0

                    continue

        # If labor rows are filled, then route the PM work order

        for rout in range(0, 3):

            if driver.find_element(By.XPATH, "//*[@id='md489b5d4-tb']").text != "COMP":

                # Click on the route button

                element_route = WebDriverWait(driver, 180, 20, ignore_exceptions).until(
                    ec.element_to_be_clickable((By.XPATH, "//*[@id='ROUTEWF_KAUWO_-tbb_anchor']")))

                route = driver.find_element(By.XPATH, "//*[@id='ROUTEWF_KAUWO_-tbb_anchor']")

                route.click()

                time.sleep(5)

                # Click on OK in the corresponding dialog box

                # element_click_ok = WebDriverWait(driver, 180, 20, ignore_exceptions).until(
                #     ec.element_to_be_clickable((By.XPATH, "//button[@type='button' and @id='md875c1f9-pb']")))
                #
                # click_ok = driver.find_element(By.XPATH, "//button[@type='button' and @id='md875c1f9-pb']")
                #
                # click_ok.click()

                driver.switch_to.alert.accept()

                time.sleep(5)

            else:

                pass

        # Once the PM work order is routed, go back to search field

        element_list_view = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
            ec.visibility_of_element_located((By.XPATH,
                                              "//*[@id='m397b0593-tabs_backToList']/table/tbody/tr/td[1]")))

        list_view = driver.find_element(By.XPATH,
                                        "//*[@id='m397b0593-tabs_backToList']/table/tbody/tr/td[1]")

        time.sleep(2)

        list_view.click()

        time.sleep(2)

        pms_routed = [print(f"WO {pm_actuals[0][i]} is closed.")]

        counter += 1

        time.sleep(2)

        len(pm_availability) - 1

# Log out and quit

element_logout = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
    ec.element_to_be_clickable((
        By.XPATH,
        "//div[@id='m4cd0065c-co_0_div']//*[@id='titlebar_hyperlink_8-co_0']//*[@id='titlebar_hyperlink_8-lbsignout']"))
)

logout = driver.find_element(
    By.XPATH,
    "//div[@id='m4cd0065c-co_0_div']//*[@id='titlebar_hyperlink_8-co_0']//*[@id='titlebar_hyperlink_8-lbsignout']")

logout.click()

time.sleep(2)

element_quit = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
    ec.visibility_of_element_located((By.XPATH, "//*[@id='returnFrm']//*[@id='submit']")))

return_login = driver.find_element(By.XPATH, "//*[@id='returnFrm']//*[@id='submit']")

return_login.click()

time.sleep(2)

driver.quit()

Am I doing something wrong? I have used a 'try-except' block but haven't been able to test it yet but would like feedback if that's how a 'try-except' block is coded. I checked the DOM when working manually, except when creating new rows or adding stuff to my work order, the DOM doesn't really change.

Here is the 'try-except' block:

for labor_row in range(0, len(pm_labor)):

            try:

                # Click on new labor for a new row to enter labor information

                element_new_labor = WebDriverWait(driver, 60, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((By.XPATH, "//*[@id='m4dfd8aef_bg_button_addrow-pb']")))

                new_labor = driver.find_element(By.XPATH, "//*[@id='m4dfd8aef_bg_button_addrow-pb']")

                new_labor.click()

                time.sleep(2)

                # Add labor ID from pm_labour list

                element_labor_id = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((
                        By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:2]_txt-tb[R:" + str(labor_row) + "]']")))

                labor_id = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:2]_txt-tb[R:" + str(labor_row) + "]']")

                labor_id.clear()

                slow_type(labor_id, pm_labor[labor_row][0].replace(" ", "", 1))

                time.sleep(2)

                # Add start date for PM from pm_labour list

                element_start_date = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((
                        By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:6]_txt-tb[R:" + str(labor_row) + "]']")))

                start_date = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:6]_txt-tb[R:" + str(labor_row) + "]']")

                start_date.clear()

                slow_type(start_date, pm_labor[labor_row][1].replace(" ", "", 1))

                time.sleep(2)

                # Add end date for PM from pm_labour list

                element_end_date = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((
                        By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:7]_txt-tb[R:" + str(labor_row) + "]']")))

                end_date = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:7]_txt-tb[R:" + str(labor_row) + "]']")

                end_date.clear()

                slow_type(end_date, pm_labor[labor_row][1].replace(" ", "", 1))

                time.sleep(2)

                # Add start time for PM from start_time list

                element_start_time = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable(
                        (By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:8]_txt-tb[R:" + str(labor_row) + "]']")))

                start_time_text = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:8]_txt-tb[R:" + str(labor_row) + "]']")

                start_time_text.clear()

                slow_type(start_time_text, start_time[counter])

                time.sleep(2)

                # Add end time for PM from end_time list

                element_end_time = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable(
                        (By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:9]_txt-tb[R:" + str(labor_row) + "]']")))

                end_time_text = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:9]_txt-tb[R:" + str(labor_row) + "]']")

                end_time_text.clear()

                slow_type(end_time_text, end_time[counter])

                time.sleep(3)

            except StaleElementReferenceException:

                # Delete row if exception is thrown and continue with loop

                element_delete_row = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable(
                        (By.XPATH,
                         "//*[@id='m900f2d81_tdrow_[C:9]_toggleimage-ti[R:" + str(labor_row) + "]']")))

                driver.find_element(
                    By.XPATH,
                    "//*[@id='m900f2d81_tdrow_[C:9]_toggleimage-ti[R:" + str(labor_row) + "]']").click()

                if labor_row == 0:

                    labor_row = 0

                    continue

                else:

                    labor_row += 0

                    continue

The error is mostly:

StaleElementException: element is not attached to page'

The specific parts where the error occurs is:

(Sometimes the error is thrown in the first iteration itself or it will work fine for the first few iterations and then break again which is more frustrating!)

1.

pm_availability = []

for pm in range(0, len(pm_actuals[0])):

    time.sleep(1)

    ignore_exceptions = (NoSuchElementException, StaleElementReferenceException,)

    element_search_text_wo = WebDriverWait(driver, 120, 5, ignore_exceptions).until(
        ec.visibility_of_element_located((By.XPATH, "//input[@id='m6a7dfd2f_tfrow_[C:1]_txt-tb']")))

    search_text_wo = driver.find_element(By.XPATH, "//input[@id='m6a7dfd2f_tfrow_[C:1]_txt-tb']")

    search_text_wo.clear()

    slow_type(search_text_wo, pm_actuals[0][pm].replace(" ", "", 1))

    action.move_to_element(search_text_wo).send_keys(Keys.RETURN).release().perform()

    element_len_elements_list = WebDriverWait(driver, 120, 5, ignore_exceptions).until(
        ec.visibility_of_any_elements_located((By.XPATH, "//*[contains(@id, 'm6a7dfd2f_tbod_tdrow-tr[R:')]")))

    len_elements_list = driver.find_elements(By.XPATH, "//*[contains(@id, 'm6a7dfd2f_tbod_tdrow-tr[R:')]")

    if len(len_elements_list) != 0:

        # Check if PM status is WSCH

        if driver.find_element(
                By.XPATH,
                "/html/body/form/div/table[2]/tbody/tr/td/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[2]/td/div/table/tbody/tr/td/div/table/tbody/tr/td/table/tbody/tr/td/div/table/tbody/tr/td/table/tbody/tr[2]/td/table/tbody/tr[2]/td/div/table/tbody/tr[3]/td/table/tbody/tr[3]/td/table/tbody/tr[4]/td[10]").text == "WSCH":

            pm_availability.append(pm_actuals[0][pm].replace(" ", "", 1))

            continue

        # If PM status is not WSCH, continue searching

        else:

            continue

    else:

        continue
        for labor_row in range(0, len(pm_labor)):

            try:

                # Click on new labor

                element_new_labor = WebDriverWait(driver, 60, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((By.XPATH, "//*[@id='m4dfd8aef_bg_button_addrow-pb']")))

                new_labor = driver.find_element(By.XPATH, "//*[@id='m4dfd8aef_bg_button_addrow-pb']")

                new_labor.click()

                time.sleep(2)

                # Add labor ID from pm_labour list

                element_labor_id = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((
                        By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:2]_txt-tb[R:" + str(labor_row) + "]']")))

                labor_id = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:2]_txt-tb[R:" + str(labor_row) + "]']")

                labor_id.clear()

                slow_type(labor_id, pm_labor[labor_row][0].replace(" ", "", 1))

                time.sleep(2)

                # Add start date for PM from pm_labour list

                element_start_date = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((
                        By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:6]_txt-tb[R:" + str(labor_row) + "]']")))

                start_date = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:6]_txt-tb[R:" + str(labor_row) + "]']")

                start_date.clear()

                slow_type(start_date, pm_labor[labor_row][1].replace(" ", "", 1))

                time.sleep(2)

                # Add end date for PM from pm_labour list

                element_end_date = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable((
                        By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:7]_txt-tb[R:" + str(labor_row) + "]']")))

                end_date = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:7]_txt-tb[R:" + str(labor_row) + "]']")

                end_date.clear()

                slow_type(end_date, pm_labor[labor_row][1].replace(" ", "", 1))

                time.sleep(2)

                # Add start time for PM from start_time list

                element_start_time = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable(
                        (By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:8]_txt-tb[R:" + str(labor_row) + "]']")))

                start_time_text = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:8]_txt-tb[R:" + str(labor_row) + "]']")

                start_time_text.clear()

                slow_type(start_time_text, start_time[counter])

                time.sleep(2)

                # Add end time for PM from end_time list

                element_end_time = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable(
                        (By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:9]_txt-tb[R:" + str(labor_row) + "]']")))

                end_time_text = driver.find_element(
                    By.XPATH, "//input[@id='m4dfd8aef_tdrow_[C:9]_txt-tb[R:" + str(labor_row) + "]']")

                end_time_text.clear()

                slow_type(end_time_text, end_time[counter])

                time.sleep(3)

            except StaleElementReferenceException:

                element_delete_row = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
                    ec.element_to_be_clickable(
                        (By.XPATH,
                         "//*[@id='m900f2d81_tdrow_[C:9]_toggleimage-ti[R:" + str(labor_row) + "]']")))

                driver.find_element(
                    By.XPATH,
                    "//*[@id='m900f2d81_tdrow_[C:9]_toggleimage-ti[R:" + str(labor_row) + "]']").click()

                if labor_row == 0:

                    labor_row = 0

                    continue

                else:

                    labor_row += 0

                    continue
        for rout in range(0, 3):

            if driver.find_element(By.XPATH, "//*[@id='md489b5d4-tb']").text != "COMP":

                # Click on the route button

                element_route = WebDriverWait(driver, 180, 20, ignore_exceptions).until(
                    ec.element_to_be_clickable((By.XPATH, "//*[@id='ROUTEWF_KAUWO_-tbb_anchor']")))

                route = driver.find_element(By.XPATH, "//*[@id='ROUTEWF_KAUWO_-tbb_anchor']")

                route.click()

                time.sleep(5)

                # Click on OK in the corresponding dialog box

                # element_click_ok = WebDriverWait(driver, 180, 20, ignore_exceptions).until(
                #     ec.element_to_be_clickable((By.XPATH, "//button[@type='button' and @id='md875c1f9-pb']")))
                #
                # click_ok = driver.find_element(By.XPATH, "//button[@type='button' and @id='md875c1f9-pb']")
                #
                # click_ok.click()

                driver.switch_to.alert.accept()

                time.sleep(5)

            else:

                pass

        element_list_view = WebDriverWait(driver, 30, 5, ignore_exceptions).until(
            ec.visibility_of_element_located((By.XPATH,
                                              "//*[@id='m397b0593-tabs_backToList']/table/tbody/tr/td[1]")))

        list_view = driver.find_element(By.XPATH,
                                        "//*[@id='m397b0593-tabs_backToList']/table/tbody/tr/td[1]")

        time.sleep(2)

        list_view.click()

        time.sleep(2)

        pms_routed = [print(f"WO {pm_actuals[0][i]} is closed.")]

        counter += 1

        time.sleep(2)

        len(pm_availability) - 1

Solution

  • StaleElementException: element is not attached to page
    

    ...implies that the previous reference of the element is now stale and the element reference is no longer present in the current state of the HTML DOM of the page.

    The common reasons behind this this exception can be either of the following:


    This usecase

    Your suspicion "when I start clicking on text fields on each new row that I get errors. It's as if adding a new row changes the whole DOM" is absolutely correct as "creates another table in the DOM" definitely changes the position of the previously identified element within the DOM Tree though others remain unchanged.


    References

    You can find a couple of relevant detailed discussions in: