Files
daniel156161 076914e5b7 refactor: reorganize client transport and extension internals
- Split client, native, remote, serve, markdown, and SDK internals into focused packages with direct imports.
- Move local and remote transport framing/protocol helpers behind clearer module boundaries.
- Break up the extension injected DOM logic into a separate content dispatch bundle and dedicated content modules.
- Add explicit client handling for passive remote discovery without noisy PQ warnings.
- Keep behavior covered with updated unit, integration, and extension tests.
2026-06-13 23:31:24 +02:00

159 lines
5.8 KiB
Python

"""Tests for tabs.* commands."""
import time
import uuid
import pytest
def test_tabs_list(browser):
tabs = browser("tabs.list")
assert isinstance(tabs, list)
assert len(tabs) > 0
first = tabs[0]
assert "id" in first
assert "windowId" in first
assert "url" in first
assert "title" in first
assert "muted" in first
assert "groupId" in first
def test_tabs_count(browser):
count = browser("tabs.count", {})
tabs = browser("tabs.list")
assert count == len(tabs)
def test_tabs_count_with_pattern(browser):
count = browser("tabs.count", {"pattern": "http"})
assert isinstance(count, int)
assert count >= 0
def test_tabs_filter(browser):
result = browser("tabs.filter", {"pattern": "http"})
assert isinstance(result, list)
for tab in result:
assert "http" in tab.get("url", "")
def test_tabs_query(browser):
result = browser("tabs.query", {"search": "a"})
assert isinstance(result, list)
def test_tabs_active_exists(browser):
tabs = browser("tabs.list")
active = [t for t in tabs if t.get("active")]
assert len(active) >= 1, "Expected at least one active tab"
def test_tabs_active_in_window(browser):
active = next(t for t in browser("tabs.list") if t.get("active"))
result = browser("tabs.active_in_window", {"windowId": active["windowId"]})
assert result["id"] == active["id"]
assert result["windowId"] == active["windowId"]
def test_tabs_status(browser):
result = browser("tabs.status", {})
assert isinstance(result, dict)
assert "id" in result
assert "muted" in result
def test_tabs_html(browser, http_tab):
html = browser("tabs.html", {"tabId": http_tab["id"]})
assert isinstance(html, str)
assert len(html) > 0
assert "<html" in html.lower() or "<!doctype" in html.lower()
def test_tabs_close_by_id(browser):
result = browser("navigate.open", {"url": "https://example.com", "background": True})
tab_id = result["id"]
browser("tabs.close", {"tabId": tab_id})
tabs = browser("tabs.list")
assert tab_id not in [t["id"] for t in tabs]
def test_tabs_dedupe(browser):
# Use a unique URL so pre-existing example.com tabs cannot be selected as
# the survivor while both freshly opened duplicates stay open.
url = f"https://example.com/?browser-cli-dedupe={uuid.uuid4().hex}"
r1 = browser("navigate.open", {"url": url, "background": True})
r2 = browser("navigate.open", {"url": url, "background": True})
id1, id2 = r1["id"], r2["id"]
try:
# Dedupe keys on tab.url and intentionally skips tabs that haven't
# resolved a URL yet, so wait for both tabs to finish loading first.
for _ in range(30):
tabs = {t["id"]: t for t in browser("tabs.list")}
if all(tabs.get(tid, {}).get("url", "") == url for tid in (id1, id2)):
break
time.sleep(0.1)
else:
pytest.skip("Duplicate test tabs did not finish loading")
result = browser("tabs.dedupe")
assert isinstance(result, dict)
if result.get("jobId"):
for _ in range(100):
status = browser("jobs.status", {"jobId": result["jobId"]})
if status.get("status") in {"done", "error", "cancelled"}:
result = status.get("result") or result
break
time.sleep(0.1)
assert result.get("closed", 0) >= 0
# At least one of the two duplicates should be gone
remaining = browser("tabs.list")
remaining_ids = {t["id"] for t in remaining}
assert not (id1 in remaining_ids and id2 in remaining_ids), \
"Both duplicate tabs still open after dedupe"
finally:
for tid in (id1, id2):
try:
browser("tabs.close", {"tabId": tid})
except Exception:
pass
def test_tabs_sort(browser):
result = browser("tabs.sort", {"by": "domain"})
# No error and at least returns something (None or dict)
assert result is None or isinstance(result, dict)
def test_tabs_move_forward(browser):
r1 = browser("navigate.open", {"url": "https://example.com", "background": True})
r2 = browser("navigate.open", {"url": "https://example.com", "background": True})
id1, id2 = r1["id"], r2["id"]
try:
# Move id1 forward — just verify no error is raised
browser("tabs.move", {"tabId": id1, "forward": True})
finally:
browser("tabs.close", {"tabId": id1})
browser("tabs.close", {"tabId": id2})
def test_tabs_merge_windows_no_crash(browser):
result = browser("tabs.merge_windows")
assert isinstance(result, dict)
assert "moved" in result
def test_tabs_mute_and_unmute(browser, http_tab):
muted = browser("tabs.mute", {"tabId": http_tab["id"]})
assert isinstance(muted, dict)
assert muted["tabId"] == http_tab["id"]
assert muted["muted"] is True
listed = browser("tabs.list")
listed_tab = next(t for t in listed if t["id"] == http_tab["id"])
assert listed_tab["muted"] is True
unmuted = browser("tabs.unmute", {"tabId": http_tab["id"]})
assert isinstance(unmuted, dict)
assert unmuted["tabId"] == http_tab["id"]
assert unmuted["muted"] is False
listed = browser("tabs.list")
listed_tab = next(t for t in listed if t["id"] == http_tab["id"])
assert listed_tab["muted"] is False
status = browser("tabs.status", {"tabId": http_tab["id"]})
assert status["muted"] is False
def test_tabs_mute_requires_explicit_tab_when_multiple_tabs_open(browser):
opened = browser("navigate.open", {"url": "https://example.com", "background": True})
try:
with pytest.raises(RuntimeError, match="Refusing to mute without explicit tab ID"):
browser("tabs.mute", {})
finally:
browser("tabs.close", {"tabId": opened["id"]})