Files
voculinux/tests/test_unused_downloads_height.py
T
Jatin K MalikandGitHub 26f90b6998 chore(release): prepare v0.17.0
Minor on the stable line. Faster Whisper and Parakeet extras, Speech Model simple setup, Snap uinput, Flatpak bundles on the tag, and QA fixes from the release branch.

Fixes tracked in the PR. Post-release follow-ups: #834.
2026-09-16 00:18:09 -07:00

92 lines
3.4 KiB
Python

"""Tests for sizing the "Unused downloads" list to the rows it holds.
The settings dialog cannot be instantiated under the mocked-GTK harness (see
test_settings_mode_change.py), so the arithmetic lives in a module-level
helper that is unit-tested directly, and the wiring around it is asserted
against the source of the two methods.
"""
import inspect
import re
from vocalinux.ui import settings_dialog
from vocalinux.ui.settings_dialog import (
_UNUSED_DOWNLOADS_MAX_HEIGHT,
_clamp_unused_downloads_height,
)
def _method_source(name: str) -> str:
src = inspect.getsource(settings_dialog)
match = re.search(rf"\n def {name}\(.*?(?=\n def )", src, re.DOTALL)
assert match, f"could not locate method {name}"
return match.group(0)
def test_list_is_as_tall_as_its_rows_render():
"""Two rows that measure 116px must not be squeezed into an estimate.
56px per row was the old guess; real rows render taller than that once
margins and the Delete button are counted, which cut off the last row
while the header still counted it (#683).
"""
assert _clamp_unused_downloads_height(116) == 116
def test_long_lists_stop_growing_at_the_cap():
"""Beyond the cap the list scrolls instead of pushing the page down."""
assert _clamp_unused_downloads_height(_UNUSED_DOWNLOADS_MAX_HEIGHT * 3) == (
_UNUSED_DOWNLOADS_MAX_HEIGHT
)
def test_refresh_sizes_the_list_after_building_the_rows():
"""A measured height is worthless if the refresh never asks for one."""
body = _method_source("_refresh_unused_downloads")
assert "self._fit_unused_downloads_height()" in body
# The per-row estimate is what clipped the list; it must not come back.
assert "56 *" not in body
def test_fit_measures_the_listbox_and_feeds_the_scroll():
body = _method_source("_fit_unused_downloads_height")
assert "self.unused_models_group.listbox.get_preferred_height()" in body
assert "self.unused_models_scroll.set_min_content_height(" in body
assert "_clamp_unused_downloads_height(natural_height)" in body
def test_scrollbar_stays_in_the_layout():
"""An overlay scrollbar hides until hovered, so a capped list looks whole."""
src = inspect.getsource(settings_dialog)
assert "self.unused_models_scroll.set_overlay_scrolling(False)" in src
def test_mapping_the_list_remeasures_it():
"""Refresh may run before the dialog is mapped; map must remeasure so a
short first measurement can never leave rows clipped."""
src = inspect.getsource(settings_dialog)
assert re.search(
r"self\.unused_models_scroll\.connect\(\s*\"map\","
r"\s*lambda \*_args: self\._fit_unused_downloads_height\(\)",
src,
)
def test_expanding_the_list_remeasures_it():
"""Measure while collapsed is worthless; expanding must remeasure."""
src = inspect.getsource(settings_dialog)
assert re.search(
r"self\.unused_expander\.connect\(\s*\"notify::expanded\","
r"\s*lambda \*_args: self\._fit_unused_downloads_height\(\)",
src,
)
def test_unused_downloads_are_a_sibling_expander_not_nested_in_advanced():
"""Same card chrome as Advanced, not an expander inside Advanced."""
src = inspect.getsource(settings_dialog)
assert "self.content_box.pack_start(self.unused_island" in src
assert "self.advanced_box.pack_start(self.unused_models_group" not in src
assert "self.unused_expander" in src
assert "_make_expander_card" in src