spotify_cli/io/formatters/
library.rs1use serde_json::Value;
4
5use crate::io::common::extract_artist_names;
6
7pub fn format_saved_tracks(items: &[Value]) {
8 println!("Saved Tracks:");
9 for (i, item) in items.iter().take(20).enumerate() {
10 if let Some(track) = item.get("track") {
11 let name = track
12 .get("name")
13 .and_then(|v| v.as_str())
14 .unwrap_or("Unknown");
15 let artists = extract_artist_names(track);
16 println!(" {}. {} - {}", i + 1, name, artists);
17 }
18 }
19}
20
21pub fn format_library_check(results: &[Value]) {
22 println!("Library Check:");
23 for (i, result) in results.iter().enumerate() {
24 let saved = result.as_bool().unwrap_or(false);
25 let status = if saved { "Saved" } else { "Not saved" };
26 println!(" Track {}: {}", i + 1, status);
27 }
28}
29
30pub fn format_markets(markets: &[Value]) {
31 if markets.is_empty() {
32 println!("No markets available.");
33 return;
34 }
35
36 println!("Available Markets ({} countries):", markets.len());
37 let market_codes: Vec<&str> = markets.iter().filter_map(|v| v.as_str()).collect();
38
39 for chunk in market_codes.chunks(10) {
41 println!(" {}", chunk.join(", "));
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use serde_json::json;
49
50 #[test]
51 fn format_saved_tracks_with_items() {
52 let items = vec![
53 json!({ "track": { "name": "Track 1", "artists": [{ "name": "Artist 1" }] } }),
54 json!({ "track": { "name": "Track 2", "artists": [{ "name": "Artist 2" }] } }),
55 ];
56 format_saved_tracks(&items);
57 }
58
59 #[test]
60 fn format_saved_tracks_empty() {
61 let items: Vec<Value> = vec![];
62 format_saved_tracks(&items);
63 }
64
65 #[test]
66 fn format_saved_tracks_more_than_twenty() {
67 let items: Vec<Value> = (0..25)
68 .map(|i| json!({ "track": { "name": format!("Track {}", i), "artists": [{ "name": "Artist" }] } }))
69 .collect();
70 format_saved_tracks(&items);
71 }
72
73 #[test]
74 fn format_saved_tracks_no_track_field() {
75 let items = vec![json!({ "name": "Direct Item" })];
76 format_saved_tracks(&items);
77 }
78
79 #[test]
80 fn format_library_check_mixed() {
81 let results = vec![json!(true), json!(false), json!(true)];
82 format_library_check(&results);
83 }
84
85 #[test]
86 fn format_library_check_empty() {
87 let results: Vec<Value> = vec![];
88 format_library_check(&results);
89 }
90
91 #[test]
92 fn format_library_check_all_saved() {
93 let results = vec![json!(true), json!(true)];
94 format_library_check(&results);
95 }
96
97 #[test]
98 fn format_library_check_none_saved() {
99 let results = vec![json!(false), json!(false)];
100 format_library_check(&results);
101 }
102
103 #[test]
104 fn format_library_check_non_bool() {
105 let results = vec![json!("invalid"), json!(null)];
106 format_library_check(&results);
107 }
108}