Skip to main content
Glama
pedrof
by pedrof
test_hue_client.py10.5 kB
""" Unit tests for HueClient helper functions and utilities. These tests focus on the pure functions and logic that don't require a connection to the actual Hue Bridge. """ import pytest from hue_mcp_server.hue_client import ( HueClient, _convert_brightness_to_percentage, _is_device_resource, BRIGHTNESS_MIN_HUE_API, BRIGHTNESS_MAX_HUE_API, BRIGHTNESS_MIN_PERCENT, BRIGHTNESS_MAX_PERCENT, COLOR_TEMP_MIN_MIREDS, COLOR_TEMP_MAX_MIREDS, CIE_XY_MIN, CIE_XY_MAX, DEVICE_RESOURCE_TYPE, ) class TestConstants: """Tests for module-level constants.""" def test_brightness_constants_defined(self): """Test that brightness constants are defined correctly.""" assert BRIGHTNESS_MIN_HUE_API == 0 assert BRIGHTNESS_MAX_HUE_API == 254 assert BRIGHTNESS_MIN_PERCENT == 0.0 assert BRIGHTNESS_MAX_PERCENT == 100.0 def test_color_temp_constants_defined(self): """Test that color temperature constants are defined correctly.""" assert COLOR_TEMP_MIN_MIREDS == 153 assert COLOR_TEMP_MAX_MIREDS == 500 def test_cie_xy_constants_defined(self): """Test that CIE xy color space constants are defined correctly.""" assert CIE_XY_MIN == 0.0 assert CIE_XY_MAX == 1.0 def test_device_resource_type_constant(self): """Test that device resource type constant is defined.""" assert DEVICE_RESOURCE_TYPE == "device" class TestBrightnessConversion: """Tests for brightness conversion helper function.""" def test_convert_min_brightness(self): """Test conversion of minimum brightness (0 -> 0%).""" result = _convert_brightness_to_percentage(BRIGHTNESS_MIN_HUE_API) assert result == BRIGHTNESS_MIN_PERCENT assert result == 0.0 def test_convert_max_brightness(self): """Test conversion of maximum brightness (254 -> 100%).""" result = _convert_brightness_to_percentage(BRIGHTNESS_MAX_HUE_API) assert result == BRIGHTNESS_MAX_PERCENT assert result == 100.0 def test_convert_mid_brightness(self): """Test conversion of mid-range brightness (~127 -> ~50%).""" result = _convert_brightness_to_percentage(127) # 127/254 * 100 = ~50% assert 49.0 <= result <= 51.0 def test_convert_quarter_brightness(self): """Test conversion of quarter brightness (~64 -> ~25%).""" result = _convert_brightness_to_percentage(64) # 64/254 * 100 = ~25.2% assert 24.0 <= result <= 26.0 def test_convert_three_quarter_brightness(self): """Test conversion of three-quarter brightness (~190 -> ~75%).""" result = _convert_brightness_to_percentage(190) # 190/254 * 100 = ~74.8% assert 73.0 <= result <= 76.0 def test_conversion_is_linear(self): """Test that conversion is linear across the range.""" # Test several points to ensure linearity test_points = [0, 50, 100, 150, 200, 254] results = [_convert_brightness_to_percentage(b) for b in test_points] # Verify results are in ascending order assert results == sorted(results) # Verify correct calculation for each point for brightness, result in zip(test_points, results): expected = (brightness / BRIGHTNESS_MAX_HUE_API) * BRIGHTNESS_MAX_PERCENT assert abs(result - expected) < 0.01 # Allow tiny floating point error def test_conversion_returns_float(self): """Test that conversion always returns a float.""" result = _convert_brightness_to_percentage(100) assert isinstance(result, float) @pytest.mark.parametrize( "hue_value,expected_percent", [ (0, 0.0), (25, 9.84), # Approximately (51, 20.08), (127, 50.0), (203, 79.92), (254, 100.0), ], ) def test_conversion_specific_values(self, hue_value, expected_percent): """Test conversion for specific known values.""" result = _convert_brightness_to_percentage(hue_value) assert abs(result - expected_percent) < 0.5 # Within 0.5% class TestDeviceResourceCheck: """Tests for device resource type checker function.""" def test_is_device_resource_returns_true_for_device(self): """Test that 'device' type returns True.""" assert _is_device_resource("device") is True def test_is_device_resource_returns_false_for_light(self): """Test that 'light' type returns False.""" assert _is_device_resource("light") is False def test_is_device_resource_returns_false_for_group(self): """Test that 'group' type returns False.""" assert _is_device_resource("group") is False def test_is_device_resource_returns_false_for_scene(self): """Test that 'scene' type returns False.""" assert _is_device_resource("scene") is False def test_is_device_resource_returns_false_for_room(self): """Test that 'room' type returns False.""" assert _is_device_resource("room") is False def test_is_device_resource_returns_false_for_zone(self): """Test that 'zone' type returns False.""" assert _is_device_resource("zone") is False def test_is_device_resource_case_sensitive(self): """Test that resource type check is case-sensitive.""" assert _is_device_resource("Device") is False assert _is_device_resource("DEVICE") is False assert _is_device_resource("device") is True def test_is_device_resource_with_empty_string(self): """Test that empty string returns False.""" assert _is_device_resource("") is False @pytest.mark.parametrize( "resource_type,expected", [ ("device", True), ("light", False), ("group", False), ("scene", False), ("room", False), ("zone", False), ("bridge", False), ("entertainment", False), ("behavior_instance", False), ], ) def test_is_device_resource_various_types(self, resource_type, expected): """Test device resource check for various Hue API resource types.""" assert _is_device_resource(resource_type) == expected class TestHueClientInitialization: """Tests for HueClient initialization (no bridge connection needed).""" def test_client_initialization_with_valid_parameters(self): """Test that client initializes correctly with valid parameters.""" client = HueClient("192.168.1.100", "test-api-key-123") assert client.bridge_ip == "192.168.1.100" assert client.api_key == "test-api-key-123" assert client.bridge is None assert client.is_connected() is False def test_client_stores_bridge_ip_correctly(self): """Test that bridge IP is stored as provided.""" test_ips = ["192.168.1.1", "10.0.0.50", "172.16.0.100"] for ip in test_ips: client = HueClient(ip, "key") assert client.bridge_ip == ip def test_client_stores_api_key_correctly(self): """Test that API key is stored as provided.""" test_keys = [ "short-key", "a" * 40, # 40 character key (typical Hue key length) "complex-key-with-numbers-123", ] for key in test_keys: client = HueClient("192.168.1.1", key) assert client.api_key == key def test_client_not_connected_initially(self): """Test that client is not connected after initialization.""" client = HueClient("192.168.1.100", "test-api-key") assert client.is_connected() is False def test_client_bridge_is_none_initially(self): """Test that bridge reference is None after initialization.""" client = HueClient("192.168.1.100", "test-api-key") assert client.bridge is None def test_multiple_clients_are_independent(self): """Test that multiple client instances are independent.""" client1 = HueClient("192.168.1.1", "key1") client2 = HueClient("192.168.1.2", "key2") assert client1.bridge_ip != client2.bridge_ip assert client1.api_key != client2.api_key assert client1 is not client2 class TestHueClientConnectionState: """Tests for HueClient connection state management (no actual connection).""" def test_is_connected_returns_false_initially(self): """Test that is_connected returns False before connection.""" client = HueClient("192.168.1.100", "test-api-key") assert client.is_connected() is False def test_is_connected_returns_boolean(self): """Test that is_connected always returns a boolean.""" client = HueClient("192.168.1.100", "test-api-key") result = client.is_connected() assert isinstance(result, bool) class TestHueClientEdgeCases: """Tests for edge cases in HueClient.""" def test_client_with_localhost_ip(self): """Test client initialization with localhost IP.""" client = HueClient("127.0.0.1", "test-key") assert client.bridge_ip == "127.0.0.1" def test_client_with_ipv6_address(self): """Test client initialization with IPv6 address.""" client = HueClient("fe80::1", "test-key") assert client.bridge_ip == "fe80::1" def test_client_with_hostname(self): """Test client initialization with hostname instead of IP.""" client = HueClient("philips-hue.local", "test-key") assert client.bridge_ip == "philips-hue.local" def test_client_with_very_long_api_key(self): """Test client with unusually long API key.""" long_key = "a" * 1000 client = HueClient("192.168.1.100", long_key) assert client.api_key == long_key assert len(client.api_key) == 1000 def test_client_with_empty_api_key(self): """Test client initialization with empty API key.""" # Client should initialize even with empty key (will fail on connect) client = HueClient("192.168.1.100", "") assert client.api_key == "" def test_client_with_special_characters_in_key(self): """Test client with special characters in API key.""" special_key = "key-with-!@#$%^&*()_+-=[]{}|;:',.<>?" client = HueClient("192.168.1.100", special_key) assert client.api_key == special_key

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pedrof/hue-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server