A decorator to ensure a function is run with jQuery available.

    If an exception from a function indicates jQuery is missing, it is loaded
    and the function re-executed.

    The browser to load jQuery into must be the first argument of the function.

def load_jquery(func):
    """
    A decorator to ensure a function is run with jQuery available.

    If an exception from a function indicates jQuery is missing, it is loaded
    and the function re-executed.

    The browser to load jQuery into must be the first argument of the function.
    """

    @wraps(func)
    def wrapped(browser, *args, **kwargs):
        """Run the function, loading jQuery if needed."""

        try:
            return func(browser, *args, **kwargs)
        except WebDriverException as ex:
            if not is_jquery_not_defined_error(ex.msg):
                raise

            load_script(browser, JQUERY)

            @wait_for
            def jquery_available():
                """Assert that jQuery has loaded."""
                try:
                    return browser.execute_script('return $')
                except WebDriverException:
                    raise AssertionError("jQuery is not loaded")

            jquery_available()

            return func(browser, *args, **kwargs)

    return wrapped