Do Not Exist in DOM

I have a function where I want to wait for an element with given text. I use Appium with behave. But O always get the same error even though I tried everything.

@step("Wait until text \"{text}\" shows up with {timeout_sec:n} timeout seconds")
def wait_until_text_visible(context, text, timeout_sec):
    check_context(context.driver, "NATIVE_APP")
    timeout = time.time() + timeout_sec

    while True:
        if time.time() > timeout:
            # Raise a TimeoutException with a custom message and stack trace
            message = f"Timeout occurred while searching for element with text '{text}'."
            stack_trace = traceback.format_exc()  # Get the current stack trace
            raise TimeoutException(message) from Exception(stack_trace)

        all_elements = [view.text for view in context.driver.find_elements(AppiumBy.XPATH, '//*')]

        if text in all_elements:
            break
        else:
            time.sleep(2)

This is my function and the error I get is:
selenium.common.exceptions.StaleElementReferenceException: Message: Cached elements ‘By.xpath: //*’ do not exist in DOM anymore;

How can I fix this?

Try anther approach. Instead of

all_elements = [view.text for view in context.driver.find_elements(AppiumBy.XPATH, '//*')]

if text in all_elements:
    break

use

try:
    context.driver.find_element(f'//*[@text="{text}"]')
    break
except NoSuchElement:
   time.sleep(2)
1 Like

Thanks, not the exact thing you wrote worked but f'//*[@text="{text}"] is the way to go! At the end I used

@step("Wait until text \"{text}\" shows up with {timeout_sec:n} timeout seconds")
def wait_until_text_visible(context, text, timeout_sec):
    check_context(context.driver, "NATIVE_APP")
    wait_for_element(context.driver, AppiumBy.XPATH, f'//*[contains(lower-case(@text), lower-case({text}"))]', timeout_sec)

def wait_for_element(driver: 'WebDriver', locator: str, value: str, timeout_sec: float = 10) -> 'WebElement':
    return WebDriverWait(driver, timeout_sec).until(EC.presence_of_element_located((locator, value)))

Once I figured that I can use @text, I handled everything like this.