Promium 3.3.30__tar.gz → 3.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {Promium-3.3.30 → Promium-3.4.0}/PKG-INFO +5 -3
- {Promium-3.3.30 → Promium-3.4.0}/Promium.egg-info/PKG-INFO +5 -3
- {Promium-3.3.30 → Promium-3.4.0}/Promium.egg-info/requires.txt +1 -1
- {Promium-3.3.30 → Promium-3.4.0}/README.rst +3 -1
- {Promium-3.3.30 → Promium-3.4.0}/promium/assertions.py +15 -6
- {Promium-3.3.30 → Promium-3.4.0}/promium/base.py +26 -9
- {Promium-3.3.30 → Promium-3.4.0}/promium/common.py +31 -21
- {Promium-3.3.30 → Promium-3.4.0}/promium/elements/link.py +22 -8
- {Promium-3.3.30 → Promium-3.4.0}/promium/logger.py +10 -14
- {Promium-3.3.30 → Promium-3.4.0}/promium/plugin.py +12 -6
- {Promium-3.3.30 → Promium-3.4.0}/promium/test_case.py +43 -12
- {Promium-3.3.30 → Promium-3.4.0}/promium/waits.py +17 -4
- {Promium-3.3.30 → Promium-3.4.0}/setup.py +2 -2
- {Promium-3.3.30 → Promium-3.4.0}/tests/test_requests.py +1 -1
- {Promium-3.3.30 → Promium-3.4.0}/LICENSE +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/Promium.egg-info/SOURCES.txt +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/Promium.egg-info/dependency_links.txt +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/Promium.egg-info/entry_points.txt +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/Promium.egg-info/top_level.txt +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/doc/__init__.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/doc/conf.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/__init__.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/browsers.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/device_config.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/elements/__init__.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/elements/checkbox.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/elements/drop_downs.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/elements/frame.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/elements/input_field.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/elements/multiselect_listbox.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/elements/radio_button.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/elements/textarea_field.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/elements/upload_button.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/exceptions.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/expected_conditions.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/helpers.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/support/__init__.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/promium/support/settings.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/setup.cfg +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/__init__.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/config.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/conftest.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/pages/__init__.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/pages/catalog_404_page.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/pages/catalog_gallery_page.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/settings/__init__.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/settings/test_base.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/settings/test_chrome.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/settings/test_edge.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/settings/test_firefox.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/settings/test_ie.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/settings/test_opera.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/test_catalog_404.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/test_catalog_gallery.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/test_enviroment.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/test_soft_asserts.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/test_waits.py +0 -0
- {Promium-3.3.30 → Promium-3.4.0}/tests/urls.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: Promium
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.0
|
|
4
4
|
Summary: Selenium wrapper for testing Web UI
|
|
5
5
|
Author: Denis Korytkin, Nataliia Guieva, Roman Zaporozhets, Vladimir Kritov, Oleh Dykusha
|
|
6
6
|
Project-URL: Home page, https://none
|
|
@@ -17,7 +17,7 @@ Requires-Python: >=3.10, <4
|
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: six>=1.10.0
|
|
19
19
|
Requires-Dist: json_checker>=1.2.1
|
|
20
|
-
Requires-Dist:
|
|
20
|
+
Requires-Dist: urllib3>=2.0.2
|
|
21
21
|
Requires-Dist: py>=1.5.2
|
|
22
22
|
Requires-Dist: pytest>=5.0.0
|
|
23
23
|
Requires-Dist: pytest_rerunfailures>=4.1.0
|
|
@@ -30,7 +30,7 @@ Requires-Dist: selenium>=4.10.0
|
|
|
30
30
|
Promium
|
|
31
31
|
========================
|
|
32
32
|
|
|
33
|
-
.. image:: https://img.shields.io/badge/python-2.7%
|
|
33
|
+
.. image:: https://img.shields.io/badge/python-2.7%20...%203.12-blue.svg
|
|
34
34
|
:target: https://pypi.org/project/Promium/
|
|
35
35
|
|
|
36
36
|
.. image:: https://badge.fury.io/py/Promium.svg
|
|
@@ -41,6 +41,8 @@ Simple selenium wrapper from implemented UI tests
|
|
|
41
41
|
|
|
42
42
|
Watch `documentation <https://qa-automation.git-doc.evo.dev/promium>`_
|
|
43
43
|
|
|
44
|
+
Coverage `link <https://qa-automation.git-doc.evo.dev/promium/htmlcov/>`_
|
|
45
|
+
|
|
44
46
|
Quick Start
|
|
45
47
|
========================
|
|
46
48
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: Promium
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.0
|
|
4
4
|
Summary: Selenium wrapper for testing Web UI
|
|
5
5
|
Author: Denis Korytkin, Nataliia Guieva, Roman Zaporozhets, Vladimir Kritov, Oleh Dykusha
|
|
6
6
|
Project-URL: Home page, https://none
|
|
@@ -17,7 +17,7 @@ Requires-Python: >=3.10, <4
|
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: six>=1.10.0
|
|
19
19
|
Requires-Dist: json_checker>=1.2.1
|
|
20
|
-
Requires-Dist:
|
|
20
|
+
Requires-Dist: urllib3>=2.0.2
|
|
21
21
|
Requires-Dist: py>=1.5.2
|
|
22
22
|
Requires-Dist: pytest>=5.0.0
|
|
23
23
|
Requires-Dist: pytest_rerunfailures>=4.1.0
|
|
@@ -30,7 +30,7 @@ Requires-Dist: selenium>=4.10.0
|
|
|
30
30
|
Promium
|
|
31
31
|
========================
|
|
32
32
|
|
|
33
|
-
.. image:: https://img.shields.io/badge/python-2.7%
|
|
33
|
+
.. image:: https://img.shields.io/badge/python-2.7%20...%203.12-blue.svg
|
|
34
34
|
:target: https://pypi.org/project/Promium/
|
|
35
35
|
|
|
36
36
|
.. image:: https://badge.fury.io/py/Promium.svg
|
|
@@ -41,6 +41,8 @@ Simple selenium wrapper from implemented UI tests
|
|
|
41
41
|
|
|
42
42
|
Watch `documentation <https://qa-automation.git-doc.evo.dev/promium>`_
|
|
43
43
|
|
|
44
|
+
Coverage `link <https://qa-automation.git-doc.evo.dev/promium/htmlcov/>`_
|
|
45
|
+
|
|
44
46
|
Quick Start
|
|
45
47
|
========================
|
|
46
48
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Promium
|
|
3
3
|
========================
|
|
4
4
|
|
|
5
|
-
.. image:: https://img.shields.io/badge/python-2.7%
|
|
5
|
+
.. image:: https://img.shields.io/badge/python-2.7%20...%203.12-blue.svg
|
|
6
6
|
:target: https://pypi.org/project/Promium/
|
|
7
7
|
|
|
8
8
|
.. image:: https://badge.fury.io/py/Promium.svg
|
|
@@ -13,6 +13,8 @@ Simple selenium wrapper from implemented UI tests
|
|
|
13
13
|
|
|
14
14
|
Watch `documentation <https://qa-automation.git-doc.evo.dev/promium>`_
|
|
15
15
|
|
|
16
|
+
Coverage `link <https://qa-automation.git-doc.evo.dev/promium/htmlcov/>`_
|
|
17
|
+
|
|
16
18
|
Quick Start
|
|
17
19
|
========================
|
|
18
20
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import re
|
|
3
3
|
import json
|
|
4
|
-
import
|
|
4
|
+
import urllib3
|
|
5
5
|
import allure
|
|
6
6
|
import logging
|
|
7
7
|
|
|
@@ -19,6 +19,17 @@ CoerceDict = Optional[Dict[str, type]]
|
|
|
19
19
|
log = logging.getLogger(__name__)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
http = urllib3.PoolManager(
|
|
23
|
+
cert_reqs=False,
|
|
24
|
+
timeout=5,
|
|
25
|
+
headers={
|
|
26
|
+
"Accept-Encoding": 'gzip, deflate',
|
|
27
|
+
"Accept": "*/*",
|
|
28
|
+
"Connection": "keep-alive",
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
22
33
|
def base_msg(msg):
|
|
23
34
|
return f"{msg}\n" if msg else ""
|
|
24
35
|
|
|
@@ -482,19 +493,17 @@ class WebDriverSoftAssertion(BaseSoftAssertion):
|
|
|
482
493
|
error = f"{self.base_msg(default_msg=default_msg, extend_msg=msg)}"
|
|
483
494
|
self.assertion_errors.append(error)
|
|
484
495
|
|
|
485
|
-
def soft_assert_image_status_code(
|
|
486
|
-
self, image, timeout=2, status_code=200, msg=None
|
|
487
|
-
):
|
|
496
|
+
def soft_assert_image_status_code(self, image, status_code=200, msg=None):
|
|
488
497
|
if not image.get_attribute('src'):
|
|
489
498
|
return self.assertion_errors.append(
|
|
490
499
|
'Image does not have attribute "src"'
|
|
491
500
|
)
|
|
492
501
|
|
|
493
502
|
img_url = image.get_attribute('src')
|
|
494
|
-
response =
|
|
503
|
+
response = http.request(url=img_url, method='GET')
|
|
495
504
|
|
|
496
505
|
self.soft_assert_equals(
|
|
497
|
-
response.
|
|
506
|
+
response.status,
|
|
498
507
|
status_code,
|
|
499
508
|
msg=msg if msg else 'img status code != 200'
|
|
500
509
|
)
|
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
import os
|
|
4
4
|
import random
|
|
5
5
|
import time
|
|
6
|
-
import
|
|
6
|
+
import urllib3
|
|
7
7
|
from collections.abc import Sequence
|
|
8
8
|
|
|
9
9
|
from functools import wraps
|
|
@@ -156,15 +156,30 @@ class Page(object):
|
|
|
156
156
|
|
|
157
157
|
def get_status_code(self):
|
|
158
158
|
""" get status_code from current page """
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
159
|
+
http = urllib3.PoolManager(
|
|
160
|
+
cert_reqs=False,
|
|
161
|
+
timeout=5,
|
|
162
|
+
)
|
|
163
|
+
cookies_str = '; '.join([
|
|
164
|
+
f'{cookie["name"]}={cookie["value"]}'
|
|
165
|
+
for cookie in self.driver.get_cookies()
|
|
166
|
+
])
|
|
167
|
+
r = http.request(
|
|
163
168
|
url=self.driver.current_url,
|
|
164
|
-
|
|
169
|
+
method='GET',
|
|
170
|
+
headers={
|
|
171
|
+
"Accept-Encoding": 'gzip, deflate',
|
|
172
|
+
"Accept": "*/*",
|
|
173
|
+
"Connection": "keep-alive",
|
|
174
|
+
'Cookie': cookies_str,
|
|
175
|
+
},
|
|
176
|
+
redirect=False,
|
|
177
|
+
retries=urllib3.Retry(
|
|
178
|
+
redirect=0,
|
|
179
|
+
raise_on_redirect=False,
|
|
180
|
+
),
|
|
165
181
|
)
|
|
166
|
-
|
|
167
|
-
return r.status_code
|
|
182
|
+
return r.status
|
|
168
183
|
|
|
169
184
|
def wait_for_animation(self):
|
|
170
185
|
wait_for_animation(self.driver)
|
|
@@ -375,7 +390,9 @@ class Collection(Base, Sequence):
|
|
|
375
390
|
"""
|
|
376
391
|
return self.find_all(by, locator).get_item(0)
|
|
377
392
|
|
|
378
|
-
def find_by_text(
|
|
393
|
+
def find_by_text(
|
|
394
|
+
self, text, check_negative=False, partial_text=True
|
|
395
|
+
) -> 'Element':
|
|
379
396
|
found_elements_by_test = []
|
|
380
397
|
if partial_text:
|
|
381
398
|
script = """
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import base64
|
|
2
2
|
import os
|
|
3
3
|
import datetime
|
|
4
|
-
import
|
|
5
|
-
import requests
|
|
4
|
+
import urllib3
|
|
6
5
|
import json
|
|
7
6
|
import time
|
|
8
7
|
import logging
|
|
@@ -17,6 +16,13 @@ from promium.waits import (
|
|
|
17
16
|
|
|
18
17
|
log = logging.getLogger(__name__)
|
|
19
18
|
|
|
19
|
+
|
|
20
|
+
http = urllib3.PoolManager(
|
|
21
|
+
cert_reqs=False,
|
|
22
|
+
timeout=5,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
20
26
|
SCREENSHOT_SERVER_HOST = os.environ.get("SCREENSHOT_SERVER_HOST")
|
|
21
27
|
SCREENSHOT_SERVER_LOGIN = os.environ.get("SCREENSHOT_SERVER_LOGIN")
|
|
22
28
|
SCREENSHOT_SERVER_PASSWORD = os.environ.get("SCREENSHOT_SERVER_PASSWORD")
|
|
@@ -136,12 +142,16 @@ def get_screenshot_path(name, with_date=True):
|
|
|
136
142
|
|
|
137
143
|
def if_server_have_problem():
|
|
138
144
|
try:
|
|
139
|
-
r =
|
|
145
|
+
r = http.request(
|
|
140
146
|
url=f"https://{SCREENSHOT_SERVER_HOST}",
|
|
141
|
-
|
|
142
|
-
|
|
147
|
+
method='GET',
|
|
148
|
+
headers={
|
|
149
|
+
'Accept-Encoding': 'gzip, deflate',
|
|
150
|
+
'Accept': '*/*',
|
|
151
|
+
'Connection': 'keep-alive',
|
|
152
|
+
},
|
|
143
153
|
)
|
|
144
|
-
r.
|
|
154
|
+
assert r.status <= 400, f'Have problem {r.status}: {r.reason}'
|
|
145
155
|
return False
|
|
146
156
|
except Exception as e:
|
|
147
157
|
return str(e)
|
|
@@ -166,14 +176,23 @@ def _upload_to_server(screenshot_path, screenshot_name):
|
|
|
166
176
|
chunks -= 1
|
|
167
177
|
|
|
168
178
|
screenshot_url = f"https://{SCREENSHOT_SERVER_HOST}/{screenshot_name}"
|
|
169
|
-
r =
|
|
179
|
+
r = http.request(
|
|
170
180
|
url=screenshot_url,
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
181
|
+
method='PUT',
|
|
182
|
+
headers={
|
|
183
|
+
'Accept-Encoding': 'gzip, deflate',
|
|
184
|
+
'Accept': '*/*',
|
|
185
|
+
'Connection': 'keep-alive',
|
|
186
|
+
'Content-Type': 'application/json',
|
|
187
|
+
'Authorization': 'Basic ' + base64.b64encode(
|
|
188
|
+
f'{SCREENSHOT_SERVER_LOGIN}:{SCREENSHOT_SERVER_PASSWORD}'
|
|
189
|
+
''.encode()
|
|
190
|
+
).decode()
|
|
191
|
+
},
|
|
192
|
+
body=read_in_chunks(open(screenshot_path, 'rb')),
|
|
174
193
|
)
|
|
175
194
|
os.remove(screenshot_path)
|
|
176
|
-
if
|
|
195
|
+
if r.status != 201:
|
|
177
196
|
return (
|
|
178
197
|
f"Screenshot not uploaded to server. "
|
|
179
198
|
f"Status code: {r.status_code}, reason: {r.reason}"
|
|
@@ -197,15 +216,6 @@ def upload_screenshot(driver, path_name="screenshot", path_with_date=True):
|
|
|
197
216
|
return f'No screenshot was captured due to exception {repr(e)}'
|
|
198
217
|
|
|
199
218
|
|
|
200
|
-
def download_and_check_file(download_url, file_path):
|
|
201
|
-
try:
|
|
202
|
-
urllib.urlretrieve(download_url, file_path)
|
|
203
|
-
return bool(os.path.isfile(file_path) and os.path.exists(file_path))
|
|
204
|
-
finally:
|
|
205
|
-
if os.path.exists(file_path):
|
|
206
|
-
os.remove(file_path)
|
|
207
|
-
|
|
208
|
-
|
|
209
219
|
def control_plus_key(driver, key):
|
|
210
220
|
"""Imitations press CONTROL key + any key"""
|
|
211
221
|
(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import
|
|
2
|
+
import urllib3
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
5
|
from promium.base import Element
|
|
@@ -33,12 +33,26 @@ class Link(Element):
|
|
|
33
33
|
|
|
34
34
|
@property
|
|
35
35
|
def response(self):
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
http = urllib3.PoolManager(
|
|
37
|
+
cert_reqs=False,
|
|
38
|
+
timeout=5,
|
|
39
|
+
)
|
|
40
|
+
cookies_str = '; '.join([
|
|
41
|
+
f'{cookie["name"]}={cookie["value"]}'
|
|
42
|
+
for cookie in self.driver.get_cookies()
|
|
43
|
+
])
|
|
39
44
|
for i in range(1, 3):
|
|
40
|
-
r =
|
|
41
|
-
|
|
45
|
+
r = http.request(
|
|
46
|
+
url=self.href,
|
|
47
|
+
method='GET',
|
|
48
|
+
headers={
|
|
49
|
+
"Accept-Encoding": 'gzip, deflate',
|
|
50
|
+
"Accept": "*/*",
|
|
51
|
+
"Connection": "keep-alive",
|
|
52
|
+
"Cookie": cookies_str,
|
|
53
|
+
},
|
|
54
|
+
)
|
|
55
|
+
if r.status in [502, 503, 504]:
|
|
42
56
|
log.warning(f'[Request Retry]: attempt:{i}, status: {r.status}')
|
|
43
57
|
else:
|
|
44
58
|
break
|
|
@@ -47,5 +61,5 @@ class Link(Element):
|
|
|
47
61
|
|
|
48
62
|
@property
|
|
49
63
|
def get_status_code(self):
|
|
50
|
-
"""Gets status
|
|
51
|
-
return self.response.
|
|
64
|
+
"""Gets status response code from link"""
|
|
65
|
+
return self.response.status
|
|
@@ -223,31 +223,27 @@ class LoggerHandler(logging.StreamHandler):
|
|
|
223
223
|
self.stream.close()
|
|
224
224
|
|
|
225
225
|
|
|
226
|
-
def request_logging(request,
|
|
227
|
-
content = str(request.
|
|
226
|
+
def request_logging(request, url, method, **kwargs):
|
|
227
|
+
content = str(request.data)
|
|
228
228
|
warning_message = (
|
|
229
229
|
"[Python request] STATUS CODE: {status_code}, LINK: {link}\n"
|
|
230
230
|
"{tabs}METHOD: {method}\n"
|
|
231
231
|
"{tabs}BODY: {body}\n"
|
|
232
232
|
"{tabs}RESPONSE CONTENT: "
|
|
233
233
|
"{content}{ellipsis} ({length} symbols)\n".format(
|
|
234
|
-
status_code=request.
|
|
235
|
-
method=
|
|
236
|
-
link=
|
|
237
|
-
body=
|
|
234
|
+
status_code=request.status,
|
|
235
|
+
method=method,
|
|
236
|
+
link=url,
|
|
237
|
+
body=kwargs.get('body'),
|
|
238
238
|
content=re.sub(r'\s+', ' ', content)[:MAX_SYMBOLS],
|
|
239
239
|
ellipsis=" ..." if len(content) > MAX_SYMBOLS else "",
|
|
240
|
-
length=len(request.
|
|
240
|
+
length=len(request.data),
|
|
241
241
|
tabs=" " * 12,
|
|
242
242
|
)
|
|
243
243
|
)
|
|
244
|
-
if 400 <= request.
|
|
244
|
+
if 400 <= request.status < 500:
|
|
245
245
|
log.warning(warning_message)
|
|
246
|
-
elif request.
|
|
246
|
+
elif request.status >= 500:
|
|
247
247
|
log.error(warning_message)
|
|
248
248
|
else:
|
|
249
|
-
log.info(
|
|
250
|
-
"[Python request] STATUS CODE: {status_code}, LINK: {link}".format(
|
|
251
|
-
status_code=request.status_code, link=request.url
|
|
252
|
-
)
|
|
253
|
-
)
|
|
249
|
+
log.info(f"[Python request] STATUS CODE: {request.status}, LINK: {url}")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import datetime
|
|
3
3
|
import logging
|
|
4
|
-
import
|
|
4
|
+
import urllib3
|
|
5
5
|
from collections import namedtuple
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
@@ -24,6 +24,12 @@ FailInfoRequest = namedtuple('FailInfoRequest', [
|
|
|
24
24
|
'test_type', 'url', 'test_case', 'status_code', 'run_command', 'txid'
|
|
25
25
|
])
|
|
26
26
|
|
|
27
|
+
DEFAULT_HEADERS = {
|
|
28
|
+
"Accept-Encoding": 'gzip, deflate',
|
|
29
|
+
"Accept": "*/*",
|
|
30
|
+
"Connection": "keep-alive",
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
|
|
28
34
|
def pytest_sessionstart(session):
|
|
29
35
|
if hasattr(session.config, 'cache'):
|
|
@@ -143,19 +149,19 @@ def request_init(request):
|
|
|
143
149
|
txid=(request.cls.xrequestid, [None])[0],
|
|
144
150
|
)
|
|
145
151
|
|
|
146
|
-
session =
|
|
152
|
+
session = urllib3.PoolManager(
|
|
153
|
+
cert_reqs=False,
|
|
154
|
+
timeout=15,
|
|
155
|
+
headers=DEFAULT_HEADERS,
|
|
156
|
+
)
|
|
147
157
|
session.url = (
|
|
148
158
|
'Use self.get_response(url) for request tests or '
|
|
149
159
|
'util methods for api tests!'
|
|
150
160
|
)
|
|
151
|
-
if request.cls.proxies:
|
|
152
|
-
session.proxies.update(request.cls.proxies)
|
|
153
161
|
request.cls.session = session
|
|
154
162
|
request.config.get_fail_debug = _get_fail_debug
|
|
155
163
|
request.config.assertion_errors = request.cls.assertion_errors = []
|
|
156
164
|
yield session
|
|
157
|
-
if session:
|
|
158
|
-
session.close()
|
|
159
165
|
request.cls.xrequestid = None
|
|
160
166
|
|
|
161
167
|
|
|
@@ -3,7 +3,7 @@ import errno
|
|
|
3
3
|
import os
|
|
4
4
|
import signal
|
|
5
5
|
import threading
|
|
6
|
-
|
|
6
|
+
import urllib3
|
|
7
7
|
import pytest
|
|
8
8
|
import logging
|
|
9
9
|
import traceback
|
|
@@ -42,6 +42,13 @@ DRIVERS = {
|
|
|
42
42
|
MAX_LOAD_TIME = 10
|
|
43
43
|
|
|
44
44
|
|
|
45
|
+
DEFAULT_HEADERS = {
|
|
46
|
+
"Accept-Encoding": 'gzip, deflate',
|
|
47
|
+
"Accept": "*/*",
|
|
48
|
+
"Connection": "keep-alive",
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
45
52
|
def timeout(seconds=5, error_message=os.strerror(errno.ETIME)):
|
|
46
53
|
def decorator(func):
|
|
47
54
|
def _handle_timeout(signum, frame):
|
|
@@ -200,37 +207,61 @@ class WebDriverTestCase(TestCase, WebDriverSoftAssertion):
|
|
|
200
207
|
@pytest.mark.usefixtures("request_init")
|
|
201
208
|
class RequestTestCase(TestCase, RequestSoftAssertion):
|
|
202
209
|
session = None
|
|
203
|
-
proxies = {}
|
|
204
210
|
|
|
205
211
|
def get_response(
|
|
206
212
|
self, url, method="GET", timeout=10, cookies=None, **kwargs,
|
|
207
213
|
):
|
|
208
214
|
self.session.url = url
|
|
209
215
|
self.session.status_code = None
|
|
216
|
+
session = self.session
|
|
210
217
|
request_cookies = {'xrequestid': self.xrequestid}
|
|
211
218
|
if cookies:
|
|
212
219
|
request_cookies.update(cookies)
|
|
220
|
+
cookies_str = '; '.join(
|
|
221
|
+
[f'{k}={v}' for k, v in request_cookies.items()]
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
if hasattr(self.session, 'session_cookie'):
|
|
225
|
+
cookies_str += f'; {self.session.session_cookie}'
|
|
226
|
+
|
|
227
|
+
if self.proxy_server and not hasattr(session, 'proxy_override_session'):
|
|
228
|
+
session = urllib3.ProxyManager(
|
|
229
|
+
proxy_url=f"http://{self.proxy_server}",
|
|
230
|
+
cert_reqs=False,
|
|
231
|
+
timeout=15,
|
|
232
|
+
)
|
|
233
|
+
session.proxy_override_session = True
|
|
234
|
+
|
|
235
|
+
headers = DEFAULT_HEADERS
|
|
236
|
+
headers['Cookie'] = cookies_str
|
|
237
|
+
if new_headers := kwargs.pop('headers', None):
|
|
238
|
+
headers.update(new_headers)
|
|
213
239
|
|
|
214
240
|
for i in range(1, 3):
|
|
215
|
-
response =
|
|
216
|
-
method=method,
|
|
241
|
+
response = session.request(
|
|
217
242
|
url=url,
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
243
|
+
method=method,
|
|
244
|
+
headers=headers,
|
|
245
|
+
timeout=urllib3.Timeout(
|
|
246
|
+
connect=5.0,
|
|
247
|
+
read=float(timeout),
|
|
248
|
+
total=float(timeout),
|
|
249
|
+
),
|
|
222
250
|
**kwargs,
|
|
223
251
|
)
|
|
224
|
-
|
|
252
|
+
request_logging(response, url, method, **kwargs)
|
|
253
|
+
self.session.status_code = response.status
|
|
254
|
+
response.status_code = response.status
|
|
225
255
|
if (
|
|
226
|
-
response.
|
|
227
|
-
|
|
256
|
+
response.status in [502, 503, 504] and
|
|
257
|
+
method in ["POST", "GET"]
|
|
228
258
|
):
|
|
229
259
|
log.warning(
|
|
230
260
|
f'[Request Retry]: attempt:{i}, '
|
|
231
|
-
f'status: {response.
|
|
261
|
+
f'status: {response.status}'
|
|
232
262
|
)
|
|
233
263
|
else:
|
|
264
|
+
self.session.session_cookie = response.headers.get('set-cookie')
|
|
234
265
|
break
|
|
235
266
|
|
|
236
267
|
return response
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
import
|
|
2
|
+
import urllib3
|
|
3
3
|
import time
|
|
4
4
|
|
|
5
5
|
from selenium.webdriver.support.ui import WebDriverWait
|
|
@@ -18,6 +18,17 @@ log = logging.getLogger(__name__)
|
|
|
18
18
|
NORMAL_LOAD_TIME = 10
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
http = urllib3.PoolManager(
|
|
22
|
+
cert_reqs=False,
|
|
23
|
+
timeout=10,
|
|
24
|
+
headers={
|
|
25
|
+
"Accept-Encoding": 'gzip, deflate',
|
|
26
|
+
"Accept": "*/*",
|
|
27
|
+
"Connection": "keep-alive",
|
|
28
|
+
},
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
21
32
|
def enable_jquery(driver):
|
|
22
33
|
"""Enables jquery"""
|
|
23
34
|
driver.execute_script(
|
|
@@ -220,10 +231,12 @@ def wait_for_status_code(url, status_code=200, tries=10, allow_redirects=True):
|
|
|
220
231
|
"""Waits for status code"""
|
|
221
232
|
current_status = None
|
|
222
233
|
for _ in range(tries):
|
|
223
|
-
response =
|
|
224
|
-
url
|
|
234
|
+
response = http.request(
|
|
235
|
+
url=url,
|
|
236
|
+
method='GET',
|
|
237
|
+
redirect=allow_redirects,
|
|
225
238
|
)
|
|
226
|
-
current_status = response.
|
|
239
|
+
current_status = response.status
|
|
227
240
|
if current_status == status_code:
|
|
228
241
|
return response
|
|
229
242
|
time.sleep(1)
|
|
@@ -6,7 +6,7 @@ from setuptools import setup, find_packages
|
|
|
6
6
|
REQUIREMENTS = [
|
|
7
7
|
'six>=1.10.0',
|
|
8
8
|
'json_checker>=1.2.1',
|
|
9
|
-
'
|
|
9
|
+
'urllib3>=2.0.2',
|
|
10
10
|
'py>=1.5.2',
|
|
11
11
|
'pytest>=5.0.0',
|
|
12
12
|
'pytest_rerunfailures>=4.1.0',
|
|
@@ -19,7 +19,7 @@ REQUIREMENTS = [
|
|
|
19
19
|
|
|
20
20
|
setup(
|
|
21
21
|
name='Promium',
|
|
22
|
-
version='3.
|
|
22
|
+
version='3.4.0',
|
|
23
23
|
install_requires=REQUIREMENTS,
|
|
24
24
|
author='Denis Korytkin, Nataliia Guieva, '
|
|
25
25
|
'Roman Zaporozhets, Vladimir Kritov, '
|
|
@@ -9,7 +9,7 @@ class TestMainPage(RequestTestCase):
|
|
|
9
9
|
test_case_url = 'some url with test case'
|
|
10
10
|
|
|
11
11
|
def test_google_search_block(self):
|
|
12
|
-
page_text = self.get_response('https://google.com.ua').
|
|
12
|
+
page_text = self.get_response('https://google.com.ua').data
|
|
13
13
|
soup = BeautifulSoup(page_text, "html.parser")
|
|
14
14
|
|
|
15
15
|
search_input = soup.find(attrs={'name': 'q'})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|