'Is there a way to refresh HTML dom when Selenium cannot locate an element?

I'm attempting to submit a login form using Selenium and Chromedriver. The form contains a username field, a password field, a checkbox and a log in button. I am able to enter the username, enter the password, and check the checkbox. But I haven't been able to figure out how to click the log in button.

When a user clicks through the form, upon checking the checkbox, the content of the HTML of the Log In button changes from...

<button tabindex="4" step="1" type="submit" 
class="btn-primary login disable login-disabled" 
id="login-submit" disabled="">Log In</button>

... to:

<button tabindex="4" step="1" type="submit" 
class="btn-primary login" 
id="login-submit">Log In</button>

This same behavior (the removal of the disable and login-disabled classes) occurs when my script clicks the captcha checkbox.

Here is the problematic code, where I've attempted to handle all possible locator handlers, but have still been unable to locate the button element:

def try_click_with_all_locator_strategies(id=None, xpath=None, link_text=None, partial_link_text=None, name=None, tag_name=None, class_name=None, css_selector=None):
    by_fields = []
    by_fields.append((By.ID, id)) if id else None
    by_fields.append((By.XPATH, xpath)) if xpath else None
    by_fields.append((By.LINK_TEXT, link_text)) if link_text else None
    by_fields.append((By.PARTIAL_LINK_TEXT, partial_link_text)) if partial_link_text else None
    by_fields.append((By.NAME, name)) if name else None
    by_fields.append((By.TAG_NAME, tag_name)) if tag_name else None
    by_fields.append((By.CLASS_NAME, class_name)) if class_name else None
    by_fields.append((By.CSS_SELECTOR, css_selector)) if css_selector else None

    found = False
    for (by_key, by_value) in by_fields:
        try:
            time.sleep(0.5)
            driver.implicitly_wait(10)
            element = driver.find_element(by=by_key, value=by_value)
            element.click()
            found = True
        except NoSuchElementException:
            print('unable to find via', by_value)
    if not found:
        print('Unable to find using any locator strategy')

try_click_with_all_locator_strategies(
    id="#login-submit", 
    xpath="/html/body/div[5]/div[1]/div/div[1]/div/form/button", 
    link_text='Log In', 
    class_name="btn-primary", 
    css_selector="#login-submit"
    )

Any help or ideas would be appreciated!



Solution 1:[1]

Aha! It turned out the answer was related to frames. To troubleshoot, I ended up printing out all the IDs on the page (referenced Python & Selenium - how do I find all element IDs on a page?), and that ended up printing only a few of the ids that it should have. It turned out that when I clicked the checkbox, it had modified the current frame.

To solve this I just needed to switch out and get to the main frame, then proceed.

driver.switch_to.parent_frame()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Asa