|
| 1 | +# Licensed to the Software Freedom Conservancy (SFC) under one |
| 2 | +# or more contributor license agreements. See the NOTICE file |
| 3 | +# distributed with this work for additional information |
| 4 | +# regarding copyright ownership. The SFC licenses this file |
| 5 | +# to you under the Apache License, Version 2.0 (the |
| 6 | +# "License"); you may not use this file except in compliance |
| 7 | +# with the License. You may obtain a copy of the License at |
| 8 | +# |
| 9 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | +# |
| 11 | +# Unless required by applicable law or agreed to in writing, |
| 12 | +# software distributed under the License is distributed on an |
| 13 | +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 14 | +# KIND, either express or implied. See the License for the |
| 15 | +# specific language governing permissions and limitations |
| 16 | +# under the License. |
| 17 | + |
| 18 | +"""Mirror of ``../bidi/browser_tests.py`` using the generated ``_bidi`` commands, not the ``driver`` facade.""" |
| 19 | + |
| 20 | +import os |
| 21 | + |
| 22 | +import pytest |
| 23 | + |
| 24 | +from selenium.common.exceptions import TimeoutException, WebDriverException |
| 25 | +from selenium.webdriver.common._bidi.browser import ( |
| 26 | + Browser, |
| 27 | + ClientWindowInfo, |
| 28 | + ClientWindowInfoState, |
| 29 | + DownloadBehaviorAllowed, |
| 30 | + DownloadBehaviorDenied, |
| 31 | +) |
| 32 | +from selenium.webdriver.common._bidi.browsing_context import BrowsingContext, CreateType, ReadinessState |
| 33 | +from selenium.webdriver.common._bidi.session import ( |
| 34 | + DirectProxyConfiguration, |
| 35 | + ManualProxyConfiguration, |
| 36 | + UserPromptHandler, |
| 37 | + UserPromptHandlerType, |
| 38 | +) |
| 39 | +from selenium.webdriver.common.by import By |
| 40 | +from selenium.webdriver.support.ui import WebDriverWait |
| 41 | + |
| 42 | + |
| 43 | +def test_create_user_context(driver): |
| 44 | + browser = Browser(driver) |
| 45 | + result = browser.create_user_context() |
| 46 | + assert result.user_context |
| 47 | + browser.remove_user_context(user_context=result.user_context) |
| 48 | + |
| 49 | + |
| 50 | +def test_get_user_contexts(driver): |
| 51 | + browser = Browser(driver) |
| 52 | + first = browser.create_user_context().user_context |
| 53 | + second = browser.create_user_context().user_context |
| 54 | + |
| 55 | + ids = [info.user_context for info in browser.get_user_contexts().user_contexts] |
| 56 | + assert first in ids |
| 57 | + assert second in ids |
| 58 | + |
| 59 | + browser.remove_user_context(user_context=first) |
| 60 | + browser.remove_user_context(user_context=second) |
| 61 | + |
| 62 | + |
| 63 | +def test_remove_user_context(driver): |
| 64 | + browser = Browser(driver) |
| 65 | + first = browser.create_user_context().user_context |
| 66 | + second = browser.create_user_context().user_context |
| 67 | + |
| 68 | + browser.remove_user_context(user_context=second) |
| 69 | + |
| 70 | + ids = [info.user_context for info in browser.get_user_contexts().user_contexts] |
| 71 | + assert first in ids |
| 72 | + assert second not in ids |
| 73 | + |
| 74 | + browser.remove_user_context(user_context=first) |
| 75 | + |
| 76 | + |
| 77 | +def test_get_client_windows(driver): |
| 78 | + result = Browser(driver).get_client_windows() |
| 79 | + |
| 80 | + assert result.client_windows |
| 81 | + window = result.client_windows[0] |
| 82 | + assert isinstance(window, ClientWindowInfo) |
| 83 | + assert window.client_window |
| 84 | + assert isinstance(window.state, str) |
| 85 | + assert window.width > 0 |
| 86 | + assert window.height > 0 |
| 87 | + assert isinstance(window.active, bool) |
| 88 | + assert isinstance(window.x, int) |
| 89 | + assert isinstance(window.y, int) |
| 90 | + |
| 91 | + |
| 92 | +def test_removing_default_user_context_raises(driver): |
| 93 | + with pytest.raises(WebDriverException): |
| 94 | + Browser(driver).remove_user_context(user_context="default") |
| 95 | + |
| 96 | + |
| 97 | +def test_client_window_state_constants(): |
| 98 | + assert ClientWindowInfoState.FULLSCREEN == "fullscreen" |
| 99 | + assert ClientWindowInfoState.MAXIMIZED == "maximized" |
| 100 | + assert ClientWindowInfoState.MINIMIZED == "minimized" |
| 101 | + assert ClientWindowInfoState.NORMAL == "normal" |
| 102 | + |
| 103 | + |
| 104 | +def test_create_user_context_with_accept_insecure_certs(driver): |
| 105 | + browser = Browser(driver) |
| 106 | + user_context = browser.create_user_context(accept_insecure_certs=True).user_context |
| 107 | + |
| 108 | + bc = BrowsingContext(driver).create(type=CreateType.WINDOW, user_context=user_context).context |
| 109 | + driver.switch_to.window(bc) |
| 110 | + |
| 111 | + driver.get("https://self-signed.badssl.com/") |
| 112 | + h1 = driver.find_element(By.TAG_NAME, "h1") |
| 113 | + assert h1.text.strip() == "self-signed.\nbadssl.com" |
| 114 | + |
| 115 | + browser.remove_user_context(user_context=user_context) |
| 116 | + |
| 117 | + |
| 118 | +def test_create_user_context_with_direct_proxy(driver): |
| 119 | + browser = Browser(driver) |
| 120 | + user_context = browser.create_user_context(proxy=DirectProxyConfiguration()).user_context |
| 121 | + |
| 122 | + bc = BrowsingContext(driver).create(type=CreateType.WINDOW, user_context=user_context).context |
| 123 | + driver.switch_to.window(bc) |
| 124 | + |
| 125 | + driver.get("http://example.com/") |
| 126 | + assert "example domain" in driver.find_element(By.TAG_NAME, "body").text.lower() |
| 127 | + |
| 128 | + browser.remove_user_context(user_context=user_context) |
| 129 | + |
| 130 | + |
| 131 | +def test_create_user_context_with_unhandled_prompt_behavior(driver): |
| 132 | + browser = Browser(driver) |
| 133 | + handler = UserPromptHandler( |
| 134 | + alert=UserPromptHandlerType.DISMISS, |
| 135 | + default=UserPromptHandlerType.DISMISS, |
| 136 | + prompt=UserPromptHandlerType.DISMISS, |
| 137 | + ) |
| 138 | + user_context = browser.create_user_context(unhandled_prompt_behavior=handler).user_context |
| 139 | + |
| 140 | + ids = [info.user_context for info in browser.get_user_contexts().user_contexts] |
| 141 | + assert user_context in ids |
| 142 | + |
| 143 | + browser.remove_user_context(user_context=user_context) |
| 144 | + |
| 145 | + |
| 146 | +@pytest.mark.xfail_chrome(reason="Chrome auto upgrades HTTP to HTTPS in untrusted networks like CI environments") |
| 147 | +def test_create_user_context_with_manual_proxy_all_params(driver, proxy_server): |
| 148 | + create_proxy_server = proxy_server(response_content=b"proxied response") |
| 149 | + no_proxy_server = proxy_server(response_content=b"direct connection - not proxied") |
| 150 | + proxy_port = create_proxy_server["port"] |
| 151 | + no_proxy_port = no_proxy_server["port"] |
| 152 | + |
| 153 | + proxy = ManualProxyConfiguration( |
| 154 | + http_proxy=f"localhost:{proxy_port}", |
| 155 | + ssl_proxy=f"localhost:{proxy_port}", |
| 156 | + socks_proxy=f"localhost:{proxy_port}", |
| 157 | + socks_version=5, |
| 158 | + no_proxy=[f"localhost:{no_proxy_port}"], |
| 159 | + ) |
| 160 | + browser = Browser(driver) |
| 161 | + user_context = browser.create_user_context(proxy=proxy).user_context |
| 162 | + |
| 163 | + bc = BrowsingContext(driver).create(type=CreateType.WINDOW, user_context=user_context).context |
| 164 | + driver.switch_to.window(bc) |
| 165 | + |
| 166 | + try: |
| 167 | + driver.get(f"http://localhost:{no_proxy_port}/") |
| 168 | + assert "direct connection - not proxied" in driver.find_element(By.TAG_NAME, "body").text.lower() |
| 169 | + |
| 170 | + driver.get("http://example.com/") |
| 171 | + assert "proxied response" in driver.find_element(By.TAG_NAME, "body").text.lower() |
| 172 | + finally: |
| 173 | + browser.remove_user_context(user_context=user_context) |
| 174 | + |
| 175 | + |
| 176 | +@pytest.mark.xfail_chrome(reason="Chrome auto upgrades HTTP to HTTPS in untrusted networks like CI environments") |
| 177 | +def test_create_user_context_with_proxy_and_accept_insecure_certs(driver, proxy_server): |
| 178 | + create_proxy_server = proxy_server(response_content=b"proxied response") |
| 179 | + port = create_proxy_server["port"] |
| 180 | + |
| 181 | + proxy = ManualProxyConfiguration( |
| 182 | + http_proxy=f"localhost:{port}", |
| 183 | + ssl_proxy=f"localhost:{port}", |
| 184 | + socks_proxy=f"localhost:{port}", |
| 185 | + socks_version=5, |
| 186 | + no_proxy=["self-signed.badssl.com"], |
| 187 | + ) |
| 188 | + browser = Browser(driver) |
| 189 | + user_context = browser.create_user_context(accept_insecure_certs=True, proxy=proxy).user_context |
| 190 | + |
| 191 | + bc = BrowsingContext(driver).create(type=CreateType.WINDOW, user_context=user_context).context |
| 192 | + driver.switch_to.window(bc) |
| 193 | + |
| 194 | + try: |
| 195 | + driver.get("https://self-signed.badssl.com/") |
| 196 | + assert "badssl.com" in driver.find_element(By.TAG_NAME, "h1").text.lower() |
| 197 | + |
| 198 | + driver.get("http://example.com/") |
| 199 | + assert "proxied response" in driver.find_element(By.TAG_NAME, "body").text.lower() |
| 200 | + finally: |
| 201 | + browser.remove_user_context(user_context=user_context) |
| 202 | + |
| 203 | + |
| 204 | +# The facade's ``set_download_behavior(allowed=..., destination_folder=...)`` builds a |
| 205 | +# DownloadBehavior union; the generated command takes the typed variant directly. |
| 206 | + |
| 207 | + |
| 208 | +@pytest.mark.xfail_firefox |
| 209 | +def test_set_download_behavior_allowed(driver, pages, tmp_path): |
| 210 | + browser = Browser(driver) |
| 211 | + try: |
| 212 | + browser.set_download_behavior(download_behavior=DownloadBehaviorAllowed(destination_folder=str(tmp_path))) |
| 213 | + |
| 214 | + context_id = driver.current_window_handle |
| 215 | + BrowsingContext(driver).navigate( |
| 216 | + context=context_id, url=pages.url("downloads/download.html"), wait=ReadinessState.COMPLETE |
| 217 | + ) |
| 218 | + driver.find_element(By.ID, "file-1").click() |
| 219 | + |
| 220 | + WebDriverWait(driver, 5).until(lambda d: "file_1.txt" in os.listdir(tmp_path)) |
| 221 | + assert "file_1.txt" in os.listdir(tmp_path) |
| 222 | + finally: |
| 223 | + browser.set_download_behavior(download_behavior=None) |
| 224 | + |
| 225 | + |
| 226 | +@pytest.mark.xfail_firefox |
| 227 | +def test_set_download_behavior_denied(driver, pages, tmp_path): |
| 228 | + browser = Browser(driver) |
| 229 | + try: |
| 230 | + browser.set_download_behavior(download_behavior=DownloadBehaviorDenied()) |
| 231 | + |
| 232 | + context_id = driver.current_window_handle |
| 233 | + BrowsingContext(driver).navigate( |
| 234 | + context=context_id, url=pages.url("downloads/download.html"), wait=ReadinessState.COMPLETE |
| 235 | + ) |
| 236 | + driver.find_element(By.ID, "file-1").click() |
| 237 | + |
| 238 | + with pytest.raises(TimeoutException): |
| 239 | + WebDriverWait(driver, 3, poll_frequency=0.2).until(lambda _: len(os.listdir(tmp_path)) > 0) |
| 240 | + finally: |
| 241 | + browser.set_download_behavior(download_behavior=None) |
| 242 | + |
| 243 | + |
| 244 | +@pytest.mark.xfail_firefox |
| 245 | +def test_set_download_behavior_user_context(driver, pages, tmp_path): |
| 246 | + browser = Browser(driver) |
| 247 | + user_context = browser.create_user_context().user_context |
| 248 | + try: |
| 249 | + bc = BrowsingContext(driver).create(type=CreateType.WINDOW, user_context=user_context).context |
| 250 | + driver.switch_to.window(bc) |
| 251 | + try: |
| 252 | + browser.set_download_behavior( |
| 253 | + download_behavior=DownloadBehaviorAllowed(destination_folder=str(tmp_path)), |
| 254 | + user_contexts=[user_context], |
| 255 | + ) |
| 256 | + BrowsingContext(driver).navigate( |
| 257 | + context=bc, url=pages.url("downloads/download.html"), wait=ReadinessState.COMPLETE |
| 258 | + ) |
| 259 | + driver.find_element(By.ID, "file-1").click() |
| 260 | + |
| 261 | + WebDriverWait(driver, 5).until(lambda d: "file_1.txt" in os.listdir(tmp_path)) |
| 262 | + initial_file_count = len(os.listdir(tmp_path)) |
| 263 | + |
| 264 | + browser.set_download_behavior(download_behavior=DownloadBehaviorDenied(), user_contexts=[user_context]) |
| 265 | + driver.find_element(By.ID, "file-2").click() |
| 266 | + |
| 267 | + with pytest.raises(TimeoutException): |
| 268 | + WebDriverWait(driver, 3, poll_frequency=0.2).until( |
| 269 | + lambda _: len(os.listdir(tmp_path)) > initial_file_count |
| 270 | + ) |
| 271 | + finally: |
| 272 | + browser.set_download_behavior(download_behavior=None, user_contexts=[user_context]) |
| 273 | + finally: |
| 274 | + browser.remove_user_context(user_context=user_context) |
0 commit comments