From 5f2d1897b245fbee12d17b5910eaf5233ca6802b Mon Sep 17 00:00:00 2001 From: salmonik Date: Tue, 5 May 2026 23:29:39 +0200 Subject: Add unit tests in /tests directory for config, database, playback, and scrobbler modules --- tests/config.rs | 133 ++++++++++++++++++++++++++++++++++++++++ tests/database.rs | 85 ++++++++++++++++++++++++++ tests/playback.rs | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/scrobbler.rs | 77 +++++++++++++++++++++++ 4 files changed, 470 insertions(+) create mode 100644 tests/config.rs create mode 100644 tests/database.rs create mode 100644 tests/playback.rs create mode 100644 tests/scrobbler.rs (limited to 'tests') diff --git a/tests/config.rs b/tests/config.rs new file mode 100644 index 0000000..70c5034 --- /dev/null +++ b/tests/config.rs @@ -0,0 +1,133 @@ +use rsp::config::Config; +use std::path::PathBuf; + +#[test] +fn test_config_get_scan_interval() { + let config = Config { + config_path: PathBuf::from("/test/config.toml"), + music_paths: vec![], + scan_interval: Some(3600), + socket_path: None, + lastfm_api_key: None, + lastfm_api_secret: None, + lastfm_session_key: None, + listenbrainz_token: None, + volume: None, + shuffle: None, + }; + assert_eq!(config.get("scan_interval").unwrap(), "3600"); +} + +#[test] +fn test_config_get_not_set() { + let config = Config { + config_path: PathBuf::from("/test/config.toml"), + ..Default::default() + }; + assert_eq!(config.get("scan_interval").unwrap(), "not set"); +} + +#[test] +fn test_config_get_volume() { + let config = Config { + config_path: PathBuf::from("/test/config.toml"), + music_paths: vec![], + scan_interval: None, + socket_path: None, + lastfm_api_key: None, + lastfm_api_secret: None, + lastfm_session_key: None, + listenbrainz_token: None, + volume: Some(75), + shuffle: None, + }; + assert_eq!(config.get("volume").unwrap(), "75"); +} + +#[test] +fn test_config_get_unknown_key() { + let config = Config::default(); + let result = config.get("unknown_key"); + assert!(result.is_err()); +} + +#[test] +fn test_config_set_scan_interval() { + let mut config = Config::default(); + config.set("scan_interval", "7200").unwrap(); + assert_eq!(config.scan_interval, Some(7200)); +} + +#[test] +fn test_config_set_invalid_scan_interval() { + let mut config = Config::default(); + let result = config.set("scan_interval", "invalid"); + assert!(result.is_err()); +} + +#[test] +fn test_config_set_volume() { + let mut config = Config::default(); + config.set("volume", "50").unwrap(); + assert_eq!(config.volume, Some(50)); +} + +#[test] +fn test_config_set_invalid_volume() { + let mut config = Config::default(); + let result = config.set("volume", "256"); + assert!(result.is_err()); +} + +#[test] +fn test_config_set_shuffle_valid() { + let mut config = Config::default(); + config.set("shuffle", "all").unwrap(); + assert_eq!(config.shuffle, Some("all".to_string())); +} + +#[test] +fn test_config_set_shuffle_off() { + let mut config = Config::default(); + config.set("shuffle", "off").unwrap(); + assert_eq!(config.shuffle, None); +} + +#[test] +fn test_config_set_shuffle_invalid() { + let mut config = Config::default(); + let result = config.set("shuffle", "invalid"); + assert!(result.is_err()); +} + +#[test] +fn test_config_set_unknown_key() { + let mut config = Config::default(); + let result = config.set("unknown_key", "value"); + assert!(result.is_err()); +} + +#[test] +fn test_config_unset_volume() { + let mut config = Config { + config_path: PathBuf::from("/test/config.toml"), + music_paths: vec![], + scan_interval: None, + socket_path: None, + lastfm_api_key: None, + lastfm_api_secret: None, + lastfm_session_key: None, + listenbrainz_token: None, + volume: Some(50), + shuffle: None, + }; + config.unset("volume").unwrap(); + assert_eq!(config.volume, None); +} + +#[test] +fn test_config_unset_unknown_key() { + let mut config = Config::default(); + let result = config.unset("unknown_key"); + assert!(result.is_err()); +} diff --git a/tests/database.rs b/tests/database.rs new file mode 100644 index 0000000..67fe0ed --- /dev/null +++ b/tests/database.rs @@ -0,0 +1,85 @@ +use rsp::database::{extract_metadata, is_audio_file}; +use std::path::PathBuf; + +#[test] +fn test_is_audio_file_mp3() { + let path = PathBuf::from("/music/song.mp3"); + assert!(is_audio_file(&path)); +} + +#[test] +fn test_is_audio_file_flac() { + let path = PathBuf::from("/music/song.flac"); + assert!(is_audio_file(&path)); +} + +#[test] +fn test_is_audio_file_ogg() { + let path = PathBuf::from("/music/song.ogg"); + assert!(is_audio_file(&path)); +} + +#[test] +fn test_is_audio_file_m4a() { + let path = PathBuf::from("/music/song.m4a"); + assert!(is_audio_file(&path)); +} + +#[test] +fn test_is_audio_file_wav() { + let path = PathBuf::from("/music/song.wav"); + assert!(is_audio_file(&path)); +} + +#[test] +fn test_is_audio_file_opus() { + let path = PathBuf::from("/music/song.opus"); + assert!(is_audio_file(&path)); +} + +#[test] +fn test_is_audio_file_uppercase() { + let path = PathBuf::from("/music/song.MP3"); + assert!(is_audio_file(&path)); +} + +#[test] +fn test_is_audio_file_non_audio() { + let path = PathBuf::from("/music/song.txt"); + assert!(!is_audio_file(&path)); +} + +#[test] +fn test_is_audio_file_no_extension() { + let path = PathBuf::from("/music/songfile"); + assert!(!is_audio_file(&path)); +} + +#[test] +fn test_extract_metadata_standard_path() { + let path = PathBuf::from("/music/Artist/Album/Track.mp3"); + let (artist, album, title, track_num, duration) = extract_metadata(&path); + assert_eq!(artist, "Artist"); + assert_eq!(album, "Album"); + assert_eq!(title, "Track"); + assert_eq!(track_num, None); + assert_eq!(duration, None); +} + +#[test] +fn test_extract_metadata_deep_path() { + let path = PathBuf::from("/music/Artist/Album/Disc1/Track.mp3"); + let (artist, album, title, _, _) = extract_metadata(&path); + assert_eq!(artist, "Album"); + assert_eq!(album, "Disc1"); + assert_eq!(title, "Track"); +} + +#[test] +fn test_extract_metadata_no_parent() { + let path = PathBuf::from("/song.mp3"); + let (artist, album, title, _, _) = extract_metadata(&path); + assert_eq!(artist, "Unknown"); + assert_eq!(album, "Unknown"); + assert_eq!(title, "song"); +} diff --git a/tests/playback.rs b/tests/playback.rs new file mode 100644 index 0000000..80ecf58 --- /dev/null +++ b/tests/playback.rs @@ -0,0 +1,175 @@ +use rsp::playback::{PlaybackState, Player, ShuffleMode, Track}; +use std::path::PathBuf; + +fn dummy_track(title: &str) -> Track { + Track { + path: PathBuf::from(format!("/music/{}", title)), + title: title.to_string(), + artist: "Test Artist".to_string(), + album: "Test Album".to_string(), + duration: Some(180000), + } +} + +#[test] +fn test_player_default_state() { + let player = Player::new(); + assert_eq!(player.state(), &PlaybackState::Stopped); + assert_eq!(player.volume(), 70); +} + +#[test] +fn test_player_play_with_track_in_queue() { + let mut player = Player::new(); + player.queue_track(dummy_track("Test Track"), "last"); + player.play(); + assert_eq!(player.state(), &PlaybackState::Playing); + assert!(player.current_track.is_some()); + assert!(player.queue.is_empty()); +} + +#[test] +fn test_player_play_with_no_track() { + let mut player = Player::new(); + player.play(); + assert_eq!(player.state(), &PlaybackState::Stopped); +} + +#[test] +fn test_player_play_track() { + let mut player = Player::new(); + player.play_track(dummy_track("Test Track")); + assert_eq!(player.state(), &PlaybackState::Playing); + assert!(player.current_track.is_some()); +} + +#[test] +fn test_player_pause() { + let mut player = Player::new(); + player.play_track(dummy_track("Test Track")); + player.pause(); + assert_eq!(player.state(), &PlaybackState::Paused); +} + +#[test] +fn test_player_pause_when_stopped() { + let mut player = Player::new(); + player.pause(); + assert_eq!(player.state(), &PlaybackState::Stopped); +} + +#[test] +fn test_player_resume() { + let mut player = Player::new(); + player.play_track(dummy_track("Test Track")); + player.pause(); + player.resume(); + assert_eq!(player.state(), &PlaybackState::Playing); +} + +#[test] +fn test_player_resume_when_stopped() { + let mut player = Player::new(); + player.resume(); + assert_eq!(player.state(), &PlaybackState::Stopped); +} + +#[test] +fn test_player_stop() { + let mut player = Player::new(); + player.play_track(dummy_track("Test Track")); + player.stop(); + assert_eq!(player.state(), &PlaybackState::Stopped); + assert!(player.current_track.is_none()); +} + +#[test] +fn test_player_next_with_queue() { + let mut player = Player::new(); + player.queue_track(dummy_track("Track 1"), "last"); + player.queue_track(dummy_track("Track 2"), "last"); + player.next(); + assert_eq!(player.current_track.as_ref().unwrap().title, "Track 1"); +} + +#[test] +fn test_player_next_empty_queue() { + let mut player = Player::new(); + player.next(); + assert_eq!(player.state(), &PlaybackState::Stopped); + assert!(player.current_track.is_none()); +} + +#[test] +fn test_player_previous() { + let mut player = Player::new(); + player.play_track(dummy_track("Test Track")); + player.previous(); + assert_eq!(player.state(), &PlaybackState::Playing); +} + +#[test] +fn test_player_set_volume() { + let mut player = Player::new(); + player.set_volume(50); + assert_eq!(player.volume(), 50); +} + +#[test] +fn test_player_set_volume_caps_at_100() { + let mut player = Player::new(); + player.set_volume(150); + assert_eq!(player.volume(), 100); +} + +#[test] +fn test_player_set_shuffle() { + let mut player = Player::new(); + player.set_shuffle(ShuffleMode::All); + assert_eq!(player.shuffle, ShuffleMode::All); +} + +#[test] +fn test_player_queue_track_now() { + let mut player = Player::new(); + player.queue_track(dummy_track("Track 1"), "now"); + assert_eq!(player.queue.len(), 1); + assert_eq!(player.queue[0].title, "Track 1"); +} + +#[test] +fn test_player_queue_track_next() { + let mut player = Player::new(); + player.queue_track(dummy_track("Track 1"), "last"); + player.queue_track(dummy_track("Track 2"), "next"); + assert_eq!(player.queue.len(), 2); + assert_eq!(player.queue[0].title, "Track 1"); + assert_eq!(player.queue[1].title, "Track 2"); +} + +#[test] +fn test_player_queue_track_last() { + let mut player = Player::new(); + player.queue_track(dummy_track("Track 1"), "last"); + player.queue_track(dummy_track("Track 2"), "last"); + assert_eq!(player.queue.len(), 2); + assert_eq!(player.queue[0].title, "Track 1"); + assert_eq!(player.queue[1].title, "Track 2"); +} + +#[test] +fn test_player_dequeue_next() { + let mut player = Player::new(); + player.queue_track(dummy_track("Track 1"), "last"); + let track = player.dequeue_next(); + assert!(track.is_some()); + assert_eq!(track.unwrap().title, "Track 1"); + assert!(player.queue.is_empty()); +} + +#[test] +fn test_player_dequeue_next_empty() { + let mut player = Player::new(); + let track = player.dequeue_next(); + assert!(track.is_none()); +} diff --git a/tests/scrobbler.rs b/tests/scrobbler.rs new file mode 100644 index 0000000..f326250 --- /dev/null +++ b/tests/scrobbler.rs @@ -0,0 +1,77 @@ +use rsp::scrobbler::Scrobbler; + +#[test] +fn test_scrobbler_new_with_all_params() { + let scrobbler = Scrobbler::new( + Some("api_key".to_string()), + Some("secret".to_string()), + Some("session".to_string()), + Some("token".to_string()), + ); + assert!(scrobbler.lastfm_api_key.is_some()); + assert!(scrobbler.lastfm_api_secret.is_some()); + assert!(scrobbler.lastfm_session_key.is_some()); + assert!(scrobbler.listenbrainz_token.is_some()); +} + +#[test] +fn test_scrobbler_new_with_none() { + let scrobbler = Scrobbler::new(None, None, None, None); + assert!(scrobbler.lastfm_api_key.is_none()); + assert!(scrobbler.lastfm_api_secret.is_none()); + assert!(scrobbler.lastfm_session_key.is_none()); + assert!(scrobbler.listenbrainz_token.is_none()); +} + +#[test] +fn test_scrobbler_now_playing_no_api_key() { + let scrobbler = Scrobbler::new(None, None, None, None); + scrobbler.now_playing("Artist", "Track", Some("Album")); +} + +#[test] +fn test_scrobbler_now_playing_with_api_key() { + let scrobbler = Scrobbler::new(Some("api_key".to_string()), None, None, None); + scrobbler.now_playing("Artist", "Track", Some("Album")); +} + +#[test] +fn test_scrobbler_scrobble_no_keys() { + let scrobbler = Scrobbler::new(None, None, None, None); + scrobbler.scrobble("Artist", "Track", Some("Album"), 1234567890); +} + +#[test] +fn test_scrobbler_scrobble_with_lastfm() { + let scrobbler = Scrobbler::new(Some("api_key".to_string()), None, None, None); + scrobbler.scrobble("Artist", "Track", Some("Album"), 1234567890); +} + +#[test] +fn test_scrobbler_scrobble_with_listenbrainz() { + let scrobbler = Scrobbler::new(None, None, None, Some("token".to_string())); + scrobbler.scrobble("Artist", "Track", Some("Album"), 1234567890); +} + +#[test] +fn test_scrobbler_scrobble_with_both() { + let scrobbler = Scrobbler::new( + Some("api_key".to_string()), + None, + None, + Some("token".to_string()), + ); + scrobbler.scrobble("Artist", "Track", Some("Album"), 1234567890); +} + +#[test] +fn test_scrobbler_now_playing_no_album() { + let scrobbler = Scrobbler::new(Some("api_key".to_string()), None, None, None); + scrobbler.now_playing("Artist", "Track", None); +} + +#[test] +fn test_scrobbler_scrobble_no_album() { + let scrobbler = Scrobbler::new(Some("api_key".to_string()), None, None, None); + scrobbler.scrobble("Artist", "Track", None, 1234567890); +} -- cgit v1.2.3