Something went wrong. Try again.
A Material 3 inspired desktop shell for Niri and Hyprland created with Ignis.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245import asyncioimport importlibimport sysimport typesfrom pathlib import Path
import fakesimport pytest
MODULES = Path(__file__).resolve().parents[1] / "modules"
def load(): fakes.install() model = importlib.import_module("modules.network.model") package = sys.modules["modules.network"] for name in ("ErrorCode", "NetworkError", "NetworkSnapshot"): setattr(package, name, getattr(model, name)) package.NetworkController = object package.get_network_controller = lambda: CONTROLLER
for name, sub in (("modules.settings", "settings"), ("modules.settings.tabs", "settings/tabs")): stub = types.ModuleType(name) stub.__path__ = [str(MODULES / sub)] sys.modules[name] = stub widgets = types.ModuleType("modules.settings.widgets") widgets.CategoryLabel = lambda title: fakes.Fake(label=title) sys.modules["modules.settings.widgets"] = widgets sys.modules.pop("modules.settings.tabs.network", None) return importlib.import_module("modules.settings.tabs.network")
from modules.network.model import ( Capabilities, Connectivity, ErrorCode, LinkDetails, LinkState, NetworkError, NetworkSnapshot, Security, WifiNetwork, WifiState,)
CONTROLLER = None
class FakeController: def __init__(self, snapshot): self.snapshot = snapshot self.calls = [] self.handlers = {} self.fail = None
def connect(self, signal, callback): assert signal == "changed" self.handlers[len(self.handlers) + 1] = callback return len(self.handlers)
def disconnect(self, handler_id): self.handlers.pop(handler_id)
def push(self, snapshot): self.snapshot = snapshot for callback in list(self.handlers.values()): callback(self)
def __getattr__(self, name): async def action(*args): self.calls.append((name, *args)) if self.fail: raise self.fail return action
def net(ssid, strength=60, state=LinkState.IDLE, saved=False, security=Security.PSK): return WifiNetwork(ssid, ssid, security, strength, state=state, saved=saved, auto_connect=True if saved else None)
def snap(*networks, enabled=True, link=None): return NetworkSnapshot( "iwd", WifiState(True, enabled, False, LinkState.IDLE, tuple(networks), link), (), Connectivity.FULL, Capabilities(forget=True, auto_connect=True, link_details=True), )
def find(root, predicate): return [w for w in root.walk() if predicate(w)]
def titles(tab): return [w.label for w in tab.walk() if "net-row-title" in w._classes]
async def settle(): for _ in range(3): await asyncio.sleep(0)
def mount(tab): async def scenario(): tab.emit("map") await settle()
asyncio.run(scenario())
@pytest.fixturedef tab_and_controller(): global CONTROLLER CONTROLLER = FakeController(snap(net("zeta", 90), net("home", 40, saved=True), net("cafe", 80))) module = load() return module.NetworkTab(), CONTROLLER
def test_initial_render_and_listener_lifecycle(tab_and_controller): tab, controller = tab_and_controller assert titles(tab) == ["home", "zeta", "cafe"] assert controller.handlers == {}
async def scenario(): tab.emit("map") assert len(controller.handlers) == 1 tab.emit("map") assert len(controller.handlers) == 1 await settle() assert ("scan",) in controller.calls tab.emit("unmap") assert controller.handlers == {}
asyncio.run(scenario())
def test_rows_are_reused_and_moved(tab_and_controller): tab, controller = tab_and_controller mount(tab) row = next(w for w in tab.walk() if type(w).__name__ == "NetworkRow" and w.network.ssid == "cafe")
controller.push(snap(net("zeta", 90), net("home", 40, saved=True), net("cafe", 80, LinkState.CONNECTED), link=LinkDetails(frequency_mhz=5180, rx_mbps=300))) assert titles(tab) == ["cafe", "home", "zeta"] same = next(w for w in tab.walk() if type(w).__name__ == "NetworkRow" and w.network.ssid == "cafe") assert same is row assert "connected" in row._classes assert row._facts_box.get_visible()
controller.push(snap(net("zeta", 90))) assert titles(tab) == ["zeta"] assert row.get_parent() is None
def test_wifi_off_shows_empty_state(tab_and_controller): tab, controller = tab_and_controller mount(tab) controller.push(snap(enabled=False)) assert titles(tab) == [] texts = [w.label for w in tab.walk() if "net-empty-text" in w._classes] assert texts == ["Turn on Wi-Fi to see networks nearby."]
def test_click_saved_network_connects(tab_and_controller): tab, controller = tab_and_controller
async def scenario(): row = next(w for w in tab.walk() if type(w).__name__ == "NetworkRow" and w.network.ssid == "home") row._on_primary() await settle()
asyncio.run(scenario()) assert ("connect_to", "home", None) in controller.calls
def test_password_flow(tab_and_controller): tab, controller = tab_and_controller
async def scenario(): row = next(w for w in tab.walk() if type(w).__name__ == "NetworkRow" and w.network.ssid == "cafe") row._on_primary() assert row._revealer.reveal_child and row._password_box.get_visible()
row._entry.text = "short" row._submit() assert row._error.label.startswith("WPA passwords") assert not [c for c in controller.calls if c[0] == "connect_to"]
controller.fail = NetworkError(ErrorCode.WRONG_PASSWORD) row._entry.text = "correct horse" row._submit() await settle() assert ("connect_to", "cafe", "correct horse") in controller.calls assert row._error.label == "Wrong password. Check it and try again." assert row._entry.text == "" assert row._revealer.reveal_child
controller.fail = None row._entry.text = "correct horse" row._submit() await settle() assert not row._revealer.reveal_child assert row._error.label == ""
asyncio.run(scenario())
def test_cancelled_connect_is_silent(tab_and_controller): tab, controller = tab_and_controller
async def scenario(): controller.fail = NetworkError(ErrorCode.CANCELLED) row = next(w for w in tab.walk() if type(w).__name__ == "NetworkRow" and w.network.ssid == "home") row._on_primary() await settle() assert row._error.label in ("", None) or not row._error.get_visible()
asyncio.run(scenario())
def test_wifi_switch_and_error_banner(tab_and_controller): tab, controller = tab_and_controller
async def scenario(): status = next(w for w in tab.walk() if type(w).__name__ == "StatusCard") controller.fail = NetworkError(ErrorCode.FAILED) status._on_toggle(None, False) await settle() assert ("set_wifi_enabled", False) in controller.calls assert status._banner.get_visible() status.clear_error() assert not status._banner.get_visible()
asyncio.run(scenario())
def test_filter_hides_rows(tab_and_controller): tab, _controller = tab_and_controller wifi = next(w for w in tab.walk() if type(w).__name__ == "NetworkList") wifi._set_query("ze") assert titles(tab) == ["zeta"] wifi._set_query("") assert sorted(titles(tab)) == ["cafe", "home", "zeta"]