use cloudflare_dns::config::Config;
use std::fs;
use std::io::Write;
use std::path::{Component, PathBuf};
fn setup_config_file(config_dir: &std::path::Path, content: &str) -> PathBuf {
fs::create_dir_all(config_dir).expect("Failed to create config dir");
let config_path = config_dir.join("config.yaml");
let mut file = fs::File::create(&config_path).expect("Failed to create config file");
file.write_all(content.as_bytes())
.expect("Failed to write config");
config_path
}
#[test]
fn test_config_yaml_valid_single_line() {
let temp_dir = tempfile::TempDir::new().expect("Failed to create temp dir");
let config_dir = temp_dir.path().join("config_single");
let content = r#"cloudflare:
api_token: token_abc123
zone_id: zone_xyz789
"#;
setup_config_file(&config_dir, content);
let parsed: Result<serde_yaml::Value, _> = serde_yaml::from_str(content);
assert!(parsed.is_ok());
let value = parsed.unwrap();
assert_eq!(value["cloudflare"]["api_token"], "token_abc123");
assert_eq!(value["cloudflare"]["zone_id"], "zone_xyz789");
}
#[test]
fn test_config_yaml_valid_with_comments() {
let content = r#"# Cloudflare DNS Manager Configuration
cloudflare:
# Your Cloudflare API token
api_token: my-api-token-here
# The zone ID for your domain
zone_id: my-zone-id-here
"#;
let parsed: Result<serde_yaml::Value, _> = serde_yaml::from_str(content);
assert!(parsed.is_ok());
let value = parsed.unwrap();
assert_eq!(value["cloudflare"]["api_token"], "my-api-token-here");
assert_eq!(value["cloudflare"]["zone_id"], "my-zone-id-here");
}
#[test]
fn test_config_yaml_invalid_missing_cloudflare_key() {
let content = r#"api_token: token_abc
zone_id: zone_xyz
"#;
let parsed: Result<cloudflare_dns::config::Config, _> = serde_yaml::from_str(content);
assert!(parsed.is_err());
}
#[test]
fn test_config_yaml_invalid_malformed() {
let content = "this: is: not: valid: yaml: [";
let parsed: Result<serde_yaml::Value, _> = serde_yaml::from_str(content);
assert!(parsed.is_err());
}
#[test]
#[serial_test::serial(env_test)]
fn test_config_from_env_both_set() {
unsafe {
std::env::set_var("CLOUDFLARE_API_TOKEN", "env_token_123");
std::env::set_var("CLOUDFLARE_ZONE_ID", "env_zone_456");
}
let config = Config::load_from_env().expect("Should load from env");
assert_eq!(config.cloudflare_api_token, "env_token_123");
assert_eq!(config.cloudflare_zone_id, "env_zone_456");
unsafe {
std::env::remove_var("CLOUDFLARE_API_TOKEN");
std::env::remove_var("CLOUDFLARE_ZONE_ID");
}
}
#[test]
#[serial_test::serial(env_test)]
fn test_config_from_env_empty_token() {
unsafe {
std::env::set_var("CLOUDFLARE_ZONE_ID", "env_zone_456");
std::env::remove_var("CLOUDFLARE_API_TOKEN");
}
let result = Config::load_from_env();
assert!(result.is_err());
unsafe {
std::env::remove_var("CLOUDFLARE_ZONE_ID");
}
}
#[test]
#[serial_test::serial(env_test)]
fn test_config_from_env_empty_zone() {
unsafe {
std::env::set_var("CLOUDFLARE_API_TOKEN", "env_token_123");
std::env::remove_var("CLOUDFLARE_ZONE_ID");
}
let result = Config::load_from_env();
assert!(result.is_err());
unsafe {
std::env::remove_var("CLOUDFLARE_API_TOKEN");
}
}
#[test]
#[serial_test::serial(env_test)]
fn test_config_from_env_neither_set() {
unsafe {
std::env::remove_var("CLOUDFLARE_API_TOKEN");
std::env::remove_var("CLOUDFLARE_ZONE_ID");
}
let result = Config::load_from_env();
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(err.contains("CLOUDFLARE_API_TOKEN"));
}
#[test]
fn test_config_path_is_in_home_directory() {
let config_path = Config::config_path();
let home = dirs::home_dir().expect("Should have home directory");
assert!(config_path.starts_with(&home));
assert!(config_path.ends_with(".config/cloudflaredns/config.yaml"));
}
#[test]
fn test_config_path_components() {
let config_path = Config::config_path();
let components: Vec<Component<'_>> = config_path.components().collect();
assert!(components.iter().any(|c| c.as_os_str() == ".config"));
assert!(components.iter().any(|c| c.as_os_str() == "cloudflaredns"));
assert!(components.iter().any(|c| c.as_os_str() == "config.yaml"));
}
#[test]
fn test_config_struct_fields_accessible() {
let config = Config {
cloudflare_api_token: "test_token".to_string(),
cloudflare_zone_id: "test_zone".to_string(),
};
assert_eq!(config.cloudflare_api_token, "test_token");
assert_eq!(config.cloudflare_zone_id, "test_zone");
}
#[test]
fn test_config_debug_format() {
let config = Config {
cloudflare_api_token: "secret_token".to_string(),
cloudflare_zone_id: "zone_123".to_string(),
};
let debug_str = format!("{:?}", config);
assert!(debug_str.contains("Config"));
assert!(debug_str.contains("cloudflare_api_token"));
assert!(debug_str.contains("cloudflare_zone_id"));
}