mirror of
https://github.com/servo/servo.git
synced 2025-06-06 00:25:37 +00:00
Devtools: add automated test for Debugger > Sources (#36401)
This patch adds our first automated test for devtools, covering the changes in #36164. These tests are not run in CI yet, but you can run them as follows: ```sh $ ./mach build --release $ ./mach test-devtools ``` Testing: this patch adds automated tests! Start of: #36325 --------- Signed-off-by: Delan Azabani <dazabani@igalia.com> Co-authored-by: atbrakhi <atbrakhi@igalia.com> Co-authored-by: Aria Edmonds <aria@ar1as.space>
This commit is contained in:
parent
23c327a988
commit
68a76baea3
7 changed files with 177 additions and 0 deletions
|
@ -37,3 +37,6 @@ types-requests
|
|||
|
||||
# For mach package on macOS.
|
||||
Mako == 1.2.2
|
||||
|
||||
# For devtools tests.
|
||||
geckordp == 1.0.3
|
||||
|
|
150
python/servo/devtools_tests.py
Normal file
150
python/servo/devtools_tests.py
Normal file
|
@ -0,0 +1,150 @@
|
|||
# Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
# file at the top-level directory of this distribution.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
# option. This file may not be copied, modified, or distributed
|
||||
# except according to those terms.
|
||||
|
||||
from concurrent.futures import Future
|
||||
import logging
|
||||
from geckordp.actors.root import RootActor
|
||||
from geckordp.actors.descriptors.tab import TabActor
|
||||
from geckordp.actors.watcher import WatcherActor
|
||||
from geckordp.actors.resources import Resources
|
||||
from geckordp.actors.events import Events
|
||||
from geckordp.rdp_client import RDPClient
|
||||
import http.server
|
||||
import os.path
|
||||
import socketserver
|
||||
import subprocess
|
||||
import time
|
||||
from threading import Thread
|
||||
from typing import Optional
|
||||
import unittest
|
||||
|
||||
|
||||
class DevtoolsTests(unittest.IsolatedAsyncioTestCase):
|
||||
# /path/to/servo/python/servo
|
||||
script_path = None
|
||||
|
||||
def __init__(self, methodName="runTest"):
|
||||
super().__init__(methodName)
|
||||
self.servoshell = None
|
||||
self.base_url = None
|
||||
self.web_server = None
|
||||
self.web_server_thread = None
|
||||
|
||||
def test_sources_list(self):
|
||||
self.run_servoshell(test_dir=os.path.join(DevtoolsTests.script_path, "devtools_tests/sources"))
|
||||
self.assert_sources_list([f"{self.base_url}/classic.js", f"{self.base_url}/test.html", "https://servo.org/js/load-table.js"])
|
||||
|
||||
def test_sources_list_with_data_no_scripts(self):
|
||||
self.run_servoshell(url="data:text/html,")
|
||||
self.assert_sources_list([])
|
||||
|
||||
def test_sources_list_with_data_empty_inline_script(self):
|
||||
self.run_servoshell(url="data:text/html,<script></script>")
|
||||
self.assert_sources_list([])
|
||||
|
||||
def test_sources_list_with_data_inline_script(self):
|
||||
self.run_servoshell(url="data:text/html,<script>;</script>")
|
||||
self.assert_sources_list(["data:text/html,<script>;</script>"])
|
||||
|
||||
def run_servoshell(self, *, test_dir=None, url=None):
|
||||
if test_dir is None:
|
||||
test_dir = os.path.join(DevtoolsTests.script_path, "devtools_tests")
|
||||
base_url = Future()
|
||||
|
||||
class Handler(http.server.SimpleHTTPRequestHandler):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, directory=test_dir, **kwargs)
|
||||
|
||||
def log_message(self, format, *args):
|
||||
# Uncomment this to log requests.
|
||||
# return super().log_message(format, *args)
|
||||
pass
|
||||
|
||||
def server_thread():
|
||||
self.web_server = socketserver.TCPServer(("0.0.0.0", 0), Handler)
|
||||
base_url.set_result(f"http://127.0.0.1:{self.web_server.server_address[1]}")
|
||||
self.web_server.serve_forever()
|
||||
|
||||
# Start a web server for the test.
|
||||
self.web_server_thread = Thread(target=server_thread)
|
||||
self.web_server_thread.start()
|
||||
self.base_url = base_url.result(1)
|
||||
|
||||
# Change this setting if you want to debug Servo.
|
||||
os.environ["RUST_LOG"] = "error,devtools=warn"
|
||||
|
||||
# Run servoshell.
|
||||
if url is None:
|
||||
url = f"{self.base_url}/test.html"
|
||||
self.servoshell = subprocess.Popen(["target/release/servo", "--devtools=6080", url])
|
||||
|
||||
# FIXME: Don’t do this
|
||||
time.sleep(1)
|
||||
|
||||
def tearDown(self):
|
||||
# Terminate servoshell.
|
||||
self.servoshell.terminate()
|
||||
|
||||
# Stop the web server.
|
||||
self.web_server.shutdown()
|
||||
self.web_server_thread.join()
|
||||
|
||||
def assert_sources_list(self, expected_urls):
|
||||
client = RDPClient()
|
||||
client.connect("127.0.0.1", 6080)
|
||||
root = RootActor(client)
|
||||
tabs = root.list_tabs()
|
||||
tab_dict = tabs[0]
|
||||
tab = TabActor(client, tab_dict["actor"])
|
||||
watcher = tab.get_watcher()
|
||||
watcher = WatcherActor(client, watcher["actor"])
|
||||
|
||||
target = Future()
|
||||
|
||||
def on_target(data):
|
||||
if data["target"]["browsingContextID"] == tab_dict["browsingContextID"]:
|
||||
target.set_result(data["target"])
|
||||
|
||||
client.add_event_listener(
|
||||
watcher.actor_id, Events.Watcher.TARGET_AVAILABLE_FORM, on_target,
|
||||
)
|
||||
watcher.watch_targets(WatcherActor.Targets.FRAME)
|
||||
|
||||
done = Future()
|
||||
target = target.result(1)
|
||||
|
||||
def on_source_resource(data):
|
||||
for [resource_type, sources] in data["array"]:
|
||||
try:
|
||||
self.assertEqual(resource_type, "source")
|
||||
self.assertEqual([source["url"] for source in sources], expected_urls)
|
||||
done.set_result(None)
|
||||
except Exception as e:
|
||||
# Raising here does nothing, for some reason.
|
||||
# Send the exception back so it can be raised.
|
||||
done.set_result(e)
|
||||
|
||||
client.add_event_listener(
|
||||
target["actor"],
|
||||
Events.Watcher.RESOURCES_AVAILABLE_ARRAY,
|
||||
on_source_resource,
|
||||
)
|
||||
watcher.watch_resources([Resources.SOURCE])
|
||||
|
||||
result: Optional[Exception] = done.result(1)
|
||||
if result:
|
||||
raise result
|
||||
client.disconnect()
|
||||
|
||||
|
||||
def run_tests(script_path):
|
||||
DevtoolsTests.script_path = script_path
|
||||
verbosity = 1 if logging.getLogger().level >= logging.WARN else 2
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(DevtoolsTests)
|
||||
return unittest.TextTestRunner(verbosity=verbosity).run(suite).wasSuccessful()
|
1
python/servo/devtools_tests/sources/classic.js
Normal file
1
python/servo/devtools_tests/sources/classic.js
Normal file
|
@ -0,0 +1 @@
|
|||
console.log("external classic");
|
2
python/servo/devtools_tests/sources/module.js
Normal file
2
python/servo/devtools_tests/sources/module.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
export default 1;
|
||||
console.log("external module");
|
11
python/servo/devtools_tests/sources/test.html
Normal file
11
python/servo/devtools_tests/sources/test.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<!doctype html><meta charset=utf-8>
|
||||
<script src="classic.js"></script>
|
||||
<script>
|
||||
console.log("inline classic");
|
||||
new Worker("worker.js");
|
||||
</script>
|
||||
<script type="module">
|
||||
import module from "./module.js";
|
||||
console.log("inline module");
|
||||
</script>
|
||||
<script src="https://servo.org/js/load-table.js"></script>
|
1
python/servo/devtools_tests/sources/worker.js
Normal file
1
python/servo/devtools_tests/sources/worker.js
Normal file
|
@ -0,0 +1 @@
|
|||
console.log("external classic worker");
|
|
@ -19,6 +19,7 @@ import subprocess
|
|||
import textwrap
|
||||
import json
|
||||
|
||||
import servo.devtools_tests
|
||||
from servo.post_build_commands import PostBuildCommands
|
||||
import wpt
|
||||
import wpt.manifestupdate
|
||||
|
@ -326,6 +327,14 @@ class MachCommands(CommandBase):
|
|||
|
||||
return 0 if passed else 1
|
||||
|
||||
@Command('test-devtools',
|
||||
description='Run tests for devtools.',
|
||||
category='testing')
|
||||
def test_devtools(self):
|
||||
print("Running devtools tests...")
|
||||
passed = servo.devtools_tests.run_tests(SCRIPT_PATH)
|
||||
return 0 if passed else 1
|
||||
|
||||
@Command('test-wpt-failure',
|
||||
description='Run the tests harness that verifies that the test failures are reported correctly',
|
||||
category='testing',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue