-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathbase.py
137 lines (108 loc) · 4.64 KB
/
base.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import urllib.parse
from time import sleep
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
import settings
from base.exceptions import HttpError, PageException
from base.locators import BaseElement, ComponentLocator
from components.navbars import HomeNavbar
class BasePage(BaseElement):
url = None
def __init__(self, driver, verify=False):
super().__init__(driver)
if verify:
self.check_page()
def goto(self, expect_redirect_to=None):
"""Navigate to a page based on its `url` attribute
and confirms you are on the expected page.
If you are not actually expecting to end up on the page you attempt to `goto`
(for example when testing permissions) you can set `expect_redirect_to` equal to
any BasePage class and it will be verified you wind up on that page instead.
"""
self.driver.get(self.url)
if expect_redirect_to:
if self.url not in self.driver.current_url:
raise PageException(
'Unexpected url structure: `{}`'.format(self.driver.current_url)
)
expect_redirect_to(self.driver, verify=True)
else:
self.check_page()
def goto_with_reload(self):
"""An extension of the goto method above to be used in instances where the first attempt
to load a page takes too long or hangs. This can often happen while running remotely using
BrowserStack. If the first attempt at goto fails then we want to refresh the page and try
to load the page again. This method serves as a workaround solution to issues that we are
having while running the nightly Selenium test suites in BrowserStack. It does not replace
the existing goto method that is called by most of the Selenium tests. This method will
only be called by tests that experience page loading timeout issues in BrowserStack.
(ex: test_navbar.py)
"""
try:
self.goto()
except PageException:
self.reload()
self.goto()
def check_page(self):
if not self.verify():
# handle any specific kind of error before go to page exception
self.error_handling()
raise PageException(
'Unexpected page structure: `{}`'.format(self.driver.current_url)
)
def verify(self):
"""Verify that you are on the expected page by confirming the page's `identity`
element is present on the page.
"""
return self.identity.present()
def error_handling(self):
pass
def reload(self):
self.driver.refresh()
def scroll_into_view(self, element):
self.driver.execute_script('arguments[0].scrollIntoView(false);', element)
# Account for navbar
self.driver.execute_script('window.scrollBy(0, 55)')
def drag_and_drop(self, source_element, dest_element):
source_element.click()
ActionChains(self.driver).drag_and_drop(source_element, dest_element).perform()
# Note: If you close the browser too quickly, the drag/drop may not go through
sleep(1)
class OSFBasePage(BasePage):
"""
Note: All pages must have a unique identity or overwrite `verify`
"""
url = settings.OSF_HOME
navbar = ComponentLocator(HomeNavbar)
def __init__(self, driver, verify=False):
super().__init__(driver, verify)
def find_error_heading_element(self):
try:
error_head = self.driver.find_element(By.CSS_SELECTOR, 'h2#error')
except NoSuchElementException:
return None
else:
return error_head
def error_handling(self):
# If we've got an error message here from osf, grab it
error_heading = self.find_error_heading_element()
if error_heading:
raise HttpError(error_heading.get_attribute('data-http-status-code'))
def is_logged_in(self):
return self.navbar.is_logged_in()
def is_logged_out(self):
return self.navbar.is_logged_out()
class GuidBasePage(OSFBasePage):
base_url = urllib.parse.urljoin(settings.OSF_HOME, '{guid}')
guid = ''
def __init__(self, driver, verify=False, guid='', domain=settings.OSF_HOME):
super().__init__(driver, verify)
# self.domain = domain
self.guid = guid
@property
def url(self):
if '{guid}' in self.base_url:
return self.base_url.format(guid=self.guid)
else:
raise ValueError('No space in base_url for GUID specified.')