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
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:
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.
You can find a couple of relevant detailed discussions in: