213 lines
6.8 KiB
Rust
213 lines
6.8 KiB
Rust
// MIT License
|
|
// Copyright (c) 2025 Mahesh @ HeshApps
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
|
|
//! Unit tests for Music module for Unibar
|
|
|
|
use super::*;
|
|
use std::process::Command;
|
|
use crate::bar_modules::BarModuleActions;
|
|
|
|
/// Helper function to create test options
|
|
fn create_test_options(with_progress: bool) -> common::AppOptions {
|
|
common::AppOptions {
|
|
interval: 1,
|
|
weather_units: common::TemperatureUnits::Metric,
|
|
weather_station: "test".to_string(),
|
|
music_progress: with_progress,
|
|
debug: false,
|
|
debug_modules: false,
|
|
debug_update: false,
|
|
}
|
|
}
|
|
|
|
/// Test that module handles missing mpc command gracefully.
|
|
/// Note: This needs ROOT permissions, hence excluding from normal
|
|
/// testing
|
|
#[test]
|
|
#[ignore]
|
|
fn test_missing_mpc_command() {
|
|
let mut module = UnibarModuleMusic::new(create_test_options(true));
|
|
|
|
// Temporarily rename mpc command if it exists
|
|
let has_mpc = Command::new("which")
|
|
.arg("mpc")
|
|
.output()
|
|
.map(|output| output.status.success())
|
|
.unwrap_or(false);
|
|
|
|
let original_mpc_path = "/usr/bin/mpc";
|
|
let backup_mpc_path = "/tmp/mpc.bak";
|
|
|
|
if has_mpc {
|
|
// Create a backup
|
|
std::fs::copy(original_mpc_path, backup_mpc_path).expect("Failed to backup mpc");
|
|
// Rename the original
|
|
std::fs::rename(original_mpc_path, "/tmp/mpc_renamed").expect("Failed to rename mpc");
|
|
}
|
|
|
|
// Generate data should not panic
|
|
module.generate_data();
|
|
|
|
// Should show appropriate error state
|
|
assert_eq!(module.get_icon(), "⏹");
|
|
assert!(module.get_content().contains("No player"));
|
|
|
|
// Restore mpc if it existed
|
|
if has_mpc {
|
|
// Remove the renamed file
|
|
std::fs::remove_file("/tmp/mpc_renamed").expect("Failed to remove renamed mpc");
|
|
// Restore from backup
|
|
std::fs::rename(backup_mpc_path, original_mpc_path).expect("Failed to restore mpc");
|
|
}
|
|
}
|
|
|
|
/// Test handling of mpc command failing
|
|
#[test]
|
|
fn test_mpc_command_failure() {
|
|
let mut module = UnibarModuleMusic::new(create_test_options(true));
|
|
|
|
// Mock mpc command to always fail
|
|
module.current_stdout = "Error: Command not found".to_string();
|
|
module.progress_stdout = "".to_string();
|
|
module.state_stdout = "stopped".to_string();
|
|
|
|
// Generate data should not panic
|
|
// module.generate_data();
|
|
|
|
// Should show appropriate error state
|
|
assert_eq!(module.get_icon(), "⏹");
|
|
assert!(module.get_content().contains("Command not found"));
|
|
}
|
|
|
|
/// Test handling of various mpc output formats
|
|
#[test]
|
|
fn test_unexpected_mpc_output() {
|
|
let mut module = UnibarModuleMusic::new(create_test_options(true));
|
|
|
|
// Test cases for current_stdout
|
|
let test_cases = vec![
|
|
"", // Empty output
|
|
"\n", // Just newline
|
|
//"invalid utf8 \x80", // Invalid UTF-8
|
|
"very\nlong\noutput\n", // Multiple lines
|
|
" ", // Just whitespace
|
|
"🎵 unicode 🎶", // Unicode characters
|
|
];
|
|
|
|
for test_case in test_cases {
|
|
module.current_stdout = test_case.to_string();
|
|
// get_content should not panic
|
|
let content = module.get_content();
|
|
assert!(!content.is_empty(), "Content should not be empty");
|
|
}
|
|
}
|
|
|
|
/// Test state handling and icon selection
|
|
#[test]
|
|
fn test_player_states() {
|
|
let mut module = UnibarModuleMusic::new(create_test_options(false));
|
|
|
|
// Test valid states
|
|
let states = vec![
|
|
("playing", "𝄞"),
|
|
("paused", "⏸"),
|
|
("stopped", "⏹"),
|
|
];
|
|
|
|
for (state, expected_icon) in states {
|
|
module.state_stdout = state.to_string();
|
|
assert_eq!(module.get_icon(), expected_icon);
|
|
}
|
|
|
|
// Test invalid states
|
|
let invalid_states = vec![
|
|
"",
|
|
"invalid",
|
|
"PLAYING",
|
|
"unknown",
|
|
"\n",
|
|
"playing\n",
|
|
];
|
|
|
|
for state in invalid_states {
|
|
module.state_stdout = state.to_string();
|
|
assert_eq!(module.get_icon(), "𝄞", "Invalid state should default to playing icon");
|
|
}
|
|
}
|
|
|
|
/// Test progress display formatting
|
|
#[test]
|
|
fn test_progress_display() {
|
|
let mut module = UnibarModuleMusic::new(create_test_options(true));
|
|
|
|
// Test various progress formats
|
|
let test_cases = vec![
|
|
("50% 3:30", "[50% 3:30]"),
|
|
("", "[]"),
|
|
("invalid", "[invalid]"),
|
|
("100% 0:00", "[100% 0:00]"),
|
|
(" 50% 3:30 ", "[50% 3:30]"), // Extra whitespace
|
|
];
|
|
|
|
for (progress, expected) in test_cases {
|
|
module.progress_stdout = progress.to_string();
|
|
module.current_stdout = "Test Song".to_string();
|
|
let content = module.get_content();
|
|
assert!(content.contains(expected));
|
|
}
|
|
|
|
// Test with progress disabled
|
|
let mut module = UnibarModuleMusic::new(create_test_options(false));
|
|
module.progress_stdout = "50% 3:30".to_string();
|
|
module.current_stdout = "Test Song".to_string();
|
|
assert_eq!(module.get_content(), "Test Song");
|
|
}
|
|
|
|
/// Test module initialization
|
|
#[test]
|
|
fn test_module_initialization() {
|
|
let module = UnibarModuleMusic::new(create_test_options(true));
|
|
|
|
assert_eq!(module.current_stdout, "");
|
|
assert_eq!(module.progress_stdout, "");
|
|
assert_eq!(module.state_stdout, "stopped");
|
|
assert_eq!(module.get_icon(), "⏹");
|
|
}
|
|
|
|
/// Test clear functionality
|
|
#[test]
|
|
fn test_clear() {
|
|
let mut module = UnibarModuleMusic::new(create_test_options(true));
|
|
|
|
// Set some data
|
|
module.current_stdout = "Test Song".to_string();
|
|
module.progress_stdout = "50% 3:30".to_string();
|
|
module.state_stdout = "playing".to_string();
|
|
|
|
// Clear the module
|
|
module.clear();
|
|
|
|
// Verify cleared state
|
|
assert_eq!(module.current_stdout, "");
|
|
assert_eq!(module.progress_stdout, "");
|
|
assert_eq!(module.state_stdout, "stopped");
|
|
}
|