diff --git a/README.md b/README.md index c1f8a10..88361ee 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # browser-debugger-tools [![Build Status](https://img.shields.io/travis/scivisum/browser-debugger-tools/master.svg?style=flat-square)](https://travis-ci.org/scivisum/browser-debugger-tools) [![PyPI](https://img.shields.io/pypi/v/browserdebuggertools.svg?style=flat-square)](https://pypi.python.org/pypi/browserdebuggertools) +![Python](https://img.shields.io/pypi/pyversions/browserdebuggertools.svg?style=flat-square) ![License](https://img.shields.io/pypi/l/browserdebuggertools.svg?style=flat-square) ## Overview The purpose is to provide a python client to connect to the debugger tools of a web-browser. diff --git a/browserdebuggertools/chrome/interface.py b/browserdebuggertools/chrome/interface.py index ee69b9f..4461bfc 100644 --- a/browserdebuggertools/chrome/interface.py +++ b/browserdebuggertools/chrome/interface.py @@ -4,8 +4,9 @@ from base64 import b64decode from browserdebuggertools.sockethandler import SocketHandler -from browserdebuggertools.exceptions import DevToolsTimeoutException, ResultNotFoundError, \ - DomainNotFoundError +from browserdebuggertools.exceptions import ( + DevToolsTimeoutException, ResultNotFoundError, DomainNotFoundError +) logging.basicConfig(format='%(levelname)s:%(message)s') @@ -160,8 +161,63 @@ def take_screenshot(self, filepath): with open(filepath, "wb") as f: f.write(b64decode(image_data)) + def stop_page_load(self): + return self.execute("Page", "stopLoading") + + def execute_javascript(self, script): + result = self.execute("Runtime", "evaluate", { + "expression": script, + "returnByValue": True + })["result"] + + return result.get("value") + + def get_url(self): + return self.execute_javascript("document.URL") + def get_document_readystate(self): """ Gets the document.readyState of the page. """ - response = self.execute("Runtime", "evaluate", {"expression": "document.readyState"}) - return response["result"]["value"] + return self.execute_javascript("document.readyState") + + def get_page_source(self): + """ Returns a string serialization of the active document's DOM + """ + return self.execute_javascript("document.documentElement.innerHTML") + + def set_user_agent_override(self, user_agent): + """ Overriding user agent with the given string. + :param user_agent: + :return: + """ + return self.execute("Network", "setUserAgentOverride", { + "userAgent": user_agent + }) + + def emulate_network_conditions( + self, offline=False, latency=-1, download_throughput=-1, upload_throughput=-1, + connection_type=None + ): + """ + + :param offline: Whether to emulate network disconnection + :param latency: Minimum latency from request sent to response headers (ms). + :param download_throughput: Maximal aggregated download throughput (bytes/sec). + -1 disables download throttling. + :param upload_throughput: Maximal aggregated upload throughput (bytes/sec). + -1 disables upload throttling. + :param connection_type: The underlying connection technology + that the browser is supposedly using + example values: "cellular2g", "cellular3g", "cellular4g", + "bluetooth", "ethernet", "wifi", "wimax" + """ + network_conditions = { + "offline": offline, + "latency": latency, + "downloadThroughput": download_throughput, + "uploadThroughput": upload_throughput, + } + if connection_type: + network_conditions.update({"connectionType": connection_type}) + + return self.execute("Network", "emulateNetworkConditions", network_conditions) diff --git a/setup.py b/setup.py index 9491e98..aee9f2a 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name="browserdebuggertools", - version="2.0.0", + version="2.1.0", packages=PACKAGES, install_requires=requires, license="GNU General Public License v3", diff --git a/tests/unittests/chrome/test_interface.py b/tests/unittests/chrome/test_interface.py index 0bdf4d2..ad2a7d0 100644 --- a/tests/unittests/chrome/test_interface.py +++ b/tests/unittests/chrome/test_interface.py @@ -57,7 +57,19 @@ def test_timed_out(self, time): class Test_ChromeInterface_enable_domain(ChromeInterfaceTest): def test_invalid_domain(self): - self.interface.execute.return_value = {"id": 1, "error": MagicMock} + self.interface.execute.return_value = {"id": 1, "error": MagicMock()} with self.assertRaises(DomainNotFoundError): self.interface.enable_domain("InvalidDomain") + + +@patch(MODULE_PATH + "ChromeInterface.execute", MagicMock()) +class Test_ChromeInterface_execute_javascript(ChromeInterfaceTest): + + def test(self): + mock_result = MagicMock() + self.interface.execute.return_value = {"id": 1, "result": {"value": mock_result}} + + result = self.interface.execute_javascript("document.readyState") + + self.assertEqual(mock_result, result)