- Implement core Rust backend with FFmpeg integration - Add TheTVDB API client with token caching - Implement directory scanner with progress callbacks - Create file manager with rename and move operations - Add audit logging functionality - Implement file mapping for TV episode renaming - Build Node.js native addon via NAPI - Include comprehensive unit and integration tests - Update gitignore to exclude build artifacts and temp files Resolves #TBD
244 lines
9.1 KiB
Rust
244 lines
9.1 KiB
Rust
//! Integration tests for TVDB API client
|
|
//!
|
|
//! These tests make real API calls to TheTVDB and require a valid API key.
|
|
//! Set the TVDB_API_KEY environment variable before running these tests.
|
|
|
|
use movie_mapper::service::tvdb_api::TVDBClient;
|
|
use movie_mapper::utils::TVDBError;
|
|
|
|
/// Get API key from environment or return a default test value
|
|
fn get_api_key() -> String {
|
|
std::env::var("TVDB_API_KEY").unwrap_or_else(|_| {
|
|
panic!("TVDB_API_KEY environment variable must be set for integration tests")
|
|
})
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_authenticate_success() {
|
|
let api_key = get_api_key();
|
|
let mut client = TVDBClient::new(&api_key).expect("Failed to create client");
|
|
|
|
// This should succeed with a valid API key
|
|
let result = client.authenticate().await;
|
|
|
|
assert!(result.is_ok(), "Authentication should succeed");
|
|
assert!(client.token.is_some(), "Token should be set after authentication");
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_search_finding_broken_bad() {
|
|
let api_key = get_api_key();
|
|
let mut client = TVDBClient::new(&api_key).expect("Failed to create client");
|
|
|
|
// Authenticate first
|
|
client.authenticate().await.expect("Authentication failed");
|
|
|
|
// Search for a well-known show
|
|
let shows = client.search("Breaking Bad").await.expect("Search failed");
|
|
|
|
assert!(!shows.is_empty(), "Should find at least one show");
|
|
|
|
// Verify the first result looks reasonable
|
|
let first_show = &shows[0];
|
|
assert_eq!(first_show.series_name, "Breaking Bad", "First result should be Breaking Bad");
|
|
assert!(first_show.id > 0, "Show should have a valid ID");
|
|
assert!(!first_show.overview.is_empty(), "Show should have an overview");
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_search_no_results() {
|
|
let api_key = get_api_key();
|
|
let mut client = TVDBClient::new(&api_key).expect("Failed to create client");
|
|
|
|
client.authenticate().await.expect("Authentication failed");
|
|
|
|
// Search for something that shouldn't exist
|
|
let shows = client.search("NonExistentShow12345XYZ").await.expect("Search should not fail");
|
|
|
|
// Should return empty array, not error
|
|
assert!(shows.is_empty(), "Should not find any shows for non-existent query");
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_search_partial_match() {
|
|
let api_key = get_api_key();
|
|
let mut client = TVDBClient::new(&api_key).expect("Failed to create client");
|
|
|
|
client.authenticate().await.expect("Authentication failed");
|
|
|
|
// Search with partial name
|
|
let shows = client.search("Breaking").await.expect("Search should not fail");
|
|
|
|
// Should find Breaking Bad and possibly other shows with "Breaking" in name
|
|
assert!(!shows.is_empty(), "Should find shows with 'Breaking' in name");
|
|
|
|
// Verify Breaking Bad is in results
|
|
let breaking_in_results = shows.iter().any(|s| s.series_name.contains("Breaking"));
|
|
assert!(breaking_in_results, "Should find shows containing 'Breaking'");
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_get_show_details() {
|
|
let api_key = get_api_key();
|
|
let mut client = TVDBClient::new(&api_key).expect("Failed to create client");
|
|
|
|
client.authenticate().await.expect("Authentication failed");
|
|
|
|
// First search to get a show ID
|
|
let shows = client.search("Breaking Bad").await.expect("Search failed");
|
|
let show_id = shows[0].id;
|
|
|
|
// Get detailed information
|
|
let details = client.get_show_details(show_id).await.expect("Get show details failed");
|
|
|
|
assert_eq!(details.id, show_id, "Details should match show ID");
|
|
assert_eq!(details.name, "Breaking Bad", "Show name should match");
|
|
assert!(!details.overview.is_empty(), "Should have an overview");
|
|
assert!(!details.seasons.is_empty(), "Should have at least one season");
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_get_season_episodes() {
|
|
let api_key = get_api_key();
|
|
let mut client = TVDBClient::new(&api_key).expect("Failed to create client");
|
|
|
|
client.authenticate().await.expect("Authentication failed");
|
|
|
|
// First search to get a show ID
|
|
let shows = client.search("Breaking Bad").await.expect("Search failed");
|
|
let show_id = shows[0].id;
|
|
|
|
// Get episodes for season 1
|
|
let episodes = client.get_season_episodes(show_id, 1).await.expect("Get episodes failed");
|
|
|
|
assert!(!episodes.is_empty(), "Should have at least one episode in season 1");
|
|
|
|
// Verify episode structure
|
|
let first_episode = &episodes[0];
|
|
assert_eq!(first_episode.season_number, 1, "Episode should be from season 1");
|
|
assert!(first_episode.number > 0, "Episode should have valid number");
|
|
assert!(!first_episode.name.is_empty(), "Episode should have a name");
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_token_caching() {
|
|
let api_key = get_api_key();
|
|
let mut client = TVDBClient::new(&api_key).expect("Failed to create client");
|
|
|
|
// First authentication
|
|
client.authenticate().await.expect("First auth failed");
|
|
let first_token = client.token.clone().expect("Should have token");
|
|
|
|
// Call search again - should use cached token
|
|
let shows = client.search("Breaking Bad").await.expect("Search failed");
|
|
|
|
// Verify we got results
|
|
assert!(!shows.is_empty(), "Should find shows");
|
|
|
|
// Token should still be the same (cached)
|
|
let second_token = client.token.clone().expect("Should still have token");
|
|
assert_eq!(first_token, second_token, "Token should be cached");
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_multiple_searches() {
|
|
let api_key = get_api_key();
|
|
let mut client = TVDBClient::new(&api_key).expect("Failed to create client");
|
|
|
|
client.authenticate().await.expect("Authentication failed");
|
|
|
|
// Perform multiple searches
|
|
let search_terms = vec!["Breaking Bad", "Better Call Saul", "The Wire"];
|
|
|
|
for term in search_terms {
|
|
let shows = client.search(term).await.expect(&format!("Search for {} failed", term));
|
|
println!("Search for '{}': Found {} results", term, shows.len());
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_full_workflow() {
|
|
let api_key = get_api_key();
|
|
let mut client = TVDBClient::new(&api_key).expect("Failed to create client");
|
|
|
|
// 1. Authenticate
|
|
client.authenticate().await.expect("Authentication failed");
|
|
|
|
// 2. Search for a show
|
|
let shows = client.search("Breaking Bad").await.expect("Search failed");
|
|
assert!(!shows.is_empty(), "Should find shows");
|
|
let show_id = shows[0].id;
|
|
|
|
// 3. Get show details
|
|
let details = client.get_show_details(show_id).await.expect("Get details failed");
|
|
println!("Show: {} ({})", details.name, details.status);
|
|
println!("Seasons: {}", details.seasons.len());
|
|
|
|
// 4. Get episodes for first season
|
|
if !details.seasons.is_empty() {
|
|
let season_number = details.seasons[0].number;
|
|
let episodes = client.get_season_episodes(show_id, season_number)
|
|
.await
|
|
.expect("Get episodes failed");
|
|
println!("Season {} has {} episodes", season_number, episodes.len());
|
|
|
|
// 5. Verify episode structure
|
|
for episode in &episodes {
|
|
println!(" - E{:02}: {}", episode.number, episode.name);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_error_handling_invalid_key() {
|
|
// Test with an invalid key to verify error handling
|
|
let mut client = TVDBClient::new("invalid-api-key-12345").expect("Failed to create client");
|
|
|
|
let result = client.authenticate().await;
|
|
|
|
// Should fail with authentication error
|
|
assert!(result.is_err(), "Authentication should fail with invalid key");
|
|
|
|
// The error should be related to authentication
|
|
let err = result.unwrap_err();
|
|
println!("Expected error: {}", err);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Integration test - requires real API calls"]
|
|
async fn test_tvdb_rate_limit_simulation() {
|
|
let api_key = get_api_key();
|
|
let mut client = TVDBClient::new(&api_key).expect("Failed to create client");
|
|
|
|
client.authenticate().await.expect("Authentication failed");
|
|
|
|
// Make many rapid requests to potentially hit rate limit
|
|
// This test may take some time and should be run with patience
|
|
for i in 0..5 {
|
|
let shows = client.search("Breaking Bad").await;
|
|
|
|
match shows {
|
|
Ok(_) => {
|
|
println!("Request {}: Success", i + 1);
|
|
}
|
|
Err(e) => {
|
|
println!("Request {}: Error - {}", i + 1, e);
|
|
// If we hit rate limit, that's actually expected behavior
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Small delay between requests
|
|
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
|
|
}
|
|
} |