summaryrefslogtreecommitdiffstats
path: root/testing/webcompat/fixtures.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/webcompat/fixtures.py')
-rw-r--r--testing/webcompat/fixtures.py255
1 files changed, 255 insertions, 0 deletions
diff --git a/testing/webcompat/fixtures.py b/testing/webcompat/fixtures.py
new file mode 100644
index 0000000000..443adfae81
--- /dev/null
+++ b/testing/webcompat/fixtures.py
@@ -0,0 +1,255 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import asyncio
+import json
+import re
+import subprocess
+
+import pytest
+import webdriver
+
+from client import Client
+
+APS_PREF = "privacy.partition.always_partition_third_party_non_cookie_storage"
+CB_PBM_PREF = "network.cookie.cookieBehavior.pbmode"
+CB_PREF = "network.cookie.cookieBehavior"
+INJECTIONS_PREF = "extensions.webcompat.perform_injections"
+PBM_PREF = "browser.privatebrowsing.autostart"
+PIP_OVERRIDES_PREF = "extensions.webcompat.enable_picture_in_picture_overrides"
+SHIMS_PREF = "extensions.webcompat.enable_shims"
+STRICT_ETP_PREF = "privacy.trackingprotection.enabled"
+UA_OVERRIDES_PREF = "extensions.webcompat.perform_ua_overrides"
+
+
+class WebDriver:
+ def __init__(self, config):
+ self.browser_binary = config.getoption("browser_binary")
+ self.device_serial = config.getoption("device_serial")
+ self.package_name = config.getoption("package_name")
+ self.addon = config.getoption("addon")
+ self.webdriver_binary = config.getoption("webdriver_binary")
+ self.port = config.getoption("webdriver_port")
+ self.wsPort = config.getoption("webdriver_ws_port")
+ self.headless = config.getoption("headless")
+ self.proc = None
+
+ def command_line_driver(self):
+ raise NotImplementedError
+
+ def capabilities(self, test_config):
+ raise NotImplementedError
+
+ def __enter__(self):
+ assert self.proc is None
+ self.proc = subprocess.Popen(self.command_line_driver())
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ self.proc.kill()
+
+
+class FirefoxWebDriver(WebDriver):
+ def command_line_driver(self):
+ return [
+ self.webdriver_binary,
+ "--port",
+ str(self.port),
+ "--websocket-port",
+ str(self.wsPort),
+ "-vv",
+ ]
+
+ def capabilities(self, test_config):
+ prefs = {}
+
+ if "aps" in test_config:
+ prefs[APS_PREF] = test_config["aps"]
+
+ if "use_interventions" in test_config:
+ value = test_config["use_interventions"]
+ prefs[INJECTIONS_PREF] = value
+ prefs[UA_OVERRIDES_PREF] = value
+ prefs[PIP_OVERRIDES_PREF] = value
+
+ if "use_pbm" in test_config:
+ prefs[PBM_PREF] = test_config["use_pbm"]
+
+ if "use_shims" in test_config:
+ prefs[SHIMS_PREF] = test_config["use_shims"]
+
+ if "use_strict_etp" in test_config:
+ prefs[STRICT_ETP_PREF] = test_config["use_strict_etp"]
+
+ # remote/cdp/CDP.sys.mjs sets cookieBehavior to 0,
+ # which we definitely do not want, so set it back to 5.
+ cookieBehavior = 4 if test_config.get("without_tcp") else 5
+ prefs[CB_PREF] = cookieBehavior
+ prefs[CB_PBM_PREF] = cookieBehavior
+
+ fx_options = {"prefs": prefs}
+
+ if self.browser_binary:
+ fx_options["binary"] = self.browser_binary
+ if self.headless:
+ fx_options["args"] = ["--headless"]
+
+ if self.device_serial:
+ fx_options["androidDeviceSerial"] = self.device_serial
+ fx_options["androidPackage"] = self.package_name
+
+ if self.addon:
+ prefs["xpinstall.signatures.required"] = False
+ prefs["extensions.experiments.enabled"] = True
+
+ return {
+ "pageLoadStrategy": "normal",
+ "moz:firefoxOptions": fx_options,
+ }
+
+
+@pytest.fixture(scope="session")
+def should_do_2fa(request):
+ return request.config.getoption("do2fa", False)
+
+
+@pytest.fixture(scope="session")
+def config_file(request):
+ path = request.config.getoption("config")
+ if not path:
+ return None
+ with open(path) as f:
+ return json.load(f)
+
+
+@pytest.fixture
+def bug_number(request):
+ return re.findall("\d+", str(request.fspath.basename))[0]
+
+
+@pytest.fixture
+def credentials(bug_number, config_file):
+ if not config_file:
+ pytest.skip(f"login info required for bug #{bug_number}")
+ return None
+
+ try:
+ credentials = config_file[bug_number]
+ except KeyError:
+ pytest.skip(f"no login for bug #{bug_number} found")
+ return
+
+ return {"username": credentials["username"], "password": credentials["password"]}
+
+
+@pytest.fixture(scope="session")
+def driver(pytestconfig):
+ if pytestconfig.getoption("browser") == "firefox":
+ cls = FirefoxWebDriver
+ else:
+ assert False
+
+ with cls(pytestconfig) as driver_instance:
+ yield driver_instance
+
+
+@pytest.fixture(scope="session")
+def event_loop():
+ return asyncio.get_event_loop_policy().new_event_loop()
+
+
+@pytest.fixture(scope="function")
+async def client(session, event_loop):
+ return Client(session, event_loop)
+
+
+def install_addon(session, addon_file_path):
+ context = session.send_session_command("GET", "moz/context")
+ session.send_session_command("POST", "moz/context", {"context": "chrome"})
+ session.execute_async_script(
+ """
+ const addon_file_path = arguments[0];
+ const cb = arguments[1];
+ const { AddonManager } = ChromeUtils.import(
+ "resource://gre/modules/AddonManager.jsm"
+ );
+ const { ExtensionPermissions } = ChromeUtils.import(
+ "resource://gre/modules/ExtensionPermissions.jsm"
+ );
+ const { FileUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/FileUtils.sys.mjs"
+ );
+ const file = new FileUtils.File(arguments[0]);
+ AddonManager.installTemporaryAddon(file).then(addon => {
+ // also make sure the addon works in private browsing mode
+ const incognitoPermission = {
+ permissions: ["internal:privateBrowsingAllowed"],
+ origins: [],
+ };
+ ExtensionPermissions.add(addon.id, incognitoPermission).then(() => {
+ addon.reload().then(cb);
+ });
+ });
+ """,
+ [addon_file_path],
+ )
+ session.send_session_command("POST", "moz/context", {"context": context})
+
+
+@pytest.fixture(scope="function")
+async def session(driver, test_config):
+ caps = driver.capabilities(test_config)
+ caps.update(
+ {
+ "acceptInsecureCerts": True,
+ "webSocketUrl": True,
+ }
+ )
+ caps = {"alwaysMatch": caps}
+ print(caps)
+
+ session = None
+ for i in range(0, 15):
+ try:
+ if not session:
+ session = webdriver.Session(
+ "localhost", driver.port, capabilities=caps, enable_bidi=True
+ )
+ session.test_config = test_config
+ session.start()
+ break
+ except (ConnectionRefusedError, webdriver.error.TimeoutException):
+ await asyncio.sleep(0.5)
+
+ await session.bidi_session.start()
+
+ if driver.addon:
+ install_addon(session, driver.addon)
+
+ yield session
+
+ await session.bidi_session.end()
+ session.end()
+
+
+@pytest.fixture(autouse=True)
+def platform(session):
+ return session.capabilities["platformName"]
+
+
+@pytest.fixture(autouse=True)
+def only_platforms(bug_number, platform, request, session):
+ if request.node.get_closest_marker("only_platforms"):
+ for only in request.node.get_closest_marker("only_platforms").args:
+ if only == platform:
+ return
+ pytest.skip(f"Bug #{bug_number} skipped on platform ({platform})")
+
+
+@pytest.fixture(autouse=True)
+def skip_platforms(bug_number, platform, request, session):
+ if request.node.get_closest_marker("skip_platforms"):
+ for skipped in request.node.get_closest_marker("skip_platforms").args:
+ if skipped == platform:
+ pytest.skip(f"Bug #{bug_number} skipped on platform ({platform})")