pythonlover12345
pythonlover12345

Reputation: 43

robotframework+Selenium: How to wait until page reloaded

When I click the button, it triggers the current page to be reloaded(assuming all displayed contents are the same). How do I wait for the reloading process?

In a situation where the code below fails,

    Click Element    btn1    # btn1 triggers the current page to be reloaded
    Wait Until Element Is Visible    btn2    timeout=10s    # This line succeeds because the page is yet reloaded and btn2(not refreshed, old one) is visble
    Click Element      btn2    # This line fails because the page is not yet stable 

how could I implement the code like below?

    Click Element    btn1
    **Wait Until The Current Page Is Reloaded And Became Stable Again**
    Click Element      btn2

Upvotes: 0

Views: 2284

Answers (2)

Bryan Oakley
Bryan Oakley

Reputation: 386210

A technique that has worked well for me is to write a keyword in python that does the following:

  • get a reference to the <html> element,
  • do the action that causes the page to be refreshed,
  • use the selenium method that allows you to wait for the element to go stale (so that you know the refresh has begun)
  • wait for the javascript variable document.readState to be "complete" (so that you know that the refresh is finished)
  • optionally wait for anything else you might need for your specific application (so that you know that your app is ready)

If you implement it as a context manager, you can put the code to trigger the refresh inside the body of the with statement.

This is the implementation I used in my page object library

class PageObject(six.with_metaclass(ABCMeta, object)):
    ...
    @property
    def selib(self):
        return self.builtin.get_library_instance("SeleniumLibrary")

    @property
    def browser(self):
        return self.selib._current_browser()

    @contextmanager
    def _wait_for_page_refresh(self, timeout=10):
        """Context manager that waits for a page transition.

        This keyword works by waiting for two things to happen:

        1) the <html> tag to go stale and get replaced, and
        2) the javascript document.readyState variable to be set
           to "complete"
        """
        old_page = self.browser.find_element_by_tag_name('html')
        yield
        WebDriverWait(self.browser, timeout).until(
            staleness_of(old_page),
            message="Old page did not go stale within %ss" % timeout
        )
        self.selib.wait_for_condition("return (document.readyState == 'complete')", timeout=10)

You could then use it in your own library keyword with something like this:

class LoginPage(PageObject):
    ...
    def click_the_submit_button(self):
        """Click the submit button, and wait for the page to reload"""
        with self._wait_for_page_refresh():
            self.selib.click_button(self.locator.submit_button)

Upvotes: 1

pavelsaman
pavelsaman

Reputation: 8352

Leaving the discussion about what it means a stable page aside, this could work. It's what was suggested in the comment section:

Click Element    btn1
Wait Until Element Is Not Visible    btn2    timeout=10
Wait Until Element Is Visible    btn2    timeout=10
Click Element      btn2

Upvotes: 1

Related Questions