spotify_cli/io/formatters/
album.rs

1//! Album formatting functions
2
3use serde_json::Value;
4
5use crate::io::common::{extract_artist_names, format_duration};
6
7/// Format a list of saved albums
8pub fn format_saved_albums(items: &[Value]) {
9    if items.is_empty() {
10        println!("No saved albums.");
11        return;
12    }
13
14    println!("Saved Albums:");
15    for (i, item) in items.iter().enumerate() {
16        let album = item.get("album").unwrap_or(item);
17        let name = album
18            .get("name")
19            .and_then(|v| v.as_str())
20            .unwrap_or("Unknown");
21        let artists = extract_artist_names(album);
22        let total_tracks = album
23            .get("total_tracks")
24            .and_then(|v| v.as_u64())
25            .unwrap_or(0);
26        let release_date = album
27            .get("release_date")
28            .and_then(|v| v.as_str())
29            .unwrap_or("Unknown");
30
31        println!(
32            "  {}. {} - {} ({} tracks, {})",
33            i + 1,
34            name,
35            artists,
36            total_tracks,
37            release_date
38        );
39    }
40}
41
42pub fn format_album_detail(payload: &Value) {
43    let name = payload
44        .get("name")
45        .and_then(|v| v.as_str())
46        .unwrap_or("Unknown");
47    let artists = extract_artist_names(payload);
48    let album_type = payload
49        .get("album_type")
50        .and_then(|v| v.as_str())
51        .unwrap_or("album");
52    let release_date = payload
53        .get("release_date")
54        .and_then(|v| v.as_str())
55        .unwrap_or("Unknown");
56    let total_tracks = payload
57        .get("total_tracks")
58        .and_then(|v| v.as_u64())
59        .unwrap_or(0);
60    let popularity = payload
61        .get("popularity")
62        .and_then(|v| v.as_u64())
63        .unwrap_or(0);
64    let uri = payload.get("uri").and_then(|v| v.as_str()).unwrap_or("");
65
66    println!("{} ({})", name, album_type);
67    println!("  Artist: {}", artists);
68    println!("  Released: {}", release_date);
69    println!("  Tracks: {}", total_tracks);
70    println!("  Popularity: {}%", popularity);
71    if !uri.is_empty() {
72        println!("  URI: {}", uri);
73    }
74
75    // Show tracks
76    if let Some(tracks) = payload
77        .get("tracks")
78        .and_then(|t| t.get("items"))
79        .and_then(|i| i.as_array())
80        && !tracks.is_empty()
81    {
82        println!("\nTracklist:");
83        for track in tracks.iter() {
84            let track_num = track
85                .get("track_number")
86                .and_then(|v| v.as_u64())
87                .unwrap_or(0);
88            let track_name = track
89                .get("name")
90                .and_then(|v| v.as_str())
91                .unwrap_or("Unknown");
92            let duration_ms = track
93                .get("duration_ms")
94                .and_then(|v| v.as_u64())
95                .unwrap_or(0);
96            let duration = format_duration(duration_ms);
97            println!("  {}. {} [{}]", track_num, track_name, duration);
98        }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105    use serde_json::json;
106
107    #[test]
108    fn format_album_detail_full() {
109        let payload = json!({
110            "name": "Test Album",
111            "artists": [{ "name": "Test Artist" }],
112            "album_type": "album",
113            "release_date": "2023-06-15",
114            "total_tracks": 12,
115            "popularity": 75,
116            "uri": "spotify:album:abc123",
117            "tracks": {
118                "items": [
119                    { "track_number": 1, "name": "Track One", "duration_ms": 210000 },
120                    { "track_number": 2, "name": "Track Two", "duration_ms": 185000 }
121                ]
122            }
123        });
124        format_album_detail(&payload);
125    }
126
127    #[test]
128    fn format_album_detail_minimal() {
129        let payload = json!({});
130        format_album_detail(&payload);
131    }
132
133    #[test]
134    fn format_album_detail_single() {
135        let payload = json!({
136            "name": "Single Release",
137            "artists": [{ "name": "Artist" }],
138            "album_type": "single",
139            "release_date": "2024-01-01",
140            "total_tracks": 1
141        });
142        format_album_detail(&payload);
143    }
144
145    #[test]
146    fn format_album_detail_compilation() {
147        let payload = json!({
148            "name": "Greatest Hits",
149            "artists": [
150                { "name": "Artist One" },
151                { "name": "Artist Two" }
152            ],
153            "album_type": "compilation",
154            "release_date": "2020",
155            "total_tracks": 20,
156            "popularity": 90
157        });
158        format_album_detail(&payload);
159    }
160
161    #[test]
162    fn format_album_detail_without_tracks() {
163        let payload = json!({
164            "name": "Album Without Tracks",
165            "artists": [{ "name": "Artist" }],
166            "album_type": "album",
167            "tracks": { "items": [] }
168        });
169        format_album_detail(&payload);
170    }
171
172    #[test]
173    fn format_album_detail_no_uri() {
174        let payload = json!({
175            "name": "Album",
176            "artists": [{ "name": "Artist" }],
177            "release_date": "2023"
178        });
179        format_album_detail(&payload);
180    }
181}