Source code for webdriverwrapper.errors

from selenium.common.exceptions import NoSuchElementException

from .exceptions import ErrorPageException, ErrorMessagesException, JSErrorsException

__all__ = (
    'expected_error_page',
    'allowed_error_pages',
    'expected_error_messages',
    'allowed_error_messages',
    'allowed_any_error_message',
)

EXPECTED_ERROR_PAGE = '__expected_error_page__'
ALLOWED_ERROR_PAGES = '__allowed_error_pages__'
EXPECTED_ERROR_MESSAGES = '__expected_error_messages__'
ALLOWED_ERROR_MESSAGES = '__allowed_error_messages__'


[docs]def expected_error_page(error_page): """ Decorator expecting defined error page at the end of test method. As param use what :py:meth:`~.WebdriverWrapperErrorMixin.get_error_page` returns. .. versionadded:: 2.0 Before this decorator was called ``ShouldBeErrorPage``. """ def wrapper(func): setattr(func, EXPECTED_ERROR_PAGE, error_page) return func return wrapper
[docs]def allowed_error_pages(*error_pages): """ Decorator ignoring defined error pages at the end of test method. As param use what :py:meth:`~.WebdriverWrapperErrorMixin.get_error_page` returns. .. versionadded:: 2.0 """ def wrapper(func): setattr(func, ALLOWED_ERROR_PAGES, error_pages) return func return wrapper
[docs]def expected_error_messages(*error_messages): """ Decorator expecting defined error messages at the end of test method. As param use what :py:meth:`~.WebdriverWrapperErrorMixin.get_error_messages` returns. .. versionadded:: 2.0 Before this decorator was called ``ShouldBeError``. """ def wrapper(func): setattr(func, EXPECTED_ERROR_MESSAGES, error_messages) return func return wrapper
[docs]def allowed_error_messages(*error_messages): """ Decorator ignoring defined error messages at the end of test method. As param use what :py:meth:`~.WebdriverWrapperErrorMixin.get_error_messages` returns. .. versionadded:: 2.0 Before this decorator was called ``CanBeError``. """ def wrapper(func): setattr(func, ALLOWED_ERROR_MESSAGES, error_messages) return func return wrapper
[docs]def allowed_any_error_message(func): """ Decorator ignoring any error messages at the end of test method. If you want allow only specific error message, use :py:func:`.allowed_error_messages` instead. .. versionadded:: 2.0 """ setattr(func, ALLOWED_ERROR_MESSAGES, ANY) return func
class ANY: pass
[docs]class WebdriverWrapperErrorMixin: """ Mixin used in :py:obj:`~webdriverwrapper.wrapper._WebdriverWrapper`. .. versionadded:: 2.0 Before you had to change decorators ``ShouldByError``, ``CanBeError`` and ``ShouldBeErrorPage`` which are gone. Now you can use original decorators and just change one of these methods. For more information check out section testing. """
[docs] def check_expected_errors(self, test_method): """ This method is called after each test. It will read decorated informations and check if there are expected errors. You can set expected errors by decorators :py:func:`.expected_error_page`, :py:func:`.allowed_error_pages`, :py:func:`.expected_error_messages`, :py:func:`.allowed_error_messages` and :py:func:`.allowed_any_error_message`. """ f = lambda key, default=[]: getattr(test_method, key, default) expected_error_page = f(EXPECTED_ERROR_PAGE, default=None) allowed_error_pages = f(ALLOWED_ERROR_PAGES) expected_error_messages = f(EXPECTED_ERROR_MESSAGES) allowed_error_messages = f(ALLOWED_ERROR_MESSAGES) self.check_errors( expected_error_page, allowed_error_pages, expected_error_messages, allowed_error_messages, )
[docs] def check_errors(self, expected_error_page=None, allowed_error_pages=[], expected_error_messages=[], allowed_error_messages=[]): """ This method should be called whenever you need to check if there is some error. Normally you need only ``check_expected_errors`` called after each test (which you specify only once), but it will check errors only at the end of test. When you have big use case and you need to be sure that on every step is not any error, use this. To parameters you should pass same values like to decorators :py:func:`.expected_error_page`, :py:func:`.allowed_error_pages`, :py:func:`.expected_error_messages` and :py:func:`.allowed_error_messages`. """ # Close unexpected alerts (it's blocking). self.close_alert(ignore_exception=True) expected_error_pages = set([expected_error_page]) if expected_error_page else set() allowed_error_pages = set(allowed_error_pages) error_page = self.get_error_page() error_pages = set([error_page]) if error_page else set() if ( error_pages & expected_error_pages != expected_error_pages or error_pages - (expected_error_pages | allowed_error_pages) ): traceback = self.get_error_traceback() raise ErrorPageException(self.current_url, error_page, expected_error_page, allowed_error_pages, traceback) error_messages = set(self.get_error_messages()) expected_error_messages = set(expected_error_messages) allowed_error_messages = error_messages if allowed_error_messages is ANY else set(allowed_error_messages) if ( error_messages & expected_error_messages != expected_error_messages or error_messages - (expected_error_messages | allowed_error_messages) ): raise ErrorMessagesException(self.current_url, error_messages, expected_error_messages, allowed_error_messages) js_errors = self.get_js_errors() if js_errors: raise JSErrorsException(self.current_url, js_errors)
[docs] def get_error_page(self): """ Method returning error page. Should return string. By default it find element with class ``error-page`` and returns text of ``h1`` header. You can change this method accordingly to your app. Error page returned from this method is used in decorators :py:func:`.expected_error_page` and :py:func:`.allowed_error_pages`. """ try: error_page = self.get_elm(class_name='error-page') except NoSuchElementException: pass else: header = error_page.get_elm(tag_name='h1') return header.text
[docs] def get_error_traceback(self): """ Method returning traceback of error page. By default it find element with class ``error-page`` and returns text of element with class ``traceback``. You can change this method accordingly to your app. """ try: error_page = self.get_elm(class_name='error-page') traceback = error_page.get_elm(class_name='traceback') except NoSuchElementException: pass else: return traceback.text
[docs] def get_error_messages(self): """ Method returning error messages. Should return list of messages. By default it find element with class ``error`` and theirs value in attribute ``error`` or text if that attribute is missing. You can change this method accordingly to your app. Error messages returned from this method are used in decorators :py:func:`.expected_error_messages` and :py:func:`.allowed_error_messages`. """ try: error_elms = self.get_elms(class_name='error') except NoSuchElementException: return [] else: try: error_values = [error_elm.get_attribute('error') for error_elm in error_elms] except Exception: error_values = [error_elm.text for error_elm in error_elms] finally: return error_values
[docs] def get_js_errors(self): """ Method returning JS errors. Should return list of errors. You have to include following JS snippet to your web app which will record all JS errors and this method will automatically read them. .. code-block:: html <script type="text/javascript"> window.jsErrors = []; window.onerror = function(errorMessage) { window.jsErrors[window.jsErrors.length] = errorMessage; } </script> """ return self.execute_script('return window.jsErrors')