feat: add TrackContextMenuConfig value type

Pure value type bundling playlists and callbacks needed to build a track
context menu; both tests pass (TDD).
feat/music-streaming
Laurent 1 month ago
parent 793fe036ad
commit c9cdf80a14
  1. 10
      Music/Models/TrackContextMenuConfig.swift
  2. 72
      MusicTests/TrackContextMenuConfigTests.swift

@ -0,0 +1,10 @@
import Foundation
struct TrackContextMenuConfig {
let playlists: [Playlist]
let lastUsedPlaylistName: String?
let selectedPlaylist: Playlist?
let onAddToPlaylist: (Track, Playlist) -> Void
let onAddToLastPlaylist: ((Track) -> Void)?
let onRemoveFromPlaylist: ((Track) -> Void)?
}

@ -0,0 +1,72 @@
import Testing
@testable import Music
struct TrackContextMenuConfigTests {
// Builds a config with all fields set and verifies:
// - stored playlists, lastUsedPlaylistName, selectedPlaylist match the inputs
// - onAddToPlaylist callback fires with the correct track and playlist
// - onAddToLastPlaylist callback fires with the correct track
// - onRemoveFromPlaylist callback fires with the correct track
// - when optional callbacks are nil, optionally calling them is safe
@Test func storesPropertiesAndFiresCallbacks() {
// 1. Create fixture data
let pl1 = Playlist.fixture(id: 1, name: "Favorites")
let pl2 = Playlist.fixture(id: 2, name: "Chill")
let track = Track.fixture(id: 42, title: "Test")
var addedTrack: Track? = nil
var addedPlaylist: Playlist? = nil
var lastTrack: Track? = nil
var removedTrack: Track? = nil
// 2. Build config with all callbacks
let config = TrackContextMenuConfig(
playlists: [pl1, pl2],
lastUsedPlaylistName: "Favorites",
selectedPlaylist: pl1,
onAddToPlaylist: { t, p in addedTrack = t; addedPlaylist = p },
onAddToLastPlaylist: { t in lastTrack = t },
onRemoveFromPlaylist: { t in removedTrack = t }
)
// 3. Verify stored properties
#expect(config.playlists.count == 2)
#expect(config.playlists[0].name == "Favorites")
#expect(config.lastUsedPlaylistName == "Favorites")
#expect(config.selectedPlaylist == pl1)
// 4. Invoke callbacks and verify they fire correctly
config.onAddToPlaylist(track, pl2)
config.onAddToLastPlaylist?(track)
config.onRemoveFromPlaylist?(track)
#expect(addedTrack?.id == track.id)
#expect(addedPlaylist?.id == pl2.id)
#expect(lastTrack?.id == track.id)
#expect(removedTrack?.id == track.id)
}
@Test func nilOptionalCallbacksAreSafe() {
// Verifies that a config with nil optional callbacks does not crash
// when you call them via optional chaining (the normal usage pattern)
let pl = Playlist.fixture(id: 1, name: "Rock")
let track = Track.fixture()
let config = TrackContextMenuConfig(
playlists: [pl],
lastUsedPlaylistName: nil,
selectedPlaylist: nil,
onAddToPlaylist: { _, _ in },
onAddToLastPlaylist: nil,
onRemoveFromPlaylist: nil
)
// These must not crash
config.onAddToLastPlaylist?(track)
config.onRemoveFromPlaylist?(track)
#expect(config.lastUsedPlaylistName == nil)
#expect(config.selectedPlaylist == nil)
}
}
Loading…
Cancel
Save