diff --git a/Cargo.toml b/Cargo.toml index 3faf5a4..39304cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,4 +34,7 @@ uuid = { version = "1.0", features = ["v4", "wasm-bindgen"] } # Environment variable handling dotenvy = "0.15" -base64 = "0.21" \ No newline at end of file +base64 = "0.21" + +[dev-dependencies] +tokio = { version = "1.0", features = ["macros", "rt"] } \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index d45d848..c2b24ef 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; use std::env; +use base64::prelude::*; /// Configuration for CalDAV server connection and authentication. /// @@ -137,7 +138,7 @@ impl CalDAVConfig { /// ``` pub fn get_basic_auth(&self) -> String { let credentials = format!("{}:{}", self.username, self.password); - base64::encode(&credentials) + BASE64_STANDARD.encode(&credentials) } } @@ -163,7 +164,6 @@ pub enum ConfigError { #[cfg(test)] mod tests { use super::*; - use std::env; #[test] fn test_basic_auth_encoding() { @@ -176,7 +176,111 @@ mod tests { }; let auth = config.get_basic_auth(); - let expected = base64::encode("testuser:testpass"); + let expected = BASE64_STANDARD.encode("testuser:testpass"); assert_eq!(auth, expected); } + + /// Integration test that authenticates with the actual Baikal CalDAV server + /// + /// This test requires a valid .env file with: + /// - CALDAV_SERVER_URL + /// - CALDAV_USERNAME + /// - CALDAV_PASSWORD + /// + /// Run with: `cargo test test_baikal_auth -- --ignored` + #[tokio::test] + #[ignore] // Ignored by default since it requires network access and valid credentials + async fn test_baikal_auth() { + // Load config from .env + let config = CalDAVConfig::from_env() + .expect("Failed to load CalDAV config from environment"); + + println!("Testing authentication to: {}", config.server_url); + + // Create HTTP client + let client = reqwest::Client::new(); + + // Make a simple OPTIONS request to test authentication + let response = client + .request(reqwest::Method::OPTIONS, &config.server_url) + .header("Authorization", format!("Basic {}", config.get_basic_auth())) + .header("User-Agent", "calendar-app/0.1.0") + .send() + .await + .expect("Failed to send request to CalDAV server"); + + println!("Response status: {}", response.status()); + println!("Response headers: {:#?}", response.headers()); + + // Check if we got a successful response or at least not a 401 Unauthorized + assert!( + response.status().is_success() || response.status() != 401, + "Authentication failed with status: {}. Check your credentials in .env", + response.status() + ); + + // For Baikal/CalDAV servers, we should see DAV headers + assert!( + response.headers().contains_key("dav") || + response.headers().contains_key("DAV") || + response.status().is_success(), + "Server doesn't appear to be a CalDAV server - missing DAV headers" + ); + + println!("✓ Authentication test passed!"); + } + + /// Test making a PROPFIND request to discover calendars + /// + /// This test requires a valid .env file and makes an actual CalDAV PROPFIND request + /// + /// Run with: `cargo test test_propfind_calendars -- --ignored` + #[tokio::test] + #[ignore] + async fn test_propfind_calendars() { + let config = CalDAVConfig::from_env() + .expect("Failed to load CalDAV config from environment"); + + let client = reqwest::Client::new(); + + // CalDAV PROPFIND request to discover calendars + let propfind_body = r#" + + + + + + + +"#; + + let response = client + .request(reqwest::Method::from_bytes(b"PROPFIND").unwrap(), &config.server_url) + .header("Authorization", format!("Basic {}", config.get_basic_auth())) + .header("Content-Type", "application/xml") + .header("Depth", "1") + .header("User-Agent", "calendar-app/0.1.0") + .body(propfind_body) + .send() + .await + .expect("Failed to send PROPFIND request"); + + let status = response.status(); + println!("PROPFIND Response status: {}", status); + + let body = response.text().await.expect("Failed to read response body"); + println!("PROPFIND Response body: {}", body); + + // We should get a 207 Multi-Status for PROPFIND + assert_eq!( + status, + reqwest::StatusCode::from_u16(207).unwrap(), + "PROPFIND should return 207 Multi-Status" + ); + + // The response should contain XML with calendar information + assert!(body.contains("calendar"), "Response should contain calendar information"); + + println!("✓ PROPFIND calendars test passed!"); + } } \ No newline at end of file