I'm building a script that automates going through a survey for work. I build surveys and I'm trying to create a script that checks that the surveys I build are working. Everything is fine up to a point where it simply crashes. I can't even tell from where. I keep having different errors occurring. The most recent is running into a stale error when working with multi_grid questions. I suspect it relates to the dom refreshing. The script creates a question type dictionary and if it runs into any of the dictionary questions it runs a sequence of entries and clicks. My issue is occuring when running into multi_grid questions where the element is not being clicked and it crashes. The process is the same as single_grid, but it will select more than one random element. def start_testing(): try: str_base_url = entry_url.get() int_num_tests = int(entry_tests.get()) if not str_base_url or int_num_tests <= 0: messagebox.showerror("Error", "Please enter both a valid URL and a positive number of respondents.") return driver = webdriver.Chrome() action = ActionChains(driver) for i in range(1, int_num_tests + 1): str_test_url = f"{str_base_url}&altid=myj_trial_27_{i}" driver.get(str_test_url) # Switch to the first iframe (index 0) try: driver.switch_to.frame(0) # Switch to the first iframe by index except NoSuchFrameException: print("Survey iframe not found.") continue while True: # Check if last page (completion page) is reached try: WebDriverWait(driver, 3).until( EC.presence_of_element_located((By.CLASS_NAME, "lastPageText")) ) print(f"Test {i}/{int_num_tests} complete.") break # End the test for this respondent except TimeoutException: pass # Continue if last page is not reached # Locate question elements inside the iframe lst_cCheck = driver.find_elements(By.CLASS_NAME, "cCheck") lst_cRadio = driver.find_elements(By.CLASS_NAME, "cRadio") lst_cTextInput = driver.find_elements(By.CLASS_NAME, "cTextInput") lst_cTextArea = driver.find_elements(By.CLASS_NAME, "cTextArea") lst_cFInput = driver.find_elements(By.CLASS_NAME, "cFInput") lst_cBtnSingleGrid = driver.find_elements(By.XPATH, "//div[@id='SingleGridQ_btn']/div/div/div/p") lst_cBtnMultiGrid = driver.find_elements(By.XPATH, "//div[@id='MultiGridQ_btn']/div/div/p") lst_cSay = driver.find_elements(By.CLASS_NAME, "cSay") lst_dropdowns = driver.find_elements(By.ID, "n0A") # Locate dropdowns # Store non-empty question types dict_question_types = { "multi_select": lst_cCheck, "single_select": lst_cRadio, "short_text": lst_cTextInput, "long_text": lst_cTextArea, "numeric_input": lst_cFInput, "single_select_grid": lst_cBtnSingleGrid, "dropdown": lst_dropdowns, "multi_select_grid": lst_cBtnMultiGrid } dict_question_types = {k: v for k, v in dict_question_types.items() if v} # Interact with question types if they exist if dict_question_types: str_selected_type = random.choice(list(dict_question_types.keys())) obj_elements = dict_question_types[str_selected_type] if str_selected_type == "multi_select": # Randomly select up to the total number of checkboxes int_num_checks = random.randint(1, len(obj_elements)) for obj_checkbox in random.sample(obj_elements, int_num_checks): action.click(obj_checkbox).perform() elif str_selected_type == "single_select": obj_random_radio = random.choice(obj_elements) action.click(obj_random_radio).perform() elif str_selected_type == "short_text": obj_text_input = random.choice(obj_elements) driver.execute_script("arguments[0].value = arguments[1];", obj_text_input, str_short_text) elif str_selected_type == "long_text": obj_text_area = random.choice(obj_elements) driver.execute_script("arguments[0].value = arguments[1];", obj_text_area, str_long_text) elif str_selected_type == "numeric_input": for obj_numeric_input in obj_elements: random_number = random.randint(1, 10) driver.execute_script("arguments[0].value = arguments[1];", obj_numeric_input, random_number) elif str_selected_type == "single_select_grid": # Keep selecting and clicking .cBtnSingleGrid until there are no more available while obj_elements: obj_grid_option = random.choice(obj_elements) driver.execute_script("arguments[0].click();", obj_grid_option) # Refresh the list of grid options after clicking obj_elements = driver.find_elements(By.XPATH, "//div[@id='SingleGridQ_btn']/div/div/div/p") print("All single grid options have been selected.") elif str_selected_type == "multi_select_grid": # Randomly select multiple grid options while obj_elements: int_num_checks = random.randint(1, len(obj_elements)) selected_options = random.sample(obj_elements, int_num_checks) for obj_grid_option in selected_options: driver.execute_script("arguments[0].click();", obj_grid_option) obj_elements = driver.find_elements(By.XPATH, "//div[@id='MultiGridQ_btn']/div/div/p") # Click the Next button after each selection set try: btn_next = WebDriverWait(driver, 5).until( EC.element_to_be_clickable((By.ID, "btnNext")) ) action.click(btn_next).perform() except TimeoutException: print("Next button not found or not clickable.") break # Refresh the list of grid options after clicking Next obj_elements = driver.find_elements(By.XPATH, "//div[@id='MultiGridQ_btn']/div/div/p") print("All multi-select grid options have been selected.") elif str_selected_type == "dropdown": for dropdown in obj_elements: # Click the dropdown to expand it dropdown.click() # Wait for options to be available time.sleep(0.5) # Optional delay to allow options to load # Locate the options within the dropdown options = dropdown.find_elements(By.TAG_NAME, "option") # Filter out options with a value of -1 valid_options = [option for option in options if option.get_attribute("value") != "-1"] if valid_options: # Select a random option from the filtered list random_option = random.choice(valid_options) random_option.click() # After processing the question types, click the Next button try: if str_selected_type != "single_select_grid" and str_selected_type != "multi_select_grid": btn_next = WebDriverWait(driver, 5).until( EC.element_to_be_clickable((By.ID, "btnNext")) ) action.click(btn_next).perform() continue # Move to the next page except TimeoutException: print("Next button not found or not clickable.") break # If no question types are available but .cSay exists, click 'Next' elif lst_cSay: try: btn_next = WebDriverWait(driver, 5).until( EC.element_to_be_clickable((By.ID, "btnNext")) ) action.click(btn_next).perform() continue # Move to the next page except TimeoutException: print("Next button not found or not clickable.") break # If neither question types nor .cSay are present, break out else: print("No actionable elements found.") break except Exception as e: print(f"An error occurred: {e}") finally: driver.quit() messagebox.showinfo("Completed", f"Tested {int_num_tests} survey links.") root.destroy() Continue reading...