Selenium python transfer webelement from one list to another

I have two lists: unused elements (filled out) and used elements. They are work as filter and I need to select elements from first one and adding them to second by button or double click. The issue: I can simply iterate through first list with code:

offers = app.driver.find_elements_by_tag_name('option')
for offer in offers:
    if "21796" in offer.get_attribute("text"):
        app.driver.find_elements_by_tag_name("option")offers.index(offer)].click()

In this case I see how offers are selected one by one. But when I try to add selected offer to second list with:

offers = app.driver.find_elements_by_tag_name('option')
for offer in offers:
    if "21796" in offer.get_attribute("text"):
        app.driver.find_elements_by_tag_name("option")offers.index(offer)].click()
        app.driver.find_element_by_name("add").click()

or

offers = app.driver.find_elements_by_tag_name('option')
double_click = ActionChains(app.driver)
for offer in offers:
    if "21796" in offer.get_attribute("text"):
        double_click.double_click(app.driver.find_elements_by_tag_name("option")[offers.index(offer)]).perform()

I get the error:

    for offer in offers:
      > if "21796" in offer.get_attribute("text"):
...
    if exception_class == ErrorInResponseException:
        raise exception_class(response, message)
    elif exception_class == UnexpectedAlertPresentException and 'alert' in value:
        raise exception_class(message, screen, stacktrace, value['alert'].get('text'))
  > raise exception_class(message, screen, stacktrace)
E       StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
E         (Session info: chrome=42.0.2311.90)
E         (Driver info: chromedriver=2.9.248315,platform=Windows NT 6.3 x86_64)

Why do on adding second action in "if" statement I losing webelement?


ANSWERS:


The issue you're facing is that there is probably something that causes the list of elements you are looking at to change while you are processing your list. This is wholly dependent on the JavaScript that runs in the page you are accessing, which you do not show. Note that even if from your perspective you do not see the list change, some implementations will treat events as clicks as a sign to refresh their list and, if the data to be displayed has in fact not change, they may still replace all the DOM elements that form the list with new DOM elements that look exactly the same as the old ones. So even tough the list looks the same, the DOM elements in the list are new, and this would cause problems for Selenium code like yours. This looks like a likely candidate for something that would trigger a list refresh: app.driver.find_element_by_name("add").click()

You reacquire the list when you do app.driver.find_elements_by_tag_name("option")[offers.index(offer)].click() but you do not reacquire the list when you do offer.get_attribute("text") so this command may refer to a DOM element which is no longer in the document, and Selenium chokes.

You do not show enough information in your question to figure a solution that would fix the problem and be the most efficient at performing the task you want. You can replace all instances of offer with app.driver.find_elements_by_tag_name("option")[offers.index(offer)] but this would be terribly inefficient. If the only thing that changes the list is clicking the "add" button, something like this should work:

offers = app.driver.find_elements_by_tag_name('option')
for x in range(0, len(offers)):
    if "21796" in offer[x].get_attribute("text"):
        offers[x].click()
        app.driver.find_element_by_name("add").click()
        # Reacquire the list after adding!
        offers = app.driver.find_elements_by_tag_name('option')

The code above assumes that the only thing that changes the list is clicking the "add" button. It also assumes that except for the stale element issue, your original code was correct. And it is not impossible that there could be a more efficient way to do it but that depends on details not present in the question.



 MORE:


 ? Python: cycle through elements in list reversing when the end is reached
 ? (Python, Selenium WD) How to automate these actions - cycle or function?
 ? (Python, Selenium WD) How to automate these actions - cycle or function?
 ? (Python, Selenium WD) How to automate these actions - cycle or function?
 ? What would be the best way to handle multiple actions in Python browser automation (with Selenium)?
 ? Using a Selenium function in an Python / SST automation script
 ? function that checks the length of the cycle
 ? Python Selenium click function does not perform any action, test is not failing
 ? Implementing 'click()' function in Python 3 for automation with Selenium.
 ? How to check if a linked list has a cycle in Java?