Warning

This document is for an in-development version of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.

Source code for galaxy.selenium.navigates_galaxy

"""A mixing that extends a HasDriver class with Galaxy-specific utilities.

Implementer must provide a self.build_url method to target Galaxy.
"""

import collections
import contextlib
import random
import string
import time
from functools import partial, wraps

import requests
import yaml

from galaxy.util.bunch import Bunch
from . import sizzle
from .data import (
    NAVIGATION,
)
from .has_driver import (
    exception_indicates_not_clickable,
    exception_indicates_stale_element,
    HasDriver,
    TimeoutException,
)
from .smart_components import SmartComponent

# Test case data
DEFAULT_PASSWORD = '123456'

RETRY_DURING_TRANSITIONS_SLEEP_DEFAULT = .1
RETRY_DURING_TRANSITIONS_ATTEMPTS_DEFAULT = 10

WaitType = collections.namedtuple("WaitType", ["name", "default_length"])

# Default wait times should make sense for a development server under low
# load. Wait times for production servers can be scaled up with a multiplier.
WAIT_TYPES = Bunch(
    # Rendering a form and registering callbacks, etc...
    UX_RENDER=WaitType("ux_render", 1),
    # Fade in, fade out, etc...
    UX_TRANSITION=WaitType("ux_transition", 5),
    # Toastr popup and dismissal, etc...
    UX_POPUP=WaitType("ux_popup", 15),
    # Creating a new history and loading it into the panel.
    DATABASE_OPERATION=WaitType("database_operation", 10),
    # Wait time for jobs to complete in default environment.
    JOB_COMPLETION=WaitType("job_completion", 30),
    # Wait time for a GIE to spawn.
    GIE_SPAWN=WaitType("gie_spawn", 30),
    # Wait time for toolshed search
    SHED_SEARCH=WaitType('shed_search', 30),
    # Wait time for repository installation
    REPO_INSTALL=WaitType('repo_install', 60),
)

# Choose a moderate wait type for operations that don't specify a type.
DEFAULT_WAIT_TYPE = WAIT_TYPES.DATABASE_OPERATION


[docs]class NullTourCallback:
[docs] def handle_step(self, step, step_index): pass
[docs]def exception_seems_to_indicate_transition(e): """True if exception seems to indicate the page state is transitioning. Galaxy features many different transition effects that change the page state over time. These transitions make it slightly more difficult to test Galaxy because atomic input actions take an indeterminate amount of time to be reflected on the screen. This method takes a Selenium assertion and tries to infer if such a transition could be the root cause of the exception. The methods that follow use it to allow retrying actions during transitions. Currently the two kinds of exceptions that we say may indicate a transition are StaleElement exceptions (a DOM element grabbed at one step is no longer available) and "not clickable" exceptions (so perhaps a popup modal is blocking a click). """ return exception_indicates_stale_element(e) or exception_indicates_not_clickable(e)
[docs]def retry_call_during_transitions(f, attempts=RETRY_DURING_TRANSITIONS_ATTEMPTS_DEFAULT, sleep=RETRY_DURING_TRANSITIONS_SLEEP_DEFAULT, exception_check=exception_seems_to_indicate_transition): previous_attempts = 0 while True: try: return f() except Exception as e: if previous_attempts > attempts: raise if not exception_check(e): raise time.sleep(sleep) previous_attempts += 1
[docs]def retry_during_transitions(f, attempts=RETRY_DURING_TRANSITIONS_ATTEMPTS_DEFAULT, sleep=RETRY_DURING_TRANSITIONS_SLEEP_DEFAULT, exception_check=exception_seems_to_indicate_transition): @wraps(f) def _retry(*args, **kwds): return retry_call_during_transitions(partial(f, *args, **kwds), attempts=attempts, sleep=sleep, exception_check=exception_check) return _retry
[docs]class NotLoggedInException(TimeoutException):
[docs] def __init__(self, timeout_exception, user_info, dom_message): template = "Waiting for UI to reflect user logged in but it did not occur. API indicates no user is currently logged in. %s API response was [%s]. %s" msg = template % (dom_message, user_info, timeout_exception.msg) super().__init__( msg=msg, screen=timeout_exception.screen, stacktrace=timeout_exception.stacktrace )