"""Tests for BrowserState navigation stack and pagination.""" from r36s_dlna_browser.dlna.browser_state import BrowserState from r36s_dlna_browser.dlna.models import MediaServer, MediaItem, ItemType def _server(name: str = "TestServer") -> MediaServer: return MediaServer(friendly_name=name, location=f"http://{name}:8080/desc.xml") def _items(n: int, container: bool = False) -> list[MediaItem]: t = ItemType.CONTAINER if container else ItemType.AUDIO return [ MediaItem( object_id=str(i), title=f"Item {i}", item_type=t, resource_url="" if container else f"http://srv/file{i}.mp3", ) for i in range(n) ] class TestServerList: def test_empty_initial(self): s = BrowserState() assert s.servers == [] assert s.selected_server is None def test_set_servers(self): s = BrowserState() servers = [_server("A"), _server("B")] s.set_servers(servers) assert len(s.servers) == 2 assert s.server_cursor == 0 assert s.selected_server.friendly_name == "A" def test_cursor_bounds(self): s = BrowserState() s.set_servers([_server("A"), _server("B"), _server("C")]) s.server_cursor = 2 assert s.selected_server.friendly_name == "C" s.server_cursor = 5 # out of bounds assert s.selected_server is None class TestBrowseStack: def test_not_in_browse_initially(self): s = BrowserState() assert not s.in_browse_mode def test_enter_server(self): s = BrowserState() s.set_servers([_server()]) obj_id = s.enter_server(s.selected_server) assert obj_id == "0" assert s.in_browse_mode assert s.current_level.object_id == "0" def test_set_items_and_cursor(self): s = BrowserState() s.set_servers([_server()]) s.enter_server(s.selected_server) items = _items(10) s.set_items(items, "0") assert len(s.current_items) == 10 assert s.cursor == 0 s.cursor = 3 assert s.cursor == 3 assert s.selected_item().title == "Item 3" def test_cursor_clamps(self): s = BrowserState() s.set_servers([_server()]) s.enter_server(s.selected_server) s.set_items(_items(5), "0") s.cursor = 100 assert s.cursor == 4 # clamped to last s.cursor = -5 assert s.cursor == 0 def test_push_and_pop(self): s = BrowserState() s.set_servers([_server()]) s.enter_server(s.selected_server) s.set_items(_items(3, container=True), "0") # Drill into child s.set_items(_items(5), "1") assert len(s.current_items) == 5 # Go back assert s.go_back() assert len(s.current_items) == 3 assert s.current_level.object_id == "0" # Go back again exits browse assert s.go_back() assert not s.in_browse_mode def test_go_back_at_root(self): s = BrowserState() assert not s.go_back() def test_reset(self): s = BrowserState() s.set_servers([_server()]) s.enter_server(s.selected_server) s.set_items(_items(5), "0") s.error = "fail" s.playback_title = "song" s.playback_paused = True s.reset() assert not s.in_browse_mode assert s.error == "" assert s.playback_title == "" assert not s.playback_paused class TestScrollOffset: def test_scroll_offset_default(self): s = BrowserState() s.set_servers([_server()]) s.enter_server(s.selected_server) s.set_items(_items(3), "0") assert s.scroll_offset == 0 def test_scroll_offset_set(self): s = BrowserState() s.set_servers([_server()]) s.enter_server(s.selected_server) s.set_items(_items(30), "0") s.scroll_offset = 10 assert s.scroll_offset == 10