ruff fixes and formatting

This commit is contained in:
2025-11-16 00:46:42 -06:00
parent 3cddaeb2b9
commit 5ec677437e
13 changed files with 244 additions and 122 deletions

View File

@@ -99,6 +99,7 @@ def reload_reticulum(page: Page, on_complete=None):
on_complete: Optional callback to run when reload is complete on_complete: Optional callback to run when reload is complete
""" """
def reload_thread(): def reload_thread():
import time import time
@@ -140,6 +141,7 @@ def reload_reticulum(page: Page, on_complete=None):
try: try:
# Re-initialize Reticulum # Re-initialize Reticulum
import ren_browser.logs import ren_browser.logs
ren_browser.logs.setup_rns_logging() ren_browser.logs.setup_rns_logging()
RNS_INSTANCE = RNS.Reticulum(str(config_dir)) RNS_INSTANCE = RNS.Reticulum(str(config_dir))
@@ -172,10 +174,17 @@ def run():
help="Select renderer (plaintext or micron)", help="Select renderer (plaintext or micron)",
) )
parser.add_argument( parser.add_argument(
"-w", "--web", action="store_true", help="Launch in web browser mode", "-w",
"--web",
action="store_true",
help="Launch in web browser mode",
) )
parser.add_argument( parser.add_argument(
"-p", "--port", type=int, default=None, help="Port for web server", "-p",
"--port",
type=int,
default=None,
help="Port for web server",
) )
parser.add_argument( parser.add_argument(
"-c", "-c",

View File

@@ -37,14 +37,16 @@ def parse_micron_line(line: str) -> list:
while i < len(line): while i < len(line):
if line[i] == "`" and i + 1 < len(line): if line[i] == "`" and i + 1 < len(line):
if current_text: if current_text:
spans.append({ spans.append(
{
"text": current_text, "text": current_text,
"bold": bold, "bold": bold,
"italic": italic, "italic": italic,
"underline": underline, "underline": underline,
"color": color, "color": color,
"bgcolor": bgcolor, "bgcolor": bgcolor,
}) }
)
current_text = "" current_text = ""
tag = line[i + 1] tag = line[i + 1]
@@ -59,13 +61,13 @@ def parse_micron_line(line: str) -> list:
underline = not underline underline = not underline
i += 2 i += 2
elif tag == "F" and i + 5 <= len(line): elif tag == "F" and i + 5 <= len(line):
color = hex_to_rgb(line[i+2:i+5]) color = hex_to_rgb(line[i + 2 : i + 5])
i += 5 i += 5
elif tag == "f": elif tag == "f":
color = None color = None
i += 2 i += 2
elif tag == "B" and i + 5 <= len(line): elif tag == "B" and i + 5 <= len(line):
bgcolor = hex_to_rgb(line[i+2:i+5]) bgcolor = hex_to_rgb(line[i + 2 : i + 5])
i += 5 i += 5
elif tag == "b": elif tag == "b":
bgcolor = None bgcolor = None
@@ -85,14 +87,16 @@ def parse_micron_line(line: str) -> list:
i += 1 i += 1
if current_text: if current_text:
spans.append({ spans.append(
{
"text": current_text, "text": current_text,
"bold": bold, "bold": bold,
"italic": italic, "italic": italic,
"underline": underline, "underline": underline,
"color": color, "color": color,
"bgcolor": bgcolor, "bgcolor": bgcolor,
}) }
)
return spans return spans
@@ -186,11 +190,10 @@ def _render_micron_internal(content: str, on_link_click=None) -> ft.Control:
if "`[" in line: if "`[" in line:
row_controls = [] row_controls = []
remaining = line
last_end = 0 last_end = 0
for link_match in re.finditer(r"`\[([^`]*)`([^\]]*)\]", line): for link_match in re.finditer(r"`\[([^`]*)`([^\]]*)\]", line):
before = line[last_end:link_match.start()] before = line[last_end : link_match.start()]
if before: if before:
before_spans = parse_micron_line(before) before_spans = parse_micron_line(before)
for span in before_spans: for span in before_spans:
@@ -203,6 +206,7 @@ def _render_micron_internal(content: str, on_link_click=None) -> ft.Control:
def handler(e): def handler(e):
if on_link_click: if on_link_click:
on_link_click(link_url) on_link_click(link_url)
return handler return handler
row_controls.append( row_controls.append(

View File

@@ -51,9 +51,7 @@ class StorageManager:
elif "APPDATA" in os.environ: # Windows elif "APPDATA" in os.environ: # Windows
storage_dir = pathlib.Path(os.environ["APPDATA"]) / "ren_browser" storage_dir = pathlib.Path(os.environ["APPDATA"]) / "ren_browser"
elif "XDG_CONFIG_HOME" in os.environ: # Linux XDG standard elif "XDG_CONFIG_HOME" in os.environ: # Linux XDG standard
storage_dir = ( storage_dir = pathlib.Path(os.environ["XDG_CONFIG_HOME"]) / "ren_browser"
pathlib.Path(os.environ["XDG_CONFIG_HOME"]) / "ren_browser"
)
else: else:
storage_dir = pathlib.Path.home() / ".ren_browser" storage_dir = pathlib.Path.home() / ".ren_browser"
@@ -126,7 +124,8 @@ class StorageManager:
if self.page and hasattr(self.page, "client_storage"): if self.page and hasattr(self.page, "client_storage"):
self.page.client_storage.set("ren_browser_config", config_content) self.page.client_storage.set("ren_browser_config", config_content)
self.page.client_storage.set( self.page.client_storage.set(
"ren_browser_config_error", f"File save failed: {error}", "ren_browser_config_error",
f"File save failed: {error}",
) )
return True return True
@@ -193,7 +192,8 @@ class StorageManager:
if self.page and hasattr(self.page, "client_storage"): if self.page and hasattr(self.page, "client_storage"):
self.page.client_storage.set( self.page.client_storage.set(
"ren_browser_bookmarks", json.dumps(bookmarks), "ren_browser_bookmarks",
json.dumps(bookmarks),
) )
return True return True
@@ -258,7 +258,9 @@ class StorageManager:
json.dump(settings, f, indent=2) json.dump(settings, f, indent=2)
if self.page and hasattr(self.page, "client_storage"): if self.page and hasattr(self.page, "client_storage"):
self.page.client_storage.set("ren_browser_settings", json.dumps(settings)) self.page.client_storage.set(
"ren_browser_settings", json.dumps(settings)
)
return True return True
except Exception: except Exception:

View File

@@ -60,7 +60,9 @@ class TabsManager:
self._on_tab_go(None, 0) self._on_tab_go(None, 0)
default_content = ( default_content = (
render_micron("Welcome to Ren Browser", on_link_click=handle_link_click_home) render_micron(
"Welcome to Ren Browser", on_link_click=handle_link_click_home
)
if app_module.RENDERER == "micron" if app_module.RENDERER == "micron"
else render_plaintext("Welcome to Ren Browser") else render_plaintext("Welcome to Ren Browser")
) )
@@ -127,7 +129,9 @@ class TabsManager:
cumulative_width = 0 cumulative_width = 0
visible_tabs_count = 0 visible_tabs_count = 0
tab_containers = [c for c in self.tab_bar.content.controls if isinstance(c, ft.Container)] tab_containers = [
c for c in self.tab_bar.content.controls if isinstance(c, ft.Container)
]
for i, tab in enumerate(self.manager.tabs): for i, tab in enumerate(self.manager.tabs):
estimated_width = len(tab["title"]) * 10 + 32 + self.tab_bar.content.spacing estimated_width = len(tab["title"]) * 10 + 32 + self.tab_bar.content.spacing
@@ -254,13 +258,17 @@ class TabsManager:
return return
idx = self.manager.index idx = self.manager.index
tab_containers = [c for c in self.tab_bar.content.controls if isinstance(c, ft.Container)] tab_containers = [
c for c in self.tab_bar.content.controls if isinstance(c, ft.Container)
]
control_to_remove = tab_containers[idx] control_to_remove = tab_containers[idx]
self.manager.tabs.pop(idx) self.manager.tabs.pop(idx)
self.tab_bar.content.controls.remove(control_to_remove) self.tab_bar.content.controls.remove(control_to_remove)
updated_tab_containers = [c for c in self.tab_bar.content.controls if isinstance(c, ft.Container)] updated_tab_containers = [
c for c in self.tab_bar.content.controls if isinstance(c, ft.Container)
]
for i, control in enumerate(updated_tab_containers): for i, control in enumerate(updated_tab_containers):
control.on_click = lambda e, i=i: self.select_tab(i) # type: ignore control.on_click = lambda e, i=i: self.select_tab(i) # type: ignore
@@ -278,7 +286,9 @@ class TabsManager:
""" """
self.manager.index = idx self.manager.index = idx
tab_containers = [c for c in self.tab_bar.content.controls if isinstance(c, ft.Container)] tab_containers = [
c for c in self.tab_bar.content.controls if isinstance(c, ft.Container)
]
for i, control in enumerate(tab_containers): for i, control in enumerate(tab_containers):
if i == idx: if i == idx:
control.bgcolor = ft.Colors.BLUE_900 control.bgcolor = ft.Colors.BLUE_900
@@ -330,7 +340,7 @@ class TabsManager:
def fetch_and_update(): def fetch_and_update():
parts = url.split(":", 1) parts = url.split(":", 1)
if len(parts) != 2: if len(parts) != 2:
result = f"Error: Invalid URL format. Expected format: hash:/page/path" result = "Error: Invalid URL format. Expected format: hash:/page/path"
page_path = "" page_path = ""
else: else:
dest_hash = parts[0] dest_hash = parts[0]

View File

@@ -77,8 +77,15 @@ def open_settings_tab(page: ft.Page, tab_manager):
snack = ft.SnackBar( snack = ft.SnackBar(
content=ft.Row( content=ft.Row(
controls=[ controls=[
ft.Icon(ft.Icons.CHECK_CIRCLE, color=ft.Colors.GREEN_400, size=20), ft.Icon(
ft.Text("Configuration saved! Restart app to apply changes.", color=ft.Colors.WHITE), ft.Icons.CHECK_CIRCLE,
color=ft.Colors.GREEN_400,
size=20,
),
ft.Text(
"Configuration saved! Restart app to apply changes.",
color=ft.Colors.WHITE,
),
], ],
tight=True, tight=True,
), ),
@@ -93,7 +100,9 @@ def open_settings_tab(page: ft.Page, tab_manager):
content=ft.Row( content=ft.Row(
controls=[ controls=[
ft.Icon(ft.Icons.ERROR, color=ft.Colors.RED_400, size=20), ft.Icon(ft.Icons.ERROR, color=ft.Colors.RED_400, size=20),
ft.Text("Failed to save configuration", color=ft.Colors.WHITE), ft.Text(
"Failed to save configuration", color=ft.Colors.WHITE
),
], ],
tight=True, tight=True,
), ),
@@ -127,7 +136,9 @@ def open_settings_tab(page: ft.Page, tab_manager):
content=ft.Row( content=ft.Row(
controls=[ controls=[
ft.Icon(ft.Icons.ERROR, color=ft.Colors.RED_400, size=20), ft.Icon(ft.Icons.ERROR, color=ft.Colors.RED_400, size=20),
ft.Text("Failed to save configuration", color=ft.Colors.WHITE), ft.Text(
"Failed to save configuration", color=ft.Colors.WHITE
),
], ],
tight=True, tight=True,
), ),
@@ -142,7 +153,12 @@ def open_settings_tab(page: ft.Page, tab_manager):
loading_snack = ft.SnackBar( loading_snack = ft.SnackBar(
content=ft.Row( content=ft.Row(
controls=[ controls=[
ft.ProgressRing(width=16, height=16, stroke_width=2, color=ft.Colors.BLUE_400), ft.ProgressRing(
width=16,
height=16,
stroke_width=2,
color=ft.Colors.BLUE_400,
),
ft.Text("Reloading Reticulum...", color=ft.Colors.WHITE), ft.Text("Reloading Reticulum...", color=ft.Colors.WHITE),
], ],
tight=True, tight=True,
@@ -162,8 +178,15 @@ def open_settings_tab(page: ft.Page, tab_manager):
snack = ft.SnackBar( snack = ft.SnackBar(
content=ft.Row( content=ft.Row(
controls=[ controls=[
ft.Icon(ft.Icons.CHECK_CIRCLE, color=ft.Colors.GREEN_400, size=20), ft.Icon(
ft.Text("Reticulum reloaded successfully!", color=ft.Colors.WHITE), ft.Icons.CHECK_CIRCLE,
color=ft.Colors.GREEN_400,
size=20,
),
ft.Text(
"Reticulum reloaded successfully!",
color=ft.Colors.WHITE,
),
], ],
tight=True, tight=True,
), ),
@@ -174,8 +197,12 @@ def open_settings_tab(page: ft.Page, tab_manager):
snack = ft.SnackBar( snack = ft.SnackBar(
content=ft.Row( content=ft.Row(
controls=[ controls=[
ft.Icon(ft.Icons.ERROR, color=ft.Colors.RED_400, size=20), ft.Icon(
ft.Text(f"Reload failed: {error}", color=ft.Colors.WHITE), ft.Icons.ERROR, color=ft.Colors.RED_400, size=20
),
ft.Text(
f"Reload failed: {error}", color=ft.Colors.WHITE
),
], ],
tight=True, tight=True,
), ),
@@ -187,6 +214,7 @@ def open_settings_tab(page: ft.Page, tab_manager):
page.update() page.update()
import ren_browser.app as app_module import ren_browser.app as app_module
app_module.reload_reticulum(page, on_reload_complete) app_module.reload_reticulum(page, on_reload_complete)
except Exception as ex: except Exception as ex:
@@ -217,8 +245,15 @@ def open_settings_tab(page: ft.Page, tab_manager):
snack = ft.SnackBar( snack = ft.SnackBar(
content=ft.Row( content=ft.Row(
controls=[ controls=[
ft.Icon(ft.Icons.CHECK_CIRCLE, color=ft.Colors.GREEN_400, size=20), ft.Icon(
ft.Text("Appearance settings saved and applied!", color=ft.Colors.WHITE), ft.Icons.CHECK_CIRCLE,
color=ft.Colors.GREEN_400,
size=20,
),
ft.Text(
"Appearance settings saved and applied!",
color=ft.Colors.WHITE,
),
], ],
tight=True, tight=True,
), ),
@@ -233,7 +268,10 @@ def open_settings_tab(page: ft.Page, tab_manager):
content=ft.Row( content=ft.Row(
controls=[ controls=[
ft.Icon(ft.Icons.ERROR, color=ft.Colors.RED_400, size=20), ft.Icon(ft.Icons.ERROR, color=ft.Colors.RED_400, size=20),
ft.Text("Failed to save appearance settings", color=ft.Colors.WHITE), ft.Text(
"Failed to save appearance settings",
color=ft.Colors.WHITE,
),
], ],
tight=True, tight=True,
), ),
@@ -410,7 +448,14 @@ def open_settings_tab(page: ft.Page, tab_manager):
nav_card = ft.Container( nav_card = ft.Container(
content=ft.Row( content=ft.Row(
controls=[btn_config, btn_appearance, btn_errors, btn_ret, btn_storage, btn_refresh], controls=[
btn_config,
btn_appearance,
btn_errors,
btn_ret,
btn_storage,
btn_refresh,
],
spacing=8, spacing=8,
wrap=True, wrap=True,
), ),

View File

@@ -84,7 +84,9 @@ def build_ui(page: Page):
tab_manager._on_tab_go(None, idx) tab_manager._on_tab_go(None, idx)
if req.page_path.endswith(".mu"): if req.page_path.endswith(".mu"):
new_control = render_micron(result, on_link_click=handle_link_click) new_control = render_micron(
result, on_link_click=handle_link_click
)
else: else:
new_control = render_plaintext(result) new_control = render_plaintext(result)
tab["content_control"] = new_control tab["content_control"] = new_control

View File

@@ -62,7 +62,9 @@ def sample_page_request():
from ren_browser.pages.page_request import PageRequest from ren_browser.pages.page_request import PageRequest
return PageRequest( return PageRequest(
destination_hash="1234567890abcdef", page_path="/page/index.mu", field_data=None, destination_hash="1234567890abcdef",
page_path="/page/index.mu",
field_data=None,
) )

View File

@@ -19,7 +19,9 @@ class TestAnnounce:
def test_announce_with_none_display_name(self): def test_announce_with_none_display_name(self):
"""Test Announce creation with None display name.""" """Test Announce creation with None display name."""
announce = Announce( announce = Announce(
destination_hash="1234567890abcdef", display_name=None, timestamp=1234567890, destination_hash="1234567890abcdef",
display_name=None,
timestamp=1234567890,
) )
assert announce.destination_hash == "1234567890abcdef" assert announce.destination_hash == "1234567890abcdef"

View File

@@ -59,7 +59,9 @@ class TestLogsModule:
assert len(logs.RET_LOGS) == 1 assert len(logs.RET_LOGS) == 1
assert logs.RET_LOGS[0] == "[2023-01-01T12:00:00] Test RNS message" assert logs.RET_LOGS[0] == "[2023-01-01T12:00:00] Test RNS message"
logs._original_rns_log.assert_called_once_with( logs._original_rns_log.assert_called_once_with(
"Test RNS message", "arg1", kwarg1="value1", "Test RNS message",
"arg1",
kwarg1="value1",
) )
assert result == "original_result" assert result == "original_result"

View File

@@ -7,7 +7,8 @@ class TestPageRequest:
def test_page_request_creation(self): def test_page_request_creation(self):
"""Test basic PageRequest creation.""" """Test basic PageRequest creation."""
request = PageRequest( request = PageRequest(
destination_hash="1234567890abcdef", page_path="/page/index.mu", destination_hash="1234567890abcdef",
page_path="/page/index.mu",
) )
assert request.destination_hash == "1234567890abcdef" assert request.destination_hash == "1234567890abcdef"

View File

@@ -51,9 +51,12 @@ class TestStorageManager:
with ( with (
patch("os.name", "posix"), patch("os.name", "posix"),
patch.dict( patch.dict(
"os.environ", {"XDG_CONFIG_HOME": "/home/user/.config"}, clear=True, "os.environ",
{"XDG_CONFIG_HOME": "/home/user/.config"},
clear=True,
), ),
patch("pathlib.Path.mkdir"),patch( patch("pathlib.Path.mkdir"),
patch(
"ren_browser.storage.storage.StorageManager._ensure_storage_directory", "ren_browser.storage.storage.StorageManager._ensure_storage_directory",
), ),
): ):
@@ -71,7 +74,11 @@ class TestStorageManager:
"""Test storage directory detection for Android with ANDROID_DATA.""" """Test storage directory detection for Android with ANDROID_DATA."""
with ( with (
patch("os.name", "posix"), patch("os.name", "posix"),
patch.dict("os.environ", {"ANDROID_ROOT": "/system", "ANDROID_DATA": "/data"}, clear=True), patch.dict(
"os.environ",
{"ANDROID_ROOT": "/system", "ANDROID_DATA": "/data"},
clear=True,
),
patch("pathlib.Path.mkdir"), patch("pathlib.Path.mkdir"),
): ):
with patch( with patch(
@@ -86,7 +93,11 @@ class TestStorageManager:
"""Test storage directory detection for Android with EXTERNAL_STORAGE.""" """Test storage directory detection for Android with EXTERNAL_STORAGE."""
with ( with (
patch("os.name", "posix"), patch("os.name", "posix"),
patch.dict("os.environ", {"ANDROID_ROOT": "/system", "EXTERNAL_STORAGE": "/storage/emulated/0"}, clear=True), patch.dict(
"os.environ",
{"ANDROID_ROOT": "/system", "EXTERNAL_STORAGE": "/storage/emulated/0"},
clear=True,
),
patch("pathlib.Path.mkdir"), patch("pathlib.Path.mkdir"),
): ):
with patch( with patch(
@@ -102,7 +113,8 @@ class TestStorageManager:
with ( with (
patch("os.name", "posix"), patch("os.name", "posix"),
patch.dict("os.environ", {"ANDROID_ROOT": "/system"}, clear=True), patch.dict("os.environ", {"ANDROID_ROOT": "/system"}, clear=True),
patch("pathlib.Path.mkdir"),patch( patch("pathlib.Path.mkdir"),
patch(
"ren_browser.storage.storage.StorageManager._ensure_storage_directory", "ren_browser.storage.storage.StorageManager._ensure_storage_directory",
), ),
): ):
@@ -169,7 +181,8 @@ class TestStorageManager:
assert result is True assert result is True
mock_page.client_storage.set.assert_called_with( mock_page.client_storage.set.assert_called_with(
"ren_browser_config", config_content, "ren_browser_config",
config_content,
) )
def test_save_config_fallback(self): def test_save_config_fallback(self):
@@ -182,13 +195,16 @@ class TestStorageManager:
storage._storage_dir = Path(temp_dir) storage._storage_dir = Path(temp_dir)
# Mock the reticulum config path to use temp dir and cause failure # Mock the reticulum config path to use temp dir and cause failure
with patch.object( with (
patch.object(
storage, storage,
"get_reticulum_config_path", "get_reticulum_config_path",
return_value=Path(temp_dir) / "reticulum", return_value=Path(temp_dir) / "reticulum",
), patch( ),
patch(
"pathlib.Path.write_text", "pathlib.Path.write_text",
side_effect=PermissionError("Access denied"), side_effect=PermissionError("Access denied"),
),
): ):
config_content = "test config content" config_content = "test config content"
result = storage.save_config(config_content) result = storage.save_config(config_content)
@@ -196,7 +212,8 @@ class TestStorageManager:
assert result is True assert result is True
# Check that the config was set to client storage # Check that the config was set to client storage
mock_page.client_storage.set.assert_any_call( mock_page.client_storage.set.assert_any_call(
"ren_browser_config", config_content, "ren_browser_config",
config_content,
) )
# Verify that client storage was called at least once # Verify that client storage was called at least once
assert mock_page.client_storage.set.call_count >= 1 assert mock_page.client_storage.set.call_count >= 1
@@ -354,10 +371,13 @@ class TestStorageManager:
with patch.object(StorageManager, "_get_storage_directory") as mock_get_dir: with patch.object(StorageManager, "_get_storage_directory") as mock_get_dir:
mock_get_dir.return_value = Path("/nonexistent/path") mock_get_dir.return_value = Path("/nonexistent/path")
with patch( with (
patch(
"pathlib.Path.mkdir", "pathlib.Path.mkdir",
side_effect=[PermissionError("Access denied"), None], side_effect=[PermissionError("Access denied"), None],
), patch("tempfile.gettempdir", return_value="/tmp"): ),
patch("tempfile.gettempdir", return_value="/tmp"),
):
storage = StorageManager() storage = StorageManager()
expected_fallback = Path("/tmp") / "ren_browser" expected_fallback = Path("/tmp") / "ren_browser"
@@ -444,7 +464,8 @@ class TestStorageManagerEdgeCases:
storage = StorageManager() storage = StorageManager()
with patch( with patch(
"pathlib.Path.write_text", side_effect=PermissionError("Access denied"), "pathlib.Path.write_text",
side_effect=PermissionError("Access denied"),
): ):
test_path = Path("/mock/path") test_path = Path("/mock/path")
result = storage._is_writable(test_path) result = storage._is_writable(test_path)

View File

@@ -105,7 +105,9 @@ class TestTabsManager:
"""Test that selecting a tab updates background colors correctly.""" """Test that selecting a tab updates background colors correctly."""
tabs_manager._add_tab_internal("Tab 2", Mock()) tabs_manager._add_tab_internal("Tab 2", Mock())
tab_controls = tabs_manager.tab_bar.content.controls[:-2] # Exclude add/close buttons tab_controls = tabs_manager.tab_bar.content.controls[
:-2
] # Exclude add/close buttons
tabs_manager.select_tab(1) tabs_manager.select_tab(1)
@@ -195,7 +197,9 @@ class TestTabsManager:
"""Test that tab click handlers are properly set.""" """Test that tab click handlers are properly set."""
tabs_manager._add_tab_internal("Tab 2", Mock()) tabs_manager._add_tab_internal("Tab 2", Mock())
tab_controls = tabs_manager.tab_bar.content.controls[:-2] # Exclude add/close buttons tab_controls = tabs_manager.tab_bar.content.controls[
:-2
] # Exclude add/close buttons
for i, control in enumerate(tab_controls): for i, control in enumerate(tab_controls):
assert control.on_click is not None assert control.on_click is not None
@@ -249,13 +253,21 @@ class TestTabsManager:
# Simulate a smaller screen, expecting more tabs to overflow # Simulate a smaller screen, expecting more tabs to overflow
tabs_manager.page.width = 400 tabs_manager.page.width = 400
tabs_manager._update_tab_visibility() tabs_manager._update_tab_visibility()
visible_tabs_small = sum(1 for c in tabs_manager.tab_bar.content.controls if isinstance(c, ft.Container) and c.visible) visible_tabs_small = sum(
1
for c in tabs_manager.tab_bar.content.controls
if isinstance(c, ft.Container) and c.visible
)
assert visible_tabs_small < 11 assert visible_tabs_small < 11
# Simulate a larger screen, expecting all tabs to be visible # Simulate a larger screen, expecting all tabs to be visible
tabs_manager.page.width = 1600 tabs_manager.page.width = 1600
tabs_manager._update_tab_visibility() tabs_manager._update_tab_visibility()
visible_tabs_large = sum(1 for c in tabs_manager.tab_bar.content.controls if isinstance(c, ft.Container) and c.visible) visible_tabs_large = sum(
1
for c in tabs_manager.tab_bar.content.controls
if isinstance(c, ft.Container) and c.visible
)
assert visible_tabs_large == 11 assert visible_tabs_large == 11
assert tabs_manager.overflow_menu is None assert tabs_manager.overflow_menu is None

View File

@@ -29,7 +29,12 @@ class TestBuildUI:
@patch("ren_browser.tabs.tabs.TabsManager") @patch("ren_browser.tabs.tabs.TabsManager")
@patch("ren_browser.controls.shortcuts.Shortcuts") @patch("ren_browser.controls.shortcuts.Shortcuts")
def test_build_ui_appbar_setup( def test_build_ui_appbar_setup(
self, mock_shortcuts, mock_tabs, mock_fetcher, mock_announce_service, mock_page, self,
mock_shortcuts,
mock_tabs,
mock_fetcher,
mock_announce_service,
mock_page,
): ):
"""Test that build_ui sets up the app bar correctly.""" """Test that build_ui sets up the app bar correctly."""
mock_tab_manager = Mock() mock_tab_manager = Mock()
@@ -51,7 +56,12 @@ class TestBuildUI:
@patch("ren_browser.tabs.tabs.TabsManager") @patch("ren_browser.tabs.tabs.TabsManager")
@patch("ren_browser.controls.shortcuts.Shortcuts") @patch("ren_browser.controls.shortcuts.Shortcuts")
def test_build_ui_drawer_setup( def test_build_ui_drawer_setup(
self, mock_shortcuts, mock_tabs, mock_fetcher, mock_announce_service, mock_page, self,
mock_shortcuts,
mock_tabs,
mock_fetcher,
mock_announce_service,
mock_page,
): ):
"""Test that build_ui sets up the drawer correctly.""" """Test that build_ui sets up the drawer correctly."""
mock_tab_manager = Mock() mock_tab_manager = Mock()