Readur/src/services/webdav/url_construction_tests.rs

766 lines
32 KiB
Rust

#[cfg(test)]
mod tests {
use super::super::{WebDAVService, WebDAVConfig};
// Helper function to create test WebDAV service for Nextcloud
fn create_nextcloud_webdav_service() -> WebDAVService {
let config = WebDAVConfig {
server_url: "https://nas.example.com".to_string(),
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string(), "txt".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
WebDAVService::new(config).unwrap()
}
// Helper function to create test WebDAV service for generic servers
fn create_generic_webdav_service() -> WebDAVService {
let config = WebDAVConfig {
server_url: "https://webdav.example.com".to_string(),
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string(), "txt".to_string()],
timeout_seconds: 30,
server_type: Some("generic".to_string()),
};
WebDAVService::new(config).unwrap()
}
#[tokio::test]
async fn test_nextcloud_path_conversion_basic() {
let service = create_nextcloud_webdav_service();
// Test basic path conversion
let full_webdav_path = "/remote.php/dav/files/testuser/Documents/";
let relative_path = service.convert_to_relative_path(full_webdav_path);
assert_eq!(relative_path, "/Documents/");
}
#[tokio::test]
async fn test_nextcloud_path_conversion_nested() {
let service = create_nextcloud_webdav_service();
// Test nested path conversion
let full_webdav_path = "/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/Projects/";
let relative_path = service.convert_to_relative_path(full_webdav_path);
assert_eq!(relative_path, "/FullerDocuments/NicoleDocuments/Projects/");
}
#[tokio::test]
async fn test_nextcloud_path_conversion_with_spaces() {
let service = create_nextcloud_webdav_service();
// Test path with URL-encoded spaces (the actual bug scenario)
let full_webdav_path = "/remote.php/dav/files/testuser/Documents/Melanie%20Martinez%20June%207%202023/";
let relative_path = service.convert_to_relative_path(full_webdav_path);
assert_eq!(relative_path, "/Documents/Melanie%20Martinez%20June%207%202023/");
}
#[tokio::test]
async fn test_nextcloud_path_conversion_with_special_chars() {
let service = create_nextcloud_webdav_service();
// Test path with various special characters
let full_webdav_path = "/remote.php/dav/files/testuser/Documents/Maranatha%20Work/";
let relative_path = service.convert_to_relative_path(full_webdav_path);
assert_eq!(relative_path, "/Documents/Maranatha%20Work/");
}
#[tokio::test]
async fn test_generic_webdav_path_conversion() {
let service = create_generic_webdav_service();
// Test generic WebDAV path conversion
let full_webdav_path = "/webdav/Documents/Projects/";
let relative_path = service.convert_to_relative_path(full_webdav_path);
assert_eq!(relative_path, "/Documents/Projects/");
}
#[tokio::test]
async fn test_path_conversion_with_mismatched_prefix() {
let service = create_nextcloud_webdav_service();
// Test path that doesn't match expected prefix (should return as-is)
let unexpected_path = "/some/other/path/Documents/";
let relative_path = service.convert_to_relative_path(unexpected_path);
assert_eq!(relative_path, "/some/other/path/Documents/");
}
#[tokio::test]
async fn test_url_construction_validation() {
let service = create_nextcloud_webdav_service();
// Test that we can identify the problem that caused the bug
// This simulates what was happening before the fix
// What we get from XML parser (full WebDAV path)
let full_webdav_path = "/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/";
// What the old code would do (WRONG - double construction)
let base_url = "https://nas.example.com/remote.php/dav/files/testuser";
let wrong_url = format!("{}{}", base_url, full_webdav_path);
// This would create a malformed URL
assert_eq!(wrong_url, "https://nas.example.com/remote.php/dav/files/testuser/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/");
// What the new code does (CORRECT)
let relative_path = service.convert_to_relative_path(full_webdav_path);
let correct_url = format!("{}{}", base_url, relative_path);
assert_eq!(correct_url, "https://nas.example.com/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/");
// Verify they're different (this is the bug we fixed)
assert_ne!(wrong_url, correct_url);
}
#[tokio::test]
async fn test_real_world_nextcloud_paths() {
let service = create_nextcloud_webdav_service();
// Test real-world paths that would come from Nextcloud XML responses
let real_world_paths = vec![
"/remote.php/dav/files/testuser/",
"/remote.php/dav/files/testuser/Documents/",
"/remote.php/dav/files/testuser/FullerDocuments/",
"/remote.php/dav/files/testuser/FullerDocuments/JonDocuments/",
"/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/",
"/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/Maranatha%20Work/",
"/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/Melanie%20Martinez%20June%207%202023/",
"/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/Misc/",
"/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/Nicole-Barakat-Website/",
"/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/RDP/",
];
let expected_relative_paths = vec![
"/",
"/Documents/",
"/FullerDocuments/",
"/FullerDocuments/JonDocuments/",
"/FullerDocuments/NicoleDocuments/",
"/FullerDocuments/NicoleDocuments/Maranatha%20Work/",
"/FullerDocuments/NicoleDocuments/Melanie%20Martinez%20June%207%202023/",
"/FullerDocuments/NicoleDocuments/Misc/",
"/FullerDocuments/NicoleDocuments/Nicole-Barakat-Website/",
"/FullerDocuments/NicoleDocuments/RDP/",
];
for (full_path, expected_relative) in real_world_paths.iter().zip(expected_relative_paths.iter()) {
let result = service.convert_to_relative_path(full_path);
assert_eq!(&result, expected_relative,
"Failed to convert {} to {}, got {}", full_path, expected_relative, result);
}
}
#[tokio::test]
async fn test_url_construction_end_to_end() {
let service = create_nextcloud_webdav_service();
// Test the complete URL construction process
let base_webdav_url = "https://nas.example.com/remote.php/dav/files/testuser";
// Simulate a path that would cause 404 with the old bug
let problematic_path = "/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/Melanie%20Martinez%20June%207%202023/";
// Convert to relative path
let relative_path = service.convert_to_relative_path(problematic_path);
// Construct final URL
let final_url = format!("{}{}", base_webdav_url, relative_path);
// Verify the URL is correctly constructed
assert_eq!(final_url, "https://nas.example.com/remote.php/dav/files/testuser/FullerDocuments/NicoleDocuments/Melanie%20Martinez%20June%207%202023/");
// Verify it doesn't contain double paths
assert!(!final_url.contains("/remote.php/dav/files/testuser/remote.php/dav/files/testuser/"));
}
#[tokio::test]
async fn test_different_usernames() {
// Test with different usernames to ensure the path conversion works correctly
let usernames = vec!["testuser", "perf3ct", "admin", "user123", "user.name"];
for username in usernames {
let config = WebDAVConfig {
server_url: "https://nas.example.com".to_string(),
username: username.to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
let service = WebDAVService::new(config).unwrap();
let full_path = format!("/remote.php/dav/files/{}/Documents/TestFolder/", username);
let relative_path = service.convert_to_relative_path(&full_path);
assert_eq!(relative_path, "/Documents/TestFolder/",
"Failed for username: {}", username);
}
}
// Test that validates the fix prevents the exact error scenario
#[tokio::test]
async fn test_fix_prevents_original_bug() {
// Create service with the same username as in the problematic path
let config = WebDAVConfig {
server_url: "https://nas.jonathonfuller.com".to_string(),
username: "perf3ct".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
let service = WebDAVService::new(config).unwrap();
// This is the exact path from the error logs that was causing 404s
let problematic_path = "/remote.php/dav/files/perf3ct/FullerDocuments/NicoleDocuments/Melanie%20Martinez%20June%207%202023/";
// Before fix: This would have been used directly, causing double path construction
let base_url = "https://nas.jonathonfuller.com/remote.php/dav/files/perf3ct";
let old_buggy_url = format!("{}{}", base_url, problematic_path);
// After fix: Convert to relative path first
let relative_path = service.convert_to_relative_path(problematic_path);
let fixed_url = format!("{}{}", base_url, relative_path);
// Debug: print what we got
println!("Original path: {}", problematic_path);
println!("Relative path: {}", relative_path);
println!("Old buggy URL: {}", old_buggy_url);
println!("Fixed URL: {}", fixed_url);
// The old URL would have been malformed (causing 404)
assert!(old_buggy_url.contains("/remote.php/dav/files/perf3ct/remote.php/dav/files/perf3ct/"));
// The new URL should be properly formed
assert_eq!(fixed_url, "https://nas.jonathonfuller.com/remote.php/dav/files/perf3ct/FullerDocuments/NicoleDocuments/Melanie%20Martinez%20June%207%202023/");
assert!(!fixed_url.contains("/remote.php/dav/files/perf3ct/remote.php/dav/files/perf3ct/"));
// Most importantly, they should be different (proving the bug was fixed)
assert_ne!(old_buggy_url, fixed_url, "The fix should produce different URLs than the buggy version");
}
// Tests for URL normalization to prevent trailing slash issues
#[tokio::test]
async fn test_nextcloud_url_normalization_with_trailing_slash() {
let config = WebDAVConfig {
server_url: "https://nas.example.com/".to_string(), // Note the trailing slash
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
// This should not panic and should normalize the URL properly
let webdav_url = config.webdav_url();
// Should not contain double slashes
assert!(!webdav_url.contains("//remote.php"), "URL should not contain double slashes: {}", webdav_url);
assert_eq!(webdav_url, "https://nas.example.com/remote.php/dav/files/testuser");
}
#[tokio::test]
async fn test_nextcloud_url_normalization_without_trailing_slash() {
let config = WebDAVConfig {
server_url: "https://nas.example.com".to_string(), // No trailing slash
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
let webdav_url = config.webdav_url();
// Should not contain double slashes
assert!(!webdav_url.contains("//remote.php"), "URL should not contain double slashes: {}", webdav_url);
assert_eq!(webdav_url, "https://nas.example.com/remote.php/dav/files/testuser");
}
#[tokio::test]
async fn test_owncloud_url_normalization_with_trailing_slash() {
let config = WebDAVConfig {
server_url: "https://cloud.example.com/".to_string(), // Note the trailing slash
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("owncloud".to_string()),
};
let webdav_url = config.webdav_url();
// Should not contain double slashes
assert!(!webdav_url.contains("//remote.php"), "URL should not contain double slashes: {}", webdav_url);
assert_eq!(webdav_url, "https://cloud.example.com/remote.php/webdav");
}
#[tokio::test]
async fn test_owncloud_url_normalization_without_trailing_slash() {
let config = WebDAVConfig {
server_url: "https://cloud.example.com".to_string(), // No trailing slash
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("owncloud".to_string()),
};
let webdav_url = config.webdav_url();
// Should not contain double slashes
assert!(!webdav_url.contains("//remote.php"), "URL should not contain double slashes: {}", webdav_url);
assert_eq!(webdav_url, "https://cloud.example.com/remote.php/webdav");
}
#[tokio::test]
async fn test_generic_webdav_url_normalization_with_trailing_slash() {
let config = WebDAVConfig {
server_url: "https://webdav.example.com/".to_string(), // Note the trailing slash
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("generic".to_string()),
};
let webdav_url = config.webdav_url();
// Should normalize by removing the trailing slash
assert_eq!(webdav_url, "https://webdav.example.com");
}
#[tokio::test]
async fn test_generic_webdav_url_normalization_without_trailing_slash() {
let config = WebDAVConfig {
server_url: "https://webdav.example.com".to_string(), // No trailing slash
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("generic".to_string()),
};
let webdav_url = config.webdav_url();
// Should remain the same
assert_eq!(webdav_url, "https://webdav.example.com");
}
#[tokio::test]
async fn test_connection_get_url_for_path_normalization() {
let config = WebDAVConfig {
server_url: "https://nas.example.com/".to_string(), // Trailing slash
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
let service = WebDAVService::new(config).unwrap();
let connection = super::super::connection::WebDAVConnection::new(
service.get_config().clone(),
super::super::config::RetryConfig::default()
).unwrap();
// Test various path scenarios
let test_cases = vec![
("/remote.php/dav/files/testuser/Photos/test.jpg", "https://nas.example.com/remote.php/dav/files/testuser/remote.php/dav/files/testuser/Photos/test.jpg"),
("Photos/test.jpg", "https://nas.example.com/remote.php/dav/files/testuser/Photos/test.jpg"),
("/Photos/test.jpg", "https://nas.example.com/remote.php/dav/files/testuser/Photos/test.jpg"),
("", "https://nas.example.com/remote.php/dav/files/testuser"),
];
for (input_path, expected_url) in test_cases {
let result_url = connection.get_url_for_path(input_path);
// Ensure no double slashes in the final URL (except after protocol)
let url_without_protocol = result_url.replace("https://", "");
assert!(!url_without_protocol.contains("//"), "URL should not contain double slashes: {}", result_url);
if input_path.starts_with("/remote.php/") {
// This case would create double paths in the buggy version
// The new version should still create a proper URL even if not ideal
assert!(!result_url.contains("/remote.php/dav/files/testuser/remote.php/dav/files/testuser/remote.php/"));
}
}
}
#[tokio::test]
async fn test_url_normalization_edge_cases() {
// Test multiple trailing slashes
let config = WebDAVConfig {
server_url: "https://nas.example.com///".to_string(), // Multiple trailing slashes
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
let webdav_url = config.webdav_url();
// Should normalize all trailing slashes
assert!(!webdav_url.contains("//remote.php"), "URL should not contain double slashes: {}", webdav_url);
assert_eq!(webdav_url, "https://nas.example.com/remote.php/dav/files/testuser");
}
#[tokio::test]
async fn test_all_server_types_url_consistency() {
let server_url_variants = vec![
"https://server.example.com",
"https://server.example.com/",
"https://server.example.com//",
"https://server.example.com///",
];
let server_types = vec![
Some("nextcloud".to_string()),
Some("owncloud".to_string()),
Some("generic".to_string()),
None,
];
for server_type in &server_types {
for server_url in &server_url_variants {
let config = WebDAVConfig {
server_url: server_url.to_string(),
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: server_type.clone(),
};
let webdav_url = config.webdav_url();
// All variants should produce the same normalized URL for a given server type
let url_without_protocol = webdav_url.replace("https://", "");
assert!(!url_without_protocol.contains("//"),
"URL should not contain double slashes for server_type {:?} and url {}: {}",
server_type, server_url, webdav_url);
// Ensure the base domain is correctly preserved
assert!(webdav_url.starts_with("https://server.example.com"),
"URL should start with normalized domain: {}", webdav_url);
}
}
}
// Tests specifically for file fetching scenarios - using actual service methods
#[tokio::test]
async fn test_service_download_file_url_construction() {
let config = WebDAVConfig {
server_url: "https://nas.jonathonfuller.com/".to_string(), // Note trailing slash (user input)
username: "perf3ct".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["png".to_string(), "pdf".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
let service = WebDAVService::new(config).unwrap();
let connection = super::super::connection::WebDAVConnection::new(
service.get_config().clone(),
super::super::config::RetryConfig::default()
).unwrap();
// These are the actual paths that would come from XML parser responses
let xml_parser_paths = vec![
"/remote.php/dav/files/perf3ct/Photos/PC%20Screenshots/zjoQcWqldv.png",
"/remote.php/dav/files/perf3ct/FullerDocuments/NicoleDocuments/Melanie%20Martinez%20June%207%202023/document.pdf",
"/remote.php/dav/files/perf3ct/FullerDocuments/JonDocuments/project.pdf",
"/remote.php/dav/files/perf3ct/Documents/work/report.pdf",
];
let expected_urls = vec![
"https://nas.jonathonfuller.com/remote.php/dav/files/perf3ct/Photos/PC%20Screenshots/zjoQcWqldv.png",
"https://nas.jonathonfuller.com/remote.php/dav/files/perf3ct/FullerDocuments/NicoleDocuments/Melanie%20Martinez%20June%207%202023/document.pdf",
"https://nas.jonathonfuller.com/remote.php/dav/files/perf3ct/FullerDocuments/JonDocuments/project.pdf",
"https://nas.jonathonfuller.com/remote.php/dav/files/perf3ct/Documents/work/report.pdf",
];
for (xml_path, expected_url) in xml_parser_paths.iter().zip(expected_urls.iter()) {
// Test the conversion from full XML path to relative path (the correct approach)
let relative_path = service.convert_to_relative_path(xml_path);
let constructed_url = connection.get_url_for_path(&relative_path);
println!("XML path: {}", xml_path);
println!("Relative path: {}", relative_path);
println!("Constructed URL: {}", constructed_url);
println!("Expected URL: {}", expected_url);
// Verify no double slashes anywhere (except after protocol)
let url_without_protocol = constructed_url.replace("https://", "");
assert!(!url_without_protocol.contains("//"),
"URL should not contain double slashes: {}", constructed_url);
// Verify no double path construction
assert!(!constructed_url.contains("/remote.php/dav/files/perf3ct/remote.php/dav/files/perf3ct/"),
"URL should not contain double path construction: {}", constructed_url);
// The URL should be properly formed for file download
assert!(constructed_url.starts_with("https://nas.jonathonfuller.com/"),
"URL should start with normalized domain: {}", constructed_url);
// Should contain the file path exactly once
let path_occurrences = constructed_url.matches("/remote.php/dav/files/perf3ct/").count();
assert_eq!(path_occurrences, 1,
"Path should appear exactly once in URL: {}", constructed_url);
// Should match expected URL
assert_eq!(constructed_url, *expected_url, "URL should match expected result");
}
}
#[tokio::test]
async fn test_file_fetch_url_construction_with_convert_to_relative_path() {
// This test demonstrates the CORRECT way to handle XML parser paths
let config = WebDAVConfig {
server_url: "https://nas.example.com/".to_string(), // Trailing slash
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
let service = WebDAVService::new(config).unwrap();
let connection = super::super::connection::WebDAVConnection::new(
service.get_config().clone(),
super::super::config::RetryConfig::default()
).unwrap();
// XML parser returns this full WebDAV path
let xml_full_path = "/remote.php/dav/files/testuser/Documents/TestFolder/file.pdf";
// Method 1: Direct concatenation (the old buggy way)
let base_webdav_url = service.get_config().webdav_url();
let buggy_url = format!("{}{}", base_webdav_url, xml_full_path);
// Method 2: Using convert_to_relative_path (the correct way)
let relative_path = service.convert_to_relative_path(xml_full_path);
let correct_url = format!("{}{}", base_webdav_url, relative_path);
// Method 3: Using get_url_for_path with relative path (the correct way)
let connection_url = connection.get_url_for_path(&relative_path);
println!("XML full path: {}", xml_full_path);
println!("Base WebDAV URL: {}", base_webdav_url);
println!("Relative path: {}", relative_path);
println!("Buggy URL: {}", buggy_url);
println!("Correct URL: {}", correct_url);
println!("Connection URL: {}", connection_url);
// The buggy method creates double paths
assert!(buggy_url.contains("/remote.php/dav/files/testuser/remote.php/dav/files/testuser/"));
// The correct method doesn't
assert!(!correct_url.contains("/remote.php/dav/files/testuser/remote.php/dav/files/testuser/"));
// The connection method with relative path should work correctly
let url_without_protocol = connection_url.replace("https://", "");
assert!(!url_without_protocol.contains("//"), "Connection URL should not contain double slashes: {}", connection_url);
assert_eq!(connection_url, correct_url, "Connection URL with relative path should match correct URL");
// Expected final URL
let expected = "https://nas.example.com/remote.php/dav/files/testuser/Documents/TestFolder/file.pdf";
assert_eq!(correct_url, expected);
}
#[tokio::test]
async fn test_file_fetch_real_world_error_scenario() {
// This recreates the exact error scenario from the user's logs
let config = WebDAVConfig {
server_url: "https://nas.jonathonfuller.com/".to_string(),
username: "Alex".to_string(), // The username from the error message
password: "testpass".to_string(),
watch_folders: vec!["/Photos".to_string()],
file_extensions: vec!["png".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
let service = WebDAVService::new(config).unwrap();
let connection = super::super::connection::WebDAVConnection::new(
service.get_config().clone(),
super::super::config::RetryConfig::default()
).unwrap();
// This is the exact path from the error message
let problematic_path = "/remote.php/dav/files/Alex/Photos/PC%20Screenshots/zjoQcWqldv.png";
// Test the CORRECT approach: convert to relative path first
let relative_path = service.convert_to_relative_path(problematic_path);
let base_url = service.get_config().webdav_url();
let corrected_url = format!("{}{}", base_url, relative_path);
// Also test using connection with relative path
let connection_url = connection.get_url_for_path(&relative_path);
println!("Problematic path: {}", problematic_path);
println!("Relative path: {}", relative_path);
println!("Base URL: {}", base_url);
println!("Corrected URL: {}", corrected_url);
println!("Connection URL: {}", connection_url);
// Verify the URL is properly constructed
assert!(!corrected_url.contains("//remote.php"),
"URL should not contain //remote.php: {}", corrected_url);
assert!(!corrected_url.contains("/remote.php/dav/files/Alex/remote.php/dav/files/Alex/"),
"URL should not contain double path construction: {}", corrected_url);
// This should be the final correct URL
assert_eq!(corrected_url,
"https://nas.jonathonfuller.com/remote.php/dav/files/Alex/Photos/PC%20Screenshots/zjoQcWqldv.png");
// Connection URL should match when using relative path
assert_eq!(connection_url, corrected_url, "Connection URL should match corrected URL when using relative path");
// And it should not contain double paths
assert!(!corrected_url.contains("/remote.php/dav/files/Alex/remote.php/dav/files/Alex/"));
}
#[tokio::test]
async fn test_file_fetch_different_server_types() {
let test_cases = vec![
(
"nextcloud",
"https://cloud.example.com/",
"user1",
"/remote.php/dav/files/user1/Documents/file.pdf",
"https://cloud.example.com/remote.php/dav/files/user1/Documents/file.pdf"
),
(
"owncloud",
"https://owncloud.example.com/",
"user2",
"/remote.php/webdav/Documents/file.pdf", // ownCloud uses different path structure
"https://owncloud.example.com/remote.php/webdav/Documents/file.pdf"
),
(
"generic",
"https://webdav.example.com/",
"user3",
"/webdav/Documents/file.pdf",
"https://webdav.example.com/webdav/Documents/file.pdf"
),
];
for (server_type, server_url, username, xml_path, expected_url) in test_cases {
let config = WebDAVConfig {
server_url: server_url.to_string(),
username: username.to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some(server_type.to_string()),
};
let service = WebDAVService::new(config).unwrap();
let connection = super::super::connection::WebDAVConnection::new(
service.get_config().clone(),
super::super::config::RetryConfig::default()
).unwrap();
// Test the CORRECT approach: convert to relative path first
let relative_path = service.convert_to_relative_path(xml_path);
let download_url = connection.get_url_for_path(&relative_path);
println!("Server type: {}", server_type);
println!("XML path: {}", xml_path);
println!("Relative path: {}", relative_path);
println!("Download URL: {}", download_url);
println!("Expected: {}", expected_url);
// Verify no double slashes
let url_without_protocol = download_url.replace("https://", "");
assert!(!url_without_protocol.contains("//"),
"URL should not contain double slashes for {}: {}", server_type, download_url);
// Verify proper structure
assert!(download_url.starts_with(&format!("https://{}", server_url.trim_start_matches("https://").trim_end_matches("/"))));
// For Nextcloud and ownCloud, verify no double path construction
if server_type == "nextcloud" {
assert!(!download_url.contains(&format!("/remote.php/dav/files/{}/remote.php/dav/files/{}/", username, username)),
"Nextcloud URL should not contain double dav path: {}", download_url);
} else if server_type == "owncloud" {
assert!(!download_url.contains("/remote.php/webdav/remote.php/webdav/"),
"ownCloud URL should not contain double webdav path: {}", download_url);
}
}
}
// Test that validates we're using the actual service methods correctly
#[tokio::test]
async fn test_webdav_service_methods_use_correct_url_construction() {
let config = WebDAVConfig {
server_url: "https://nas.example.com/".to_string(), // Trailing slash
username: "testuser".to_string(),
password: "testpass".to_string(),
watch_folders: vec!["/Documents".to_string()],
file_extensions: vec!["pdf".to_string()],
timeout_seconds: 30,
server_type: Some("nextcloud".to_string()),
};
let service = WebDAVService::new(config).unwrap();
// Test paths that would come from XML parser
let xml_paths = vec![
"/remote.php/dav/files/testuser/Documents/file1.pdf",
"/remote.php/dav/files/testuser/Photos/image.png",
"/remote.php/dav/files/testuser/Work/Folder/document.pdf",
];
for xml_path in xml_paths {
// Test the convert_to_relative_path method (used by service methods)
let relative_path = service.convert_to_relative_path(xml_path);
println!("XML path: {}", xml_path);
println!("Relative path: {}", relative_path);
// Verify the relative path doesn't contain server prefixes
assert!(!relative_path.contains("/remote.php/dav/files/"),
"Relative path should not contain server prefix: {}", relative_path);
// Verify it starts with / but removes the server-specific part
assert!(relative_path.starts_with('/'), "Relative path should start with /: {}", relative_path);
// For this test, the service methods would use this relative path
// which prevents the double path construction issue
}
}
}