from contextlib import contextmanager
from selenium.common.exceptions import NoSuchWindowException
import nerodia
[docs]class AfterHooks(object):
"""
After hooks are blocks that run after certain browser events.
They are generally used to ensure application under test does not encounter
any error and are automatically executed after following events:
1. Open URL.
2. Refresh page.
3. Click, double-click or right-click on element.
4. Alert closing.
"""
def __init__(self, browser):
self.browser = browser
self.after_hooks = []
[docs] def add(self, method=None, after_hook=None):
"""
Adds new after hook
:param method: callable method
:param after_hook: callable object
:Example:
from __future__ import print_function
browser.after_hooks.add(method=lambda b: 'Server Error' in browser.text and \
print('Application exception or 500 error!')
browser.goto('watir.github.io/404') #=> 'Application exception or 500 error!'
"""
if method:
self.after_hooks.append(method)
elif callable(after_hook):
self.after_hooks.append(after_hook)
else:
raise ValueError('expected method or callable class')
[docs] def delete(self, after_hook):
"""
Deletes after hook
:param after_hook: hook to delete
:Example:
from __future__ import print_function
browser.after_hooks.add(method=lambda b: 'Server Error' in browser.text and \
print('Application exception or 500 error!')
browser.goto('watir.github.io/404') #=> 'Application exception or 500 error!'
browser.after_hooks.delete(browser.after_hooks[0])
browser.refresh
"""
self.after_hooks.remove(after_hook)
[docs] def run(self):
""" Runs after hooks """
# We can't just rescue exception because Firefox automatically closes alert when
# exception raised
try:
if self.after_hooks and not self.browser.alert.exists:
for hook in self.after_hooks:
hook(self.browser)
except NoSuchWindowException as e:
nerodia.logger.info('Could not execute After Hooks because browser window was '
'closed {}'.format(e))
[docs] @contextmanager
def without(self):
"""
Executes a block without running error after hooks
:Example:
with browser.after_hooks.without():
self.browser.element(name='new_user_button').click()
"""
current_after_hooks = self.after_hooks
self.after_hooks = []
yield
self.after_hooks = current_after_hooks
def __len__(self):
"""
Returns number of after hooks
:rtype: int
:Example:
browser.after_hooks.add(method=lambda b: print('Some after_hook'))
len(browser.after_hooks) #=> 1
"""
return len(self.after_hooks)
def __getitem__(self, index):
"""
Gets the after hook at the given index
:param index: index of the after hook
:return: callable object
"""
return self.after_hooks[index]