more checks and updated pipeines
Some checks failed
🏗️ Build and Test JellyTau / Build APK and Run Tests (push) Has been cancelled
Traceability Validation / Check Requirement Traces (push) Has been cancelled

This commit is contained in:
Duncan Tourolle 2026-02-14 09:11:22 +01:00
parent e664bf4620
commit dbcaa1a1a5
4 changed files with 354 additions and 2 deletions

View File

@ -14,7 +14,7 @@ on:
jobs: jobs:
validate-traces: validate-traces:
runs-on: ubuntu-latest runs-on: [linux, amd64]
name: Check Requirement Traces name: Check Requirement Traces
steps: steps:

View File

@ -15,7 +15,7 @@ on:
jobs: jobs:
traceability: traceability:
name: Validate Requirement Traces name: Validate Requirement Traces
runs-on: ubuntu-latest runs-on: [linux, amd64]
steps: steps:
- name: Checkout code - name: Checkout code

View File

@ -41,3 +41,237 @@ pub struct PlaybackProgressRequest {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub play_session_id: Option<String>, pub play_session_id: Option<String>,
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_jellyfin_config_creation() {
let config = JellyfinConfig {
server_url: "https://jellyfin.example.com".to_string(),
access_token: "token-123".to_string(),
device_id: "device-456".to_string(),
};
assert_eq!(config.server_url, "https://jellyfin.example.com");
assert_eq!(config.access_token, "token-123");
assert_eq!(config.device_id, "device-456");
}
#[test]
fn test_jellyfin_config_clone() {
let config = JellyfinConfig {
server_url: "https://server.local".to_string(),
access_token: "token-abc".to_string(),
device_id: "device-xyz".to_string(),
};
let cloned = config.clone();
assert_eq!(config.server_url, cloned.server_url);
assert_eq!(config.access_token, cloned.access_token);
assert_eq!(config.device_id, cloned.device_id);
}
#[test]
fn test_playback_start_request_serialization() {
let request = PlaybackStartRequest {
item_id: "item-123".to_string(),
position_ticks: 0,
play_session_id: Some("session-456".to_string()),
play_command: "PlayNow".to_string(),
is_paused: false,
};
let json = serde_json::to_string(&request);
assert!(json.is_ok());
let serialized = json.unwrap();
assert!(serialized.contains("item-123"));
assert!(serialized.contains("PlayNow"));
}
#[test]
fn test_playback_start_request_without_session() {
let request = PlaybackStartRequest {
item_id: "item-789".to_string(),
position_ticks: 1_000_000,
play_session_id: None,
play_command: "Resume".to_string(),
is_paused: true,
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("true"));
assert!(!json.contains("playSessionId"));
}
#[test]
fn test_playback_start_request_pascal_case() {
let request = PlaybackStartRequest {
item_id: "item-1".to_string(),
position_ticks: 100,
play_session_id: Some("session-1".to_string()),
play_command: "Play".to_string(),
is_paused: false,
};
let json = serde_json::to_string(&request).unwrap();
// Verify PascalCase serialization
assert!(json.contains("ItemId"));
assert!(json.contains("PositionTicks"));
assert!(json.contains("PlaySessionId"));
assert!(json.contains("PlayCommand"));
assert!(json.contains("IsPaused"));
}
#[test]
fn test_playback_stopped_request_serialization() {
let request = PlaybackStoppedRequest {
item_id: "item-555".to_string(),
position_ticks: 5_000_000,
play_session_id: Some("session-789".to_string()),
};
let json = serde_json::to_string(&request);
assert!(json.is_ok());
let serialized = json.unwrap();
assert!(serialized.contains("item-555"));
assert!(serialized.contains("5000000"));
}
#[test]
fn test_playback_stopped_request_without_session() {
let request = PlaybackStoppedRequest {
item_id: "item-000".to_string(),
position_ticks: 0,
play_session_id: None,
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("item-000"));
assert!(!json.contains("playSessionId"));
}
#[test]
fn test_playback_stopped_request_pascal_case() {
let request = PlaybackStoppedRequest {
item_id: "i1".to_string(),
position_ticks: 500,
play_session_id: Some("s1".to_string()),
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("ItemId"));
assert!(json.contains("PositionTicks"));
assert!(json.contains("PlaySessionId"));
}
#[test]
fn test_playback_progress_request_serialization() {
let request = PlaybackProgressRequest {
item_id: "item-999".to_string(),
position_ticks: 150_000_000,
is_paused: false,
play_session_id: Some("session-111".to_string()),
};
let json = serde_json::to_string(&request);
assert!(json.is_ok());
let serialized = json.unwrap();
assert!(serialized.contains("item-999"));
assert!(serialized.contains("150000000"));
assert!(serialized.contains("false"));
}
#[test]
fn test_playback_progress_request_paused() {
let request = PlaybackProgressRequest {
item_id: "item-paused".to_string(),
position_ticks: 75_000_000,
is_paused: true,
play_session_id: None,
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("true"));
assert!(json.contains("item-paused"));
}
#[test]
fn test_playback_progress_request_pascal_case() {
let request = PlaybackProgressRequest {
item_id: "i2".to_string(),
position_ticks: 200,
is_paused: true,
play_session_id: Some("s2".to_string()),
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("ItemId"));
assert!(json.contains("PositionTicks"));
assert!(json.contains("IsPaused"));
assert!(json.contains("PlaySessionId"));
}
#[test]
fn test_playback_start_request_various_position_values() {
let positions = vec![0, 1_000_000, 10_000_000, 100_000_000, 1_000_000_000];
for pos in positions {
let request = PlaybackStartRequest {
item_id: "item-test".to_string(),
position_ticks: pos,
play_session_id: None,
play_command: "Play".to_string(),
is_paused: false,
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("item-test"));
assert!(json.contains(&pos.to_string()));
}
}
#[test]
fn test_jellyfin_config_debug() {
let config = JellyfinConfig {
server_url: "https://debug.example.com".to_string(),
access_token: "token-debug".to_string(),
device_id: "device-debug".to_string(),
};
let debug_str = format!("{:?}", config);
assert!(debug_str.contains("JellyfinConfig"));
assert!(debug_str.contains("https://debug.example.com"));
}
#[test]
fn test_playback_requests_creation_patterns() {
// Test various creation patterns
let start = PlaybackStartRequest {
item_id: "i1".to_string(),
position_ticks: 0,
play_session_id: None,
play_command: "PlayNow".to_string(),
is_paused: false,
};
let stopped = PlaybackStoppedRequest {
item_id: "i1".to_string(),
position_ticks: 1_000_000,
play_session_id: None,
};
let progress = PlaybackProgressRequest {
item_id: "i1".to_string(),
position_ticks: 500_000,
is_paused: false,
play_session_id: None,
};
// All should serialize successfully
assert!(serde_json::to_string(&start).is_ok());
assert!(serde_json::to_string(&stopped).is_ok());
assert!(serde_json::to_string(&progress).is_ok());
}
}

View File

@ -13,3 +13,121 @@ pub struct PlaylistItem {
pub sort_order: i32, pub sort_order: i32,
pub added_at: Option<DateTime<Utc>>, pub added_at: Option<DateTime<Utc>>,
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_playlist_item_creation() {
let item = PlaylistItem {
id: Some(1),
playlist_id: "playlist-123".to_string(),
item_id: "item-456".to_string(),
sort_order: 0,
added_at: None,
};
assert_eq!(item.id, Some(1));
assert_eq!(item.playlist_id, "playlist-123");
assert_eq!(item.item_id, "item-456");
assert_eq!(item.sort_order, 0);
assert!(item.added_at.is_none());
}
#[test]
fn test_playlist_item_without_id() {
let item = PlaylistItem {
id: None,
playlist_id: "playlist-789".to_string(),
item_id: "item-999".to_string(),
sort_order: 5,
added_at: None,
};
assert!(item.id.is_none());
assert_eq!(item.sort_order, 5);
}
#[test]
fn test_playlist_item_serialization() {
let item = PlaylistItem {
id: Some(42),
playlist_id: "pl-001".to_string(),
item_id: "it-001".to_string(),
sort_order: 10,
added_at: None,
};
let json = serde_json::to_string(&item);
assert!(json.is_ok());
let serialized = json.unwrap();
assert!(serialized.contains("pl-001"));
assert!(serialized.contains("it-001"));
assert!(serialized.contains("10"));
}
#[test]
fn test_playlist_item_clone() {
let item = PlaylistItem {
id: Some(99),
playlist_id: "clone-playlist".to_string(),
item_id: "clone-item".to_string(),
sort_order: 3,
added_at: None,
};
let cloned = item.clone();
assert_eq!(item.id, cloned.id);
assert_eq!(item.playlist_id, cloned.playlist_id);
assert_eq!(item.item_id, cloned.item_id);
assert_eq!(item.sort_order, cloned.sort_order);
}
#[test]
fn test_playlist_item_with_timestamp() {
let now = Utc::now();
let item = PlaylistItem {
id: Some(100),
playlist_id: "time-playlist".to_string(),
item_id: "time-item".to_string(),
sort_order: 7,
added_at: Some(now),
};
assert!(item.added_at.is_some());
assert_eq!(item.added_at, Some(now));
}
#[test]
fn test_playlist_item_multiple_sort_orders() {
let sort_orders = vec![0, 1, 5, 10, 100, 999];
for order in sort_orders {
let item = PlaylistItem {
id: Some(1),
playlist_id: "pl".to_string(),
item_id: "it".to_string(),
sort_order: order,
added_at: None,
};
assert_eq!(item.sort_order, order);
}
}
#[test]
fn test_playlist_item_debug() {
let item = PlaylistItem {
id: Some(200),
playlist_id: "debug-pl".to_string(),
item_id: "debug-it".to_string(),
sort_order: 15,
added_at: None,
};
let debug_str = format!("{:?}", item);
assert!(debug_str.contains("PlaylistItem"));
assert!(debug_str.contains("debug-pl"));
}
}