package devices import ( "testing" "xiaomihome/xiaomi" ) func TestToInt(t *testing.T) { tests := []struct { name string value interface{} want int }{ {"float64", float64(42), 42}, {"int", int(42), 42}, {"int64", int64(42), 42}, {"uint8", uint8(100), 100}, {"uint16", uint16(1000), 1000}, {"nil", nil, 0}, {"string", "hello", 0}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := toInt(tt.value) if got != tt.want { t.Errorf("toInt(%v) = %d, want %d", tt.value, got, tt.want) } }) } } func TestToFloat(t *testing.T) { tests := []struct { name string value interface{} want float64 }{ {"float64", float64(26.5), 26.5}, {"float32", float32(30.0), 30.0}, {"int", int(25), 25.0}, {"int64", int64(20), 20.0}, {"string", "26.5", 0.0}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := toFloat(tt.value) if got != tt.want { t.Errorf("toFloat(%v) = %f, want %f", tt.value, got, tt.want) } }) } } func TestAirConditionerModeConstants(t *testing.T) { // Verify all mode values have reverse mappings for _, m := range []ACMode{ModeCool, ModeHeat, ModeFan, ModeDry, ModeAuto} { if _, ok := modeReverseMap[m]; !ok { t.Errorf("missing reverse mapping for %s", m) } } // Verify all value entries map back correctly for v, m := range modeValueMap { if r, ok := modeReverseMap[m]; !ok || r != v { t.Errorf("modeReverseMap[modeValueMap[%d]] = %v, want %d", v, r, v) } } } func TestFanSpeedConstants(t *testing.T) { for _, s := range []FanSpeed{SpeedLow, SpeedMedium, SpeedHigh, SpeedAuto} { if _, ok := fanSpeedReverseMap[s]; !ok { t.Errorf("missing reverse mapping for %s", s) } } } func TestSwingModeConstants(t *testing.T) { for _, s := range []SwingMode{SwingOff, SwingVertical, SwingHorizontal, SwingBoth} { if _, ok := swingReverseMap[s]; !ok { t.Errorf("missing reverse mapping for %s", s) } } } func TestMatchURN(t *testing.T) { tests := []struct { name string urn string types []string want bool }{ { "air-conditioner", "urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c1:1", []string{"air-conditioner"}, true, }, { "light", "urn:miot-spec-v2:device:light:0000A001:philips-bulb:1", []string{"light"}, true, }, { "switch outlet", "urn:miot-spec-v2:device:outlet:0000A002:xiaomi-plug:1", []string{"switch", "outlet"}, true, }, { "fan", "urn:miot-spec-v2:device:fan:0000A003:xiaomi-fan:1", []string{"fan"}, true, }, { "curtain", "urn:miot-spec-v2:device:curtain:0000A005:aqara-c1:1", []string{"curtain"}, true, }, { "humidifier", "urn:miot-spec-v2:device:humidifier:0000A006:xiaomi-h1:1", []string{"humidifier"}, true, }, { "vacuum", "urn:miot-spec-v2:device:vacuum:0000A007:roborock-s5:1", []string{"vacuum"}, true, }, { "water-heater", "urn:miot-spec-v2:device:water-heater:0000A008:xiaomi-wh1:1", []string{"water-heater"}, true, }, { "heater thermostat", "urn:miot-spec-v2:device:heater:0000A009:xiaomi-h1:1", []string{"heater"}, true, }, { "no match", "urn:miot-spec-v2:device:unknown:0000A099:test:1", []string{"air-conditioner", "light", "switch"}, false, }, { "empty URN", "", []string{"light"}, false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := matchURN(tt.urn, tt.types...) if got != tt.want { t.Errorf("matchURN(%q, %v) = %v, want %v", tt.urn, tt.types, got, tt.want) } }) } } func TestFactoryNilClientPanic(t *testing.T) { // Create with a nil client should panic (calling methods on nil client) // This is a documentation test noting expected behavior t.Skip("requires real or mock client") } func TestCreateNilInfo(t *testing.T) { client := &xiaomi.Client{} result, err := Create(client, nil) if result != nil { t.Errorf("expected nil result, got %v", result) } if err == nil { t.Error("expected error for nil info") } }