diff --git a/bin/splash b/bin/splash old mode 100755 new mode 100644 diff --git a/debian/rules b/debian/rules old mode 100755 new mode 100644 diff --git a/dockerfiles/splash/provision.sh b/dockerfiles/splash/provision.sh old mode 100755 new mode 100644 diff --git a/scripts/rst2inspections.py b/scripts/rst2inspections.py old mode 100755 new mode 100644 diff --git a/setup.cfg b/setup.cfg old mode 100755 new mode 100644 diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 diff --git a/splash/browser_tab.py b/splash/browser_tab.py index 713b63798..5f760fb9c 100644 --- a/splash/browser_tab.py +++ b/splash/browser_tab.py @@ -6,7 +6,9 @@ import weakref import uuid -from PyQt5.QtCore import QObject, QSize, Qt, QTimer, pyqtSlot +from PyQt5.QtCore import QObject, QSize, QPoint, Qt, QTimer, QEvent, pyqtSlot +from PyQt5.QtGui import QMouseEvent +from PyQt5.QtWidgets import QApplication from PyQt5.QtNetwork import QNetworkRequest from PyQt5.QtWebKitWidgets import QWebPage from PyQt5.QtWebKit import QWebSettings @@ -729,6 +731,15 @@ def html(self): self.store_har_timing("_onHtmlRendered") return result + def mouse_click(self, x, y): + """ mouse click on given point(x, y) of web_page""" + self.logger.log("mouse clicking on point(%d, %d)" % (x,y), min_level=2) + evt = QMouseEvent(QEvent.MouseButtonPress, QPoint(x,y), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier) + QApplication.sendEvent(self.web_page, evt) + evt = QMouseEvent(QEvent.MouseButtonRelease, QPoint(x,y), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier) + QApplication.sendEvent(self.web_page, evt) + self.store_har_timing("_onMouseClicked") + def _get_image(self, image_format, width, height, render_all, scale_method, region): old_size = self.web_page.viewportSize() @@ -912,7 +923,7 @@ def _send_request(self, url, callback, method='GET', body=None, ua_from_headers = _get_header_value(headers, b'user-agent') web_page_ua = self.web_page.userAgentForUrl(to_qurl(url)) user_agent = ua_from_headers or web_page_ua - request.setRawHeader(b"user-agent", to_bytes(user_agent)) + request.setRawHeader(b"User-Agent", to_bytes(user_agent)) if method.upper() == "POST": reply = self.network_manager.post(request, body) diff --git a/splash/kernel/inspections/splash-auto.json b/splash/kernel/inspections/splash-auto.json index 87942a604..874256778 100644 --- a/splash/kernel/inspections/splash-auto.json +++ b/splash/kernel/inspections/splash-auto.json @@ -197,6 +197,17 @@ "details": "Example:\n\n.. code-block:: lua\n\n -- A simplistic implementation of render.html endpoint\n function main(splash)\n splash:set_result_content_type(\"text/html; charset=utf-8\")\n assert(splash:go(splash.args.url))\n return splash:html()\n end\n\nNothing prevents us from taking multiple HTML snapshots. For example, let's\nvisit first 3 pages on a website, and for each page store\ninitial HTML snapshot and an HTML snapshot after waiting 0.5s:\n\ntreat = require(\"treat\")\n\n-- Given an url, this function returns a table\n-- with the page screenshoot, it's HTML contents\n-- and it's title.\nfunction page_info(splash, url)\n local ok, msg = splash:go(url)\n if not ok then\n return {ok=false, reason=msg}\n end\n local res = {\n html=splash:html(),\n title=splash:evaljs('document.title'),\n image=splash:png(),\n ok=true,\n }\n return res\nend\n\n-- visit first 3 pages of hacker news\nlocal base = \"https://news.ycombinator.com/news?p=\"\nfunction main(splash)\n local result = treat.as_array({})\n for i=1,3 do\n local url = base .. i\n result[i] = page_info(splash, url)\n end\n return result\nend", "params": null }, + "splash:mouse_click": { + "name": "mouse_click", + "header": "splash:mouse_click", + "content": "Click a given point(x, y) of web_page, usually (x, y) relate to an element of html", + "short": "Click a given point(x, y) of web_page", + "signature": "splash:mouse_click(x, y)", + "returns": "nil", + "async": "no.", + "details": "", + "params": "* x - integer, position of the mouse cursor relative to web_page.\n* y - integer, position of the mouse cursor relative to web_page." + }, "splash:png": { "name": "png", "header": "splash:png", @@ -516,4 +527,4 @@ "details": "As of now, this table contains:\n\n* ``splash`` - (string) Splash version\n* ``major`` - (int) Splash major version\n* ``minor`` - (int) Splash minor version\n* ``python`` - (string) Python version\n* ``qt`` - (string) Qt version\n* ``pyqt`` - (string) PyQt version\n* ``webkit`` - (string) WebKit version\n* ``sip`` - (string) SIP version\n* ``twisted`` - (string) Twisted version\n\nExample:\n\n.. code-block:: lua\n\n function main(splash)\n local version = splash:get_version()\n if version.major < 2 and version.minor < 8 then\n error(\"Splash 1.8 or newer required\")\n end\n end", "params": null } -} \ No newline at end of file +} diff --git a/splash/qtrender_lua.py b/splash/qtrender_lua.py index 0909f49e7..46ff020a8 100644 --- a/splash/qtrender_lua.py +++ b/splash/qtrender_lua.py @@ -567,6 +567,10 @@ def error(error_info): def html(self): return self.tab.html() + @command() + def mouse_click(self, x, y): + return self.tab.mouse_click(x, y) + @command() def png(self, width=None, height=None, render_all=False, scale_method=None, region=None): diff --git a/splash/tests/mockserver.py b/splash/tests/mockserver.py old mode 100755 new mode 100644 diff --git a/splash/tests/test_execute.py b/splash/tests/test_execute.py index 789341f43..66c5c3a84 100644 --- a/splash/tests/test_execute.py +++ b/splash/tests/test_execute.py @@ -1395,11 +1395,11 @@ class JsonPostArgsTest(ArgsTest): request_handler = JsonPostRequestHandler def test_headers(self): - headers = {"user-agent": "Firefox", "content-type": "text/plain"} + headers = {"User-Agent": "Firefox", "content-type": "text/plain"} self.assertArgsPassed({"headers": headers}) def test_headers_items(self): - headers = [["user-agent", "Firefox"], ["content-type", "text/plain"]] + headers = [["User-Agent", "Firefox"], ["content-type", "text/plain"]] self.assertArgsPassed({"headers": headers}) def test_access_headers(self): @@ -1407,12 +1407,12 @@ def test_access_headers(self): function main(splash) local ua = "Unknown" if splash.args.headers then - ua = splash.args.headers['user-agent'] + ua = splash.args.headers['User-Agent'] end return {ua=ua, firefox=(ua=="Firefox")} end """ - resp = self.request_lua(func, {'headers': {"user-agent": "Firefox"}}) + resp = self.request_lua(func, {'headers': {"User-Agent": "Firefox"}}) self.assertStatusCode(resp, 200) self.assertEqual(resp.json(), {"ua": "Firefox", "firefox": True}) @@ -1876,13 +1876,13 @@ def test_set_user_agent(self): self.assertNotIn("Mozilla", data["res3"]) if six.PY3: - self.assertNotIn("b'user-agent': b'Foozilla'", data["res1"]) - self.assertIn("b'user-agent': b'Foozilla'", data["res2"]) - self.assertIn("b'user-agent': b'Foozilla'", data["res3"]) + self.assertNotIn("b'User-Agent': b'Foozilla'", data["res1"]) + self.assertIn("b'User-Agent': b'Foozilla'", data["res2"]) + self.assertIn("b'User-Agent': b'Foozilla'", data["res3"]) else: - self.assertNotIn("'user-agent': 'Foozilla'", data["res1"]) - self.assertIn("'user-agent': 'Foozilla'", data["res2"]) - self.assertIn("'user-agent': 'Foozilla'", data["res3"]) + self.assertNotIn("'User-Agent': 'Foozilla'", data["res1"]) + self.assertIn("'User-Agent': 'Foozilla'", data["res2"]) + self.assertIn("'User-Agent': 'Foozilla'", data["res3"]) def test_set_user_agent_base_url(self): resp = self.request_lua(""" @@ -2534,7 +2534,7 @@ def test_get_with_default_headers(self): headers = resp.json() self.assertNotEqual(len(headers), 0) self.assertEqual(len(headers), 1) - self.assertIn("Mozilla/5.0", headers["user-agent"]) + self.assertIn("Mozilla/5.0", headers["User-Agent"]) def test_get_with_custom_headers(self): resp = self.request_lua(""" @@ -2552,7 +2552,7 @@ def test_get_with_custom_headers(self): self.assertNotEqual(len(headers), 0) self.assertEqual(headers["Header-1"], "Value 1") self.assertEqual(headers["Header-2"], "Value 2") - self.assertIn("user-agent", headers) + self.assertIn("User-Agent", headers) def test_get_with_custom_ua(self): resp = self.request_lua(""" @@ -2565,26 +2565,26 @@ def test_get_with_custom_ua(self): self.assertStatusCode(resp, 200) headers = resp.json() self.assertNotEqual(len(headers), 0) - self.assertEqual(headers["user-agent"], "CUSTOM UA") + self.assertEqual(headers["User-Agent"], "CUSTOM UA") def test_get_with_custom_ua_in_headers(self): resp = self.request_lua(""" function main(splash) - response = assert(splash:http_get{splash.args.url, headers={["user-agent"]="Value 1"}}) + response = assert(splash:http_get{splash.args.url, headers={["User-Agent"]="Value 1"}}) return response.request.headers end """, {"url": self.mockurl("jsrender")}) self.assertStatusCode(resp, 200) headers = resp.json() self.assertNotEqual(len(headers), 0) - self.assertEqual(headers["user-agent"], "Value 1") + self.assertEqual(headers["User-Agent"], "Value 1") def test_get_with_custom_ua_in_headers_and_set_with_splash(self): resp = self.request_lua(""" function main(splash) splash:set_user_agent("CUSTOM UA") response1 = assert(splash:http_get(splash.args.url)) - response2 = assert(splash:http_get{splash.args.url, headers={["user-agent"]="Value 1"}}) + response2 = assert(splash:http_get{splash.args.url, headers={["User-Agent"]="Value 1"}}) response3 = assert(splash:http_get(splash.args.url)) return { @@ -2597,10 +2597,10 @@ def test_get_with_custom_ua_in_headers_and_set_with_splash(self): self.assertStatusCode(resp, 200) resp = resp.json() headers1, headers2, headers3 = resp["result1"], resp["result2"], resp["result3"] - self.assertTrue(all("user-agent" in h for h in (headers1, headers2, headers3))) - self.assertEqual(headers1["user-agent"], "CUSTOM UA") - self.assertEqual(headers2["user-agent"], "Value 1") - self.assertEqual(headers3["user-agent"], "CUSTOM UA") + self.assertTrue(all("User-Agent" in h for h in (headers1, headers2, headers3))) + self.assertEqual(headers1["User-Agent"], "CUSTOM UA") + self.assertEqual(headers2["User-Agent"], "Value 1") + self.assertEqual(headers3["User-Agent"], "CUSTOM UA") def test_ua_on_rendering(self): resp = self.request_lua(""" @@ -2611,13 +2611,13 @@ def test_ua_on_rendering(self): result[#result+1] = response.request.headers end) - response = assert(splash:go{splash.args.url, headers={["user-agent"]="Value 1"}}) + response = assert(splash:go{splash.args.url, headers={["User-Agent"]="Value 1"}}) return result end """, {"url": self.mockurl("subresources")}) self.assertStatusCode(resp, 200) resp = resp.json() - uas = [r.get("User-Agent", r.get("user-agent")) for r in resp] + uas = [r.get("User-Agent", r.get("User-Agent")) for r in resp] self.assertTrue(all(h == "Value 1" for h in uas)) def test_bad_url(self):