"""Tests for MumbleClient dispatcher and callback wiring.""" from unittest.mock import MagicMock, patch from tuimble.client import ConnectionFailed, MumbleClient def test_default_state(): client = MumbleClient(host="localhost") assert client.connected is False assert client.users == {} assert client.channels == {} assert client.my_channel_id is None def test_dispatcher_routes_callback(): client = MumbleClient(host="localhost") calls = [] client.set_dispatcher(lambda fn, *a: calls.append((fn, a))) sentinel = object() client.on_connected = sentinel client._dispatch(client.on_connected) assert len(calls) == 1 assert calls[0] == (sentinel, ()) def test_dispatch_without_dispatcher_calls_directly(): client = MumbleClient(host="localhost") results = [] def callback(): results.append("called") client.on_connected = callback client._dispatch(client.on_connected) assert results == ["called"] def test_dispatch_skips_none_callback(): client = MumbleClient(host="localhost") # Should not raise client._dispatch(None) def test_set_self_deaf_calls_pymumble(): client = MumbleClient(host="localhost") client._connected = True myself = MagicMock() users = MagicMock() users.myself = myself mumble = MagicMock() mumble.users = users client._mumble = mumble client.set_self_deaf(True) myself.deafen.assert_called_once() myself.undeafen.assert_not_called() myself.reset_mock() client.set_self_deaf(False) myself.undeafen.assert_called_once() myself.deafen.assert_not_called() def test_set_self_deaf_noop_when_disconnected(): client = MumbleClient(host="localhost") # Should not raise when not connected client.set_self_deaf(True) def test_cert_defaults(): client = MumbleClient(host="localhost") assert client._certfile == "" assert client._keyfile == "" def test_cert_custom(): client = MumbleClient( host="localhost", certfile="/path/cert.pem", keyfile="/path/key.pem", ) assert client._certfile == "/path/cert.pem" assert client._keyfile == "/path/key.pem" def test_connection_failed_retryable(): exc = ConnectionFailed("network error", retryable=True) assert str(exc) == "network error" assert exc.retryable is True def test_connection_failed_not_retryable(): exc = ConnectionFailed("auth rejected", retryable=False) assert str(exc) == "auth rejected" assert exc.retryable is False def test_connection_failed_default_retryable(): exc = ConnectionFailed("something broke") assert exc.retryable is True def test_reconnect_resets_state(): client = MumbleClient(host="localhost") client._connected = True client._mumble = MagicMock() with patch.object(client, "connect"): client.reconnect() # disconnect should have cleared _mumble before connect assert client._connected is False def test_disconnect_clears_connected(): client = MumbleClient(host="localhost") client._connected = True client._mumble = MagicMock() client.disconnect() assert client.connected is False