package models import ( "encoding/xml" "testing" ) func TestNewKey(t *testing.T) { key := NewKey(KeyPlay) if key.State != KeyStatePress { t.Errorf("Expected state %q, got %q", KeyStatePress, key.State) } if key.Sender != "Gabbo" { t.Errorf("Expected sender %q, got %q", "Gabbo", key.Sender) } if key.Value != KeyPlay { t.Errorf("Expected value %q, got %q", KeyPlay, key.Value) } } func TestNewKeyPress(t *testing.T) { key := NewKeyPress(KeyPause) if key.State != KeyStatePress { t.Errorf("Expected state %q, got %q", KeyStatePress, key.State) } if key.Value != KeyPause { t.Errorf("Expected value %q, got %q", KeyPause, key.Value) } } func TestNewKeyRelease(t *testing.T) { key := NewKeyRelease(KeyStop) if key.State != KeyStateRelease { t.Errorf("Expected state %q, got %q", KeyStateRelease, key.State) } if key.Sender != "Gabbo" { t.Errorf("Expected sender %q, got %q", "Gabbo", key.Sender) } if key.Value != KeyStop { t.Errorf("Expected value %q, got %q", KeyStop, key.Value) } } func TestKeyXMLMarshal(t *testing.T) { tests := []struct { name string key *Key expectedXML string }{ { name: "PLAY key press", key: NewKey(KeyPlay), expectedXML: `PLAY`, }, { name: "PAUSE key press", key: NewKey(KeyPause), expectedXML: `PAUSE`, }, { name: "STOP key release", key: NewKeyRelease(KeyStop), expectedXML: `STOP`, }, { name: "VOLUME_UP key press", key: NewKey(KeyVolumeUp), expectedXML: `VOLUME_UP`, }, { name: "PRESET_1 key press", key: NewKey(KeyPreset1), expectedXML: `PRESET_1`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { xmlData, err := xml.Marshal(tt.key) if err != nil { t.Fatalf("Failed to marshal XML: %v", err) } if string(xmlData) != tt.expectedXML { t.Errorf("Expected XML %q, got %q", tt.expectedXML, string(xmlData)) } }) } } func TestKeyXMLUnmarshal(t *testing.T) { tests := []struct { name string xmlData string want Key }{ { name: "PLAY key press", xmlData: `PLAY`, want: Key{ State: KeyStatePress, Sender: "Gabbo", Value: KeyPlay, }, }, { name: "PAUSE key release", xmlData: `PAUSE`, want: Key{ State: KeyStateRelease, Sender: "TestSender", Value: KeyPause, }, }, { name: "VOLUME_DOWN key press", xmlData: `VOLUME_DOWN`, want: Key{ State: KeyStatePress, Sender: "WebApp", Value: KeyVolumeDown, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var key Key err := xml.Unmarshal([]byte(tt.xmlData), &key) if err != nil { t.Fatalf("Failed to unmarshal XML: %v", err) } if key.State != tt.want.State { t.Errorf("Expected state %q, got %q", tt.want.State, key.State) } if key.Sender != tt.want.Sender { t.Errorf("Expected sender %q, got %q", tt.want.Sender, key.Sender) } if key.Value != tt.want.Value { t.Errorf("Expected value %q, got %q", tt.want.Value, key.Value) } }) } } func TestIsValidKey(t *testing.T) { validKeys := []string{ // Playback Controls KeyPlay, KeyPause, KeyStop, KeyPrevTrack, KeyNextTrack, // Rating and Bookmark Controls KeyThumbsUp, KeyThumbsDown, KeyBookmark, // Power and System Controls KeyPower, KeyMute, // Volume Controls KeyVolumeUp, KeyVolumeDown, // Preset Controls KeyPreset1, KeyPreset2, KeyPreset3, KeyPreset4, KeyPreset5, KeyPreset6, // Input Controls KeyAuxInput, // Shuffle Controls KeyShuffleOff, KeyShuffleOn, // Repeat Controls KeyRepeatOff, KeyRepeatOne, KeyRepeatAll, } invalidKeys := []string{ "INVALID_KEY", "play", "PAUSE_BUTTON", "PRESET_7", "PRESET_0", "", "VOLUME", } for _, key := range validKeys { t.Run("valid_"+key, func(t *testing.T) { if !IsValidKey(key) { t.Errorf("Expected %q to be valid", key) } }) } for _, key := range invalidKeys { t.Run("invalid_"+key, func(t *testing.T) { if IsValidKey(key) { t.Errorf("Expected %q to be invalid", key) } }) } } func TestGetAllValidKeys(t *testing.T) { keys := GetAllValidKeys() expectedKeys := []string{ // Playback Controls KeyPlay, KeyPause, KeyStop, KeyPrevTrack, KeyNextTrack, // Rating and Bookmark Controls KeyThumbsUp, KeyThumbsDown, KeyBookmark, // Power and System Controls KeyPower, KeyMute, // Volume Controls KeyVolumeUp, KeyVolumeDown, // Preset Controls KeyPreset1, KeyPreset2, KeyPreset3, KeyPreset4, KeyPreset5, KeyPreset6, // Input Controls KeyAuxInput, // Shuffle Controls KeyShuffleOff, KeyShuffleOn, // Repeat Controls KeyRepeatOff, KeyRepeatOne, KeyRepeatAll, } if len(keys) != len(expectedKeys) { t.Errorf("Expected %d keys, got %d", len(expectedKeys), len(keys)) } keyMap := make(map[string]bool) for _, key := range keys { keyMap[key] = true } for _, expectedKey := range expectedKeys { if !keyMap[expectedKey] { t.Errorf("Expected key %q not found in result", expectedKey) } } // Verify all returned keys are valid for _, key := range keys { if !IsValidKey(key) { t.Errorf("GetAllValidKeys returned invalid key: %q", key) } } } func TestKeyConstants(t *testing.T) { // Test that all key constants are defined and non-empty keyTests := []struct { name string value string }{ {"KeyPlay", KeyPlay}, {"KeyPause", KeyPause}, {"KeyStop", KeyStop}, {"KeyPrevTrack", KeyPrevTrack}, {"KeyNextTrack", KeyNextTrack}, {"KeyVolumeUp", KeyVolumeUp}, {"KeyVolumeDown", KeyVolumeDown}, {"KeyPreset1", KeyPreset1}, {"KeyPreset2", KeyPreset2}, {"KeyPreset3", KeyPreset3}, {"KeyPreset4", KeyPreset4}, {"KeyPreset5", KeyPreset5}, {"KeyPreset6", KeyPreset6}, } for _, tt := range keyTests { t.Run(tt.name, func(t *testing.T) { if tt.value == "" { t.Errorf("Expected %s to be non-empty", tt.name) } }) } } func TestKeyStateConstants(t *testing.T) { if KeyStatePress == "" { t.Error("KeyStatePress should not be empty") } if KeyStateRelease == "" { t.Error("KeyStateRelease should not be empty") } if KeyStatePress == KeyStateRelease { t.Error("KeyStatePress and KeyStateRelease should be different") } } // Benchmark tests func BenchmarkNewKey(b *testing.B) { for i := 0; i < b.N; i++ { NewKey(KeyPlay) } } func BenchmarkKeyXMLMarshal(b *testing.B) { key := NewKey(KeyPlay) b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = xml.Marshal(key) } } func BenchmarkIsValidKey(b *testing.B) { for i := 0; i < b.N; i++ { IsValidKey(KeyPlay) } } // Test that demonstrates the press+release pattern from API documentation func TestKeyPressReleasePattern(t *testing.T) { // According to API docs, we should send press followed by release keyValue := KeyPlay // Create press command keyPress := NewKey(keyValue) if keyPress.State != KeyStatePress { t.Errorf("Expected press state, got %s", keyPress.State) } if keyPress.Value != keyValue { t.Errorf("Expected key value %s, got %s", keyValue, keyPress.Value) } if keyPress.Sender != "Gabbo" { t.Errorf("Expected sender 'Gabbo', got %s", keyPress.Sender) } // Create release command keyRelease := NewKeyRelease(keyValue) if keyRelease.State != KeyStateRelease { t.Errorf("Expected release state, got %s", keyRelease.State) } if keyRelease.Value != keyValue { t.Errorf("Expected key value %s, got %s", keyValue, keyRelease.Value) } if keyRelease.Sender != "Gabbo" { t.Errorf("Expected sender 'Gabbo', got %s", keyRelease.Sender) } // Test XML marshaling for both pressXML, err := xml.Marshal(keyPress) if err != nil { t.Fatalf("Failed to marshal press XML: %v", err) } expectedPressXML := `PLAY` if string(pressXML) != expectedPressXML { t.Errorf("Press XML: got %s, want %s", string(pressXML), expectedPressXML) } releaseXML, err := xml.Marshal(keyRelease) if err != nil { t.Fatalf("Failed to marshal release XML: %v", err) } expectedReleaseXML := `PLAY` if string(releaseXML) != expectedReleaseXML { t.Errorf("Release XML: got %s, want %s", string(releaseXML), expectedReleaseXML) } }