forked from cryzed/Selenium-Requests
-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_seleniumrequests.py
183 lines (142 loc) · 7.05 KB
/
test_seleniumrequests.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import json
import socket
import threading
import pytest
import requests
import six
from six.moves import BaseHTTPServer, http_cookies
from seleniumrequests import Firefox, Chrome, Ie, Edge, Opera, Safari, BlackBerry, PhantomJS, Android, Remote
from seleniumrequests.request import get_unused_port, get_tld
WEBDRIVER_CLASSES = Firefox, Chrome, Ie, Edge, Opera, Safari, BlackBerry, PhantomJS, Android, Remote
class DummyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(six.b('<html></html>'))
# Suppress unwanted logging to stderr
def log_message(self, format, *args):
pass
class EchoHeaderRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
# Python 2's HTTPMessage class contains the actual data in its
# "dict"-attribute, whereas in Python 3 HTTPMessage is itself the
# container. Treat headers as case-insensitive
data = json.dumps(dict(self.headers) if six.PY3 else self.headers.dict)
self.send_response(200)
# Send JSON data in a header instead of the body field, because some
# browsers add additional markup which is ugly to parse out
self.send_header('echo', data)
self.end_headers()
# This is needed so the WebDriver instance allows setting of cookies
self.wfile.write(six.b('<html></html>'))
# Suppress unwanted logging to stderr
def log_message(self, format, *args):
pass
class SetCookieRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
if 'set-cookie' in (self.headers if six.PY3 else self.headers.dict):
self.send_header('set-cookie', 'some=cookie')
self.end_headers()
# This is needed so the WebDriver instance allows setting of cookies
self.wfile.write(six.b('<html></html>'))
# Suppress unwanted logging to stderr
def log_message(self, format, *args):
pass
def run_http_server(request_handler_class):
while True:
port = get_unused_port()
try:
server = BaseHTTPServer.HTTPServer(('', port), request_handler_class)
break
except socket.error:
pass
def run():
while True:
server.handle_request()
thread = threading.Thread(target=run)
thread.daemon = True
thread.start()
return 'http://127.0.0.1:%d/' % port
dummy_server = run_http_server(DummyRequestHandler)
echo_header_server = run_http_server(EchoHeaderRequestHandler)
set_cookie_server = run_http_server(SetCookieRequestHandler)
def instantiate_webdriver(webdriver_class):
try:
return webdriver_class()
# Selenium raises Exception directly in some WebDriver classes...
except Exception:
pytest.skip('WebDriver not available')
def make_window_handling_test(webdriver_class):
def test_window_handling():
webdriver = instantiate_webdriver(webdriver_class)
webdriver.get(dummy_server)
original_window_handle = webdriver.current_window_handle
webdriver.execute_script("window.open('%s', '_blank');" % dummy_server)
original_window_handles = set(webdriver.window_handles)
# We need a different domain here to test the correct behaviour. Using
# localhost isn't fool-proof because the hosts file is editable, so
# make the most reliable choice we can: Google
webdriver.request('GET', 'https://www.google.com/')
# Make sure that the window handle was switched back to the original
# one after making a request that caused a new window to open
assert webdriver.current_window_handle == original_window_handle
# Make sure that all additional window handles that were opened during
# the request were closed again
assert set(webdriver.window_handles) == original_window_handles
webdriver.quit()
return test_window_handling
def make_headers_test(webdriver_class):
def test_headers():
webdriver = instantiate_webdriver(webdriver_class)
# TODO: Add more cookie examples with additional fields, such as
# expires, path, comment, max-age, secure, version, httponly
domain = get_tld(echo_header_server) if webdriver.name == 'phantomjs' else None
cookies = (
{'domain': domain, 'name': 'hello', 'value': 'world'},
{'domain': domain, 'name': 'another', 'value': 'cookie'}
)
# Open the server URL with the WebDriver instance initially so we can
# set custom cookies
webdriver.get(echo_header_server)
for cookie in cookies:
webdriver.add_cookie(cookie)
response = webdriver.request('GET', echo_header_server, headers={'extra': 'header'},
cookies={'extra': 'cookie'})
sent_headers = requests.structures.CaseInsensitiveDict(json.loads(response.headers['echo']))
# Simply assert that the User-Agent isn't requests' default one, which
# means that it and the rest of the headers must have been overwritten
assert sent_headers['user-agent'] != requests.utils.default_user_agent()
# Check if the additional header was sent as well
assert 'extra' in sent_headers and sent_headers['extra'] == 'header'
cookies = http_cookies.SimpleCookie()
# Python 2's Cookie module expects a string object, not Unicode
cookies.load(sent_headers['cookie'] if six.PY3 else sent_headers['cookie'].encode('ASCII'))
assert 'hello' in cookies and cookies['hello'].value == 'world'
assert 'another' in cookies and cookies['another'].value == 'cookie'
# Check if the additional cookie was sent as well
assert 'extra' in cookies and cookies['extra'].value == 'cookie'
webdriver.quit()
return test_headers
def make_cookie_test(webdriver_class):
def test_cookies():
webdriver = instantiate_webdriver(webdriver_class)
# Make sure that the WebDriver itself doesn't receive the Set-Cookie
# header, instead the requests request should receive it and set it
# manually within the WebDriver instance.
webdriver.request('GET', set_cookie_server, headers={'set-cookie': ''})
# Open the URL so that we can actually get the cookies
webdriver.get(set_cookie_server)
cookie = webdriver.get_cookies()[0]
assert cookie['name'] == 'some' and cookie['value'] == 'cookie'
# TODO: Improve this
# Ensure that the Requests session cookies were cleared and only
# cookies directly taken from the WebDriver instance are used
assert not webdriver.requests_session.cookies
webdriver.quit()
return test_cookies
for webdriver_class in WEBDRIVER_CLASSES:
name = webdriver_class.__name__.lower()
globals()['test_%s_window_handling' % name] = make_window_handling_test(webdriver_class)
globals()['test_%s_headers' % name] = make_headers_test(webdriver_class)
globals()['test_%s_set_cookie' % name] = make_cookie_test(webdriver_class)