package models import ( "encoding/xml" "testing" "time" ) func TestName_UnmarshalXML(t *testing.T) { xmlData := `Living Room SoundTouch` var name Name err := xml.Unmarshal([]byte(xmlData), &name) if err != nil { t.Fatalf("Failed to unmarshal XML: %v", err) } if name.Value != "Living Room SoundTouch" { t.Errorf("Expected name 'Living Room SoundTouch', got '%s'", name.Value) } if name.GetName() != "Living Room SoundTouch" { t.Errorf("Expected GetName() 'Living Room SoundTouch', got '%s'", name.GetName()) } if name.String() != "Living Room SoundTouch" { t.Errorf("Expected String() 'Living Room SoundTouch', got '%s'", name.String()) } if name.IsEmpty() { t.Error("Expected IsEmpty() to return false for non-empty name") } } func TestName_EmptyName(t *testing.T) { xmlData := `` var name Name err := xml.Unmarshal([]byte(xmlData), &name) if err != nil { t.Fatalf("Failed to unmarshal XML: %v", err) } if !name.IsEmpty() { t.Error("Expected IsEmpty() to return true for empty name") } if name.GetName() != "" { t.Errorf("Expected GetName() to return empty string, got '%s'", name.GetName()) } } func TestCapabilities_UnmarshalXML(t *testing.T) { xmlData := ` true true false false true false true ` var capabilities Capabilities err := xml.Unmarshal([]byte(xmlData), &capabilities) if err != nil { t.Fatalf("Failed to unmarshal XML: %v", err) } // Test basic fields if capabilities.DeviceID != "AABBCCDDEEFF" { t.Errorf("Expected DeviceID 'AABBCCDDEEFF', got '%s'", capabilities.DeviceID) } // Test boolean capabilities if capabilities.HasLightswitch() { t.Error("Expected HasLightswitch() to return false") } if capabilities.HasClockDisplay() { t.Error("Expected HasClockDisplay() to return false") } if !capabilities.HasLRStereoCapability() { t.Error("Expected HasLRStereoCapability() to return true") } if capabilities.HasBCOResetCapability() { t.Error("Expected HasBCOResetCapability() to return false") } if !capabilities.HasPowerSavingDisabled() { t.Error("Expected HasPowerSavingDisabled() to return true") } // Test network capabilities if !capabilities.HasDualModeNetwork() { t.Error("Expected HasDualModeNetwork() to return true") } if !capabilities.HasWSAPIProxy() { t.Error("Expected HasWSAPIProxy() to return true") } // Test DSP capabilities if capabilities.HasDSPMonoStereo() { t.Error("Expected HasDSPMonoStereo() to return false") } // Test capability by name if !capabilities.HasCapability("systemtimeout") { t.Error("Expected to have systemtimeout capability") } if capabilities.HasCapability("nonexistent") { t.Error("Expected to not have nonexistent capability") } // Test capability names capNames := capabilities.GetCapabilityNames() if len(capNames) != 2 { t.Errorf("Expected 2 capability names, got %d", len(capNames)) } // Test summaries networkCaps := capabilities.GetNetworkCapabilities() expectedNetworkCaps := []string{"Dual Mode", "WSAPI Proxy"} if len(networkCaps) != len(expectedNetworkCaps) { t.Errorf("Expected %d network capabilities, got %d", len(expectedNetworkCaps), len(networkCaps)) } audioCaps := capabilities.GetAudioCapabilities() expectedAudioCaps := []string{"L/R Stereo"} if len(audioCaps) != len(expectedAudioCaps) { t.Errorf("Expected %d audio capabilities, got %d", len(expectedAudioCaps), len(audioCaps)) } systemCaps := capabilities.GetSystemCapabilities() expectedSystemCaps := []string{"Power Saving Disabled"} if len(systemCaps) != len(expectedSystemCaps) { t.Errorf("Expected %d system capabilities, got %d", len(expectedSystemCaps), len(systemCaps)) } } func TestCapabilities_HostedWifiConfig(t *testing.T) { xmlData := ` true false true true ` var capabilities Capabilities err := xml.Unmarshal([]byte(xmlData), &capabilities) if err != nil { t.Fatalf("Failed to unmarshal XML: %v", err) } if !capabilities.HasHostedWifiConfig() { t.Error("Expected HasHostedWifiConfig() to return true") } if capabilities.GetHostedWifiPort() != "80" { t.Errorf("Expected hosted wifi port '80', got '%s'", capabilities.GetHostedWifiPort()) } if capabilities.GetHostedWifiHostedBy() != "BCO" { t.Errorf("Expected hosted wifi hosted by 'BCO', got '%s'", capabilities.GetHostedWifiHostedBy()) } if !capabilities.HasLightswitch() { t.Error("Expected HasLightswitch() to return true") } if !capabilities.HasClockDisplay() { t.Error("Expected HasClockDisplay() to return true") } } func TestPresets_UnmarshalXML(t *testing.T) { xmlData := ` My Playlist https://i.scdn.co/image/ab67616d00001e025ff75c5d082fc50a3a74ad7b Chill Music Collection https://i.scdn.co/image/ab67616d0000b273e07c8adc6fb49168dc8b7a2f Radio Station ` var presets Presets err := xml.Unmarshal([]byte(xmlData), &presets) if err != nil { t.Fatalf("Failed to unmarshal XML: %v", err) } // Test basic structure if presets.GetPresetCount() != 3 { t.Errorf("Expected 3 presets, got %d", presets.GetPresetCount()) } // Test first preset preset1 := presets.GetPresetByID(1) if preset1 == nil { t.Fatal("Expected to find preset with ID 1") } if preset1.GetDisplayName() != "My Playlist" { t.Errorf("Expected display name 'My Playlist', got '%s'", preset1.GetDisplayName()) } if !preset1.IsSpotifyPreset() { t.Error("Expected preset 1 to be a Spotify preset") } if preset1.GetSource() != "SPOTIFY" { t.Errorf("Expected source 'SPOTIFY', got '%s'", preset1.GetSource()) } if preset1.GetSourceAccount() != "user@example.com" { t.Errorf("Expected source account 'user@example.com', got '%s'", preset1.GetSourceAccount()) } if !preset1.HasTimestamps() { t.Error("Expected preset 1 to have timestamps") } // Test timestamps expectedCreated := time.Unix(1719128436, 0) if !preset1.GetCreatedTime().Equal(expectedCreated) { t.Errorf("Expected created time %v, got %v", expectedCreated, preset1.GetCreatedTime()) } expectedUpdated := time.Unix(1728740382, 0) if !preset1.GetUpdatedTime().Equal(expectedUpdated) { t.Errorf("Expected updated time %v, got %v", expectedUpdated, preset1.GetUpdatedTime()) } // Test third preset (TuneIn radio) preset3 := presets.GetPresetByID(3) if preset3 == nil { t.Fatal("Expected to find preset with ID 3") } if preset3.IsSpotifyPreset() { t.Error("Expected preset 3 to not be a Spotify preset") } if preset3.GetSource() != "TUNEIN" { t.Errorf("Expected source 'TUNEIN', got '%s'", preset3.GetSource()) } if preset3.HasTimestamps() { t.Error("Expected preset 3 to not have timestamps") } // Test filtering methods spotifyPresets := presets.GetSpotifyPresets() if len(spotifyPresets) != 2 { t.Errorf("Expected 2 Spotify presets, got %d", len(spotifyPresets)) } tuneinPresets := presets.GetPresetsBySource("TUNEIN") if len(tuneinPresets) != 1 { t.Errorf("Expected 1 TuneIn preset, got %d", len(tuneinPresets)) } // Test empty slots emptySlots := presets.GetEmptyPresetSlots() expectedEmpty := []int{4, 5, 6} if len(emptySlots) != len(expectedEmpty) { t.Errorf("Expected %d empty slots, got %d", len(expectedEmpty), len(emptySlots)) } // Test used slots usedSlots := presets.GetUsedPresetSlots() expectedUsed := []int{1, 2, 3} if len(usedSlots) != len(expectedUsed) { t.Errorf("Expected %d used slots, got %d", len(expectedUsed), len(usedSlots)) } // Test summary summary := presets.GetPresetsSummary() if summary["total"] != 3 { t.Errorf("Expected total 3, got %d", summary["total"]) } if summary["used"] != 3 { t.Errorf("Expected used 3, got %d", summary["used"]) } if summary["spotify"] != 2 { t.Errorf("Expected spotify 2, got %d", summary["spotify"]) } if summary["SPOTIFY"] != 2 { t.Errorf("Expected SPOTIFY 2, got %d", summary["SPOTIFY"]) } if summary["TUNEIN"] != 1 { t.Errorf("Expected TUNEIN 1, got %d", summary["TUNEIN"]) } // Test most recent preset mostRecent := presets.GetMostRecentPreset() if mostRecent == nil { t.Fatal("Expected to find most recent preset") } if mostRecent.ID != 2 { t.Errorf("Expected most recent preset ID 2, got %d", mostRecent.ID) } // Test oldest preset oldest := presets.GetOldestPreset() if oldest == nil { t.Fatal("Expected to find oldest preset") } if oldest.ID != 2 { t.Errorf("Expected oldest preset ID 2, got %d", oldest.ID) } } func TestPresets_EmptyPresets(t *testing.T) { xmlData := `` var presets Presets err := xml.Unmarshal([]byte(xmlData), &presets) if err != nil { t.Fatalf("Failed to unmarshal XML: %v", err) } if presets.HasPresets() { t.Error("Expected HasPresets() to return false for empty presets") } if presets.GetPresetCount() != 0 { t.Errorf("Expected preset count 0, got %d", presets.GetPresetCount()) } emptySlots := presets.GetEmptyPresetSlots() expectedSlots := []int{1, 2, 3, 4, 5, 6} if len(emptySlots) != len(expectedSlots) { t.Errorf("Expected %d empty slots, got %d", len(expectedSlots), len(emptySlots)) } if presets.GetMostRecentPreset() != nil { t.Error("Expected GetMostRecentPreset() to return nil for empty presets") } if presets.GetOldestPreset() != nil { t.Error("Expected GetOldestPreset() to return nil for empty presets") } } func TestPreset_EdgeCases(t *testing.T) { // Test preset without ContentItem emptyPreset := Preset{ID: 1} if !emptyPreset.IsEmpty() { t.Error("Expected IsEmpty() to return true for preset without ContentItem") } if emptyPreset.GetDisplayName() != "Preset 1" { t.Errorf("Expected display name 'Preset 1', got '%s'", emptyPreset.GetDisplayName()) } if emptyPreset.GetSource() != "" { t.Errorf("Expected empty source, got '%s'", emptyPreset.GetSource()) } if emptyPreset.GetArtworkURL() != "" { t.Errorf("Expected empty artwork URL, got '%s'", emptyPreset.GetArtworkURL()) } if emptyPreset.IsSpotifyPreset() { t.Error("Expected IsSpotifyPreset() to return false for empty preset") } // Test preset with ContentItem but no artwork presetNoArt := Preset{ ID: 2, ContentItem: &ContentItem{ Source: "TUNEIN", ItemName: "Test Station", }, } if presetNoArt.GetArtworkURL() != "" { t.Errorf("Expected empty artwork URL, got '%s'", presetNoArt.GetArtworkURL()) } if presetNoArt.GetDisplayName() != "Test Station" { t.Errorf("Expected display name 'Test Station', got '%s'", presetNoArt.GetDisplayName()) } }