Add CalDAV integration tests with Baikal server

- Updated base64 usage to new API (BASE64_STANDARD.encode)
- Added tokio dev dependency for async testing
- Created comprehensive integration tests:
  - test_baikal_auth: Tests authentication with OPTIONS request
  - test_propfind_calendars: Tests calendar discovery with PROPFIND
- Tests validate:
  - HTTP Basic Auth with .env credentials
  - DAV server capabilities detection
  - CalDAV PROPFIND XML responses
  - 207 Multi-Status handling
- Both tests pass successfully against Baikal server
- Tests marked as #[ignore] for CI/network isolation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Connor Johnstone
2025-08-28 15:18:43 -04:00
parent 01411f76c4
commit 103c380098
2 changed files with 111 additions and 4 deletions

View File

@@ -34,4 +34,7 @@ uuid = { version = "1.0", features = ["v4", "wasm-bindgen"] }
# Environment variable handling
dotenvy = "0.15"
base64 = "0.21"
base64 = "0.21"
[dev-dependencies]
tokio = { version = "1.0", features = ["macros", "rt"] }

View File

@@ -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#"<?xml version="1.0" encoding="utf-8" ?>
<d:propfind xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
<d:prop>
<d:resourcetype />
<d:displayname />
<c:calendar-description />
<c:supported-calendar-component-set />
</d:prop>
</d:propfind>"#;
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!");
}
}