Skip to content
This repository was archived by the owner on Jan 3, 2024. It is now read-only.

Commit 85319b5

Browse files
authored
Introduce end2end test framework (#222)
1 parent bccb8e8 commit 85319b5

20 files changed

+1005
-149
lines changed

.flake8

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[flake8]
2-
exclude = docs
2+
exclude = docs, thirdparty
33
max-line-length = 119
44
per-file-ignores =
55
*/__init__.py: F401, F403

.github/workflows/cibuild.yml

+41-16
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,51 @@ on:
44
push:
55
branches:
66
- master
7-
- gh_actions
7+
- end2end_tests
88

99
jobs:
10-
tox:
10+
flake8:
1111
runs-on: ubuntu-latest
12-
strategy:
13-
matrix:
14-
python-version: [3.6, 3.7, 3.8]
1512
steps:
1613
- uses: actions/checkout@v1
14+
- uses: actions/setup-python@v2
15+
- run: python -m pip install --upgrade pip
16+
- run: pip install tox
17+
- run: tox -e flake8
1718

18-
- name: Setup Python ${{ matrix.python-version }}
19-
uses: actions/setup-python@v2
20-
with:
21-
python-version: ${{ matrix.python-version }}
22-
23-
- name: Install dependencies
24-
run: |
25-
python -m pip install --upgrade pip
26-
pip install tox tox-gh-actions
19+
unit_tests:
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
include:
24+
- os: windows-latest
25+
py: 3.9
26+
- os: macos-latest
27+
py: 3.9
28+
- os: ubuntu-latest
29+
py: 3.9
30+
- os: ubuntu-latest
31+
py: 3.8
32+
- os: ubuntu-latest
33+
py: 3.7
34+
- os: ubuntu-latest
35+
py: 3.6
36+
runs-on: ${{ matrix.os }}
37+
steps:
38+
- run: printenv
39+
- uses: actions/checkout@v1
40+
- uses: actions/setup-python@v2
41+
with:
42+
python-version: ${{ matrix.py }}
43+
- run: pip install tox
44+
- run: tox -e py
2745

28-
- name: Run tox
29-
run: tox
46+
end2end_tests:
47+
runs-on: ubuntu-latest
48+
steps:
49+
- uses: actions/checkout@v1
50+
- uses: actions/setup-python@v2
51+
with:
52+
python-version: 3.9
53+
- run: pip install tox
54+
- run: tox -e e2e

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ coverage.xml
4646
*.cover
4747
.hypothesis/
4848
.pytest_cache/
49+
headless-chromium
4950

5051
# Translations
5152
*.mo

README.rst

+8-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Selenium Wire extends Selenium's Python bindings to give you access to the under
99
.. image:: https://codecov.io/gh/wkeeling/selenium-wire/branch/master/graph/badge.svg
1010
:target: https://codecov.io/gh/wkeeling/selenium-wire
1111

12-
.. image:: https://img.shields.io/badge/python-3.6%2C%203.7%2C%203.8-blue.svg
12+
.. image:: https://img.shields.io/badge/python-3.6%2C%203.7%2C%203.8%2C%203.9-blue.svg
1313
:target: https://pypi.python.org/pypi/selenium-wire
1414

1515
.. image:: https://img.shields.io/pypi/v/selenium-wire.svg
@@ -480,7 +480,7 @@ Selenium Wire works by redirecting browser traffic through an internal proxy ser
480480
driver = webdriver.Firefox(seleniumwire_options=options)
481481
482482
``request.abort()``
483-
You can abort a request early by using ``request.abort()`` from within a `request interceptor`_. This will send an immediate response back to the client without the request travelling any further. You can use this mechanism to block certain types of requests (e.g. images) to improve page load performance. Aborted requests are not captured.
483+
You can abort a request early by using ``request.abort()`` from within a `request interceptor`_. This will send an immediate response back to the client without the request travelling any further. You can use this mechanism to block certain types of requests (e.g. images) to improve page load performance.
484484

485485
.. code:: python
486486
@@ -507,7 +507,7 @@ The configuration takes the following format:
507507
options = {
508508
'proxy': {
509509
'http': 'http://192.168.10.100:8888',
510-
'https': 'https://192.168.10.100:8889',
510+
'https': 'https://192.168.10.100:8888',
511511
'no_proxy': 'localhost,127.0.0.1'
512512
}
513513
}
@@ -519,17 +519,17 @@ To use HTTP Basic Auth with your proxy, specify the username and password in the
519519
520520
options = {
521521
'proxy': {
522-
'https': 'https://user:[email protected]:8889',
522+
'https': 'https://user:[email protected]:8888',
523523
}
524524
}
525525
526-
For proxy authentication different to Basic, you can supply the full value for the ``Proxy-Authorization`` header using the ``custom_authorization`` option. For example, if your proxy used the Bearer scheme:
526+
For authentication other than Basic, you can supply the full value for the ``Proxy-Authorization`` header using the ``custom_authorization`` option. For example, if your proxy used the Bearer scheme:
527527

528528
.. code:: python
529529
530530
options = {
531531
'proxy': {
532-
'https': 'https://192.168.10.100:8889', # No username or password used
532+
'https': 'https://192.168.10.100:8888', # No username or password used
533533
'custom_authorization': 'Bearer mytoken123' # Custom Proxy-Authorization header value
534534
}
535535
}
@@ -543,7 +543,7 @@ The proxy configuration can also be loaded through environment variables called
543543
.. code:: bash
544544
545545
$ export HTTP_PROXY="http://192.168.10.100:8888"
546-
$ export HTTPS_PROXY="https://192.168.10.100:8889"
546+
$ export HTTPS_PROXY="https://192.168.10.100:8888"
547547
$ export NO_PROXY="localhost,127.0.0.1"
548548
549549
SOCKS
@@ -556,7 +556,7 @@ Using a SOCKS proxy is the same as using an HTTP based one:
556556
options = {
557557
'proxy': {
558558
'http': 'socks5://user:[email protected]:8888',
559-
'https': 'socks5://user:[email protected]:8889',
559+
'https': 'socks5://user:[email protected]:8888',
560560
'no_proxy': 'localhost,127.0.0.1'
561561
}
562562
}

seleniumwire/handler.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,11 @@ def request(self, flow):
4444
content=request.response.body,
4545
headers=[(k.encode('utf-8'), v.encode('utf-8')) for k, v in request.response.headers.items()]
4646
)
47-
return
48-
49-
flow.request.method = request.method
50-
flow.request.url = request.url
51-
flow.request.headers = self._to_headers_obj(request.headers)
52-
flow.request.raw_content = request.body
47+
else:
48+
flow.request.method = request.method
49+
flow.request.url = request.url
50+
flow.request.headers = self._to_headers_obj(request.headers)
51+
flow.request.raw_content = request.body
5352

5453
log.info('Capturing request: %s', request.url)
5554

@@ -58,6 +57,10 @@ def request(self, flow):
5857
if request.id is not None: # Will not be None when captured
5958
flow.request.id = request.id
6059

60+
if request.response:
61+
# This response will be a mocked response. Capture it for completeness.
62+
self.proxy.storage.save_response(request.id, request.response)
63+
6164
# Could possibly use mitmproxy's 'anticomp' option instead of this
6265
if self.proxy.options.get('disable_encoding') is True:
6366
flow.request.headers['Accept-Encoding'] = 'identity'

seleniumwire/inspect.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import inspect
22
import time
3-
from typing import List, Optional
3+
from typing import List, Optional, Union
44

55
from selenium.common.exceptions import TimeoutException
66

@@ -40,7 +40,7 @@ def last_request(self) -> Optional[Request]:
4040
"""
4141
return self.proxy.storage.load_last_request()
4242

43-
def wait_for_request(self, path: str, timeout: int = 10) -> Request:
43+
def wait_for_request(self, path: str, timeout: Union[int, float] = 10) -> Request:
4444
"""Wait up to the timeout period for a request with the specified
4545
path to be seen.
4646
@@ -68,7 +68,7 @@ def wait_for_request(self, path: str, timeout: int = 10) -> Request:
6868
request = self.proxy.storage.find(path)
6969

7070
if request is None:
71-
time.sleep(0.2)
71+
time.sleep(1 / 5)
7272
else:
7373
return request
7474

seleniumwire/mitmproxy.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -292,4 +292,4 @@ class SendToLogger:
292292

293293
def log(self, entry):
294294
"""Send a mitmproxy log message through our own logger."""
295-
getattr(logger, entry.level, logger.info)(entry.msg)
295+
getattr(logger, entry.level.replace('warn', 'warning'), logger.info)(entry.msg)

setup.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@
5353
'dev': [
5454
'coverage',
5555
'flake8',
56-
'mitmproxy', # This should be removed once the mitmproxy backend goes
56+
'gunicorn',
57+
'httpbin',
58+
'mitmproxy', # Needed by the mitmproxy backend and end2end tests
5759
'pre-commit',
5860
'pytest',
5961
'pytest-cov',

tests/end2end/__init__.py

Whitespace-only changes.

tests/end2end/jsonform.html

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<html>
2+
<head>
3+
<title>Post JSON to End2End Test</title>
4+
</head>
5+
<body>
6+
<button id="submit" onclick="sendJson()">Submit</button>
7+
</body>
8+
<script>
9+
function sendJson() {
10+
let xhr = new XMLHttpRequest();
11+
xhr.open("POST", "https://localhost:8085/post", true);
12+
xhr.setRequestHeader("Content-Type", "application/json");
13+
let data = JSON.stringify(
14+
{ "hello": "world", "spam": "eggs" }
15+
);
16+
xhr.send(data);
17+
}
18+
</script>
19+
</html>

tests/end2end/linux/chromedriver

10.7 MB
Binary file not shown.
54.1 MB
Binary file not shown.

0 commit comments

Comments
 (0)