mod common;
use common::TestProject;
use mecha10_cli::services::ConfigService;
use std::path::PathBuf;
#[test]
fn test_is_initialized_here() {
let project = TestProject::new().unwrap();
std::env::set_current_dir(&project.root).unwrap();
assert!(!ConfigService::is_initialized_here());
project
.create_file(
"mecha10.json",
r#"{
"robot": {"id": "test-001"},
"nodes": {"drivers": [], "custom": []},
"services": {}
}"#,
)
.unwrap();
assert!(ConfigService::is_initialized_here());
}
#[test]
fn test_is_initialized() {
let project = TestProject::new().unwrap();
assert!(!ConfigService::is_initialized(&project.root));
project
.create_file(
"mecha10.json",
r#"{
"robot": {"id": "test-001"},
"nodes": {"drivers": [], "custom": []},
"services": {}
}"#,
)
.unwrap();
assert!(ConfigService::is_initialized(&project.root));
}
#[tokio::test]
async fn test_load_default() {
let project = TestProject::new().unwrap();
std::env::set_current_dir(&project.root).unwrap();
project
.create_file(
"mecha10.json",
r#"{
"name": "test-robot",
"version": "0.1.0",
"robot": {"id": "test-robot-001"},
"nodes": {"drivers": [], "custom": []},
"services": {}
}"#,
)
.unwrap();
let config = ConfigService::load_default().await.unwrap();
assert_eq!(config.robot.id, "test-robot-001");
}
#[tokio::test]
async fn test_load_from_specific_path() {
let project = TestProject::new().unwrap();
let config_path = project
.create_file(
"custom.json",
r#"{
"name": "custom-robot",
"version": "0.1.0",
"robot": {"id": "custom-robot"},
"nodes": {"drivers": [], "custom": []},
"services": {}
}"#,
)
.unwrap();
let config = ConfigService::load_from(&config_path).await.unwrap();
assert_eq!(config.robot.id, "custom-robot");
}
#[tokio::test]
async fn test_load_from_nonexistent_file() {
let result = ConfigService::load_from(&PathBuf::from("/nonexistent/path/mecha10.json")).await;
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("not found"));
}
#[tokio::test]
async fn test_load_invalid_json() {
let project = TestProject::new().unwrap();
let config_path = project.create_file("mecha10.json", "{ invalid json ").unwrap();
let result = ConfigService::load_from(&config_path).await;
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("Failed to parse"));
}
#[tokio::test]
async fn test_load_robot_id() {
let project = TestProject::new().unwrap();
let config_path = project
.create_file(
"mecha10.json",
r#"{
"name": "robot-123",
"version": "0.1.0",
"robot": {"id": "robot-123"},
"nodes": {"drivers": [], "custom": []},
"services": {}
}"#,
)
.unwrap();
let robot_id = ConfigService::load_robot_id(&config_path).await.unwrap();
assert_eq!(robot_id, "robot-123");
}
#[test]
fn test_find_config_in_current_dir() {
let project = TestProject::new().unwrap();
project
.create_file(
"mecha10.json",
r#"{
"robot": {"id": "test"},
"nodes": {"drivers": [], "custom": []},
"services": {}
}"#,
)
.unwrap();
let found = ConfigService::find_config_from(&project.root).unwrap();
assert_eq!(found, project.root.join("mecha10.json"));
}
#[test]
fn test_find_config_in_parent_dir() {
let project = TestProject::new().unwrap();
project
.create_file(
"mecha10.json",
r#"{
"robot": {"id": "test"},
"nodes": {"drivers": [], "custom": []},
"services": {}
}"#,
)
.unwrap();
let subdir = project.root.join("subdir/nested");
std::fs::create_dir_all(&subdir).unwrap();
let found = ConfigService::find_config_from(&subdir).unwrap();
assert_eq!(found, project.root.join("mecha10.json"));
}
#[test]
fn test_find_config_not_found() {
let project = TestProject::new().unwrap();
let result = ConfigService::find_config_from(&project.root);
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("No mecha10.json found"));
}
#[test]
fn test_default_config_paths() {
let paths = ConfigService::default_config_paths();
assert!(!paths.is_empty());
assert!(paths.contains(&PathBuf::from("mecha10.json")));
}
#[tokio::test]
async fn test_try_load_from_defaults_success() {
let project = TestProject::new().unwrap();
std::env::set_current_dir(&project.root).unwrap();
project
.create_file(
"mecha10.json",
r#"{
"name": "default-robot",
"version": "0.1.0",
"robot": {"id": "default-robot"},
"nodes": {"drivers": [], "custom": []},
"services": {}
}"#,
)
.unwrap();
let (path, config) = ConfigService::try_load_from_defaults().await.unwrap();
assert_eq!(path, PathBuf::from("mecha10.json"));
assert_eq!(config.robot.id, "default-robot");
}
#[tokio::test]
async fn test_try_load_from_defaults_not_found() {
let project = TestProject::new().unwrap();
std::env::set_current_dir(&project.root).unwrap();
let result = ConfigService::try_load_from_defaults().await;
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("No valid mecha10.json found"));
}
#[test]
fn test_validate_nonexistent_file() {
let result = ConfigService::validate(&PathBuf::from("/nonexistent/mecha10.json"));
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("not found"));
}
#[tokio::test]
async fn test_config_with_services() {
let project = TestProject::new().unwrap();
let config_path = project
.create_file(
"mecha10.json",
r#"{
"name": "service-robot",
"version": "0.1.0",
"robot": {"id": "service-robot"},
"nodes": {"drivers": [], "custom": []},
"services": {
"http_api": {
"host": "0.0.0.0",
"port": 8080
},
"database": {
"url": "postgresql://localhost/test",
"max_connections": 20,
"timeout_seconds": 60
}
}
}"#,
)
.unwrap();
let config = ConfigService::load_from(&config_path).await.unwrap();
assert_eq!(config.robot.id, "service-robot");
assert!(config.services.http_api.is_some());
assert!(config.services.database.is_some());
let http_api = config.services.http_api.unwrap();
assert_eq!(http_api.host, "0.0.0.0");
assert_eq!(http_api.port, 8080);
let database = config.services.database.unwrap();
assert_eq!(database.url, "postgresql://localhost/test");
assert_eq!(database.max_connections, 20);
assert_eq!(database.timeout_seconds, 60);
}
#[tokio::test]
async fn test_config_with_nodes() {
let project = TestProject::new().unwrap();
let config_path = project
.create_file(
"mecha10.json",
r#"{
"name": "node-robot",
"version": "0.1.0",
"robot": {"id": "node-robot"},
"nodes": [
"@mecha10/camera",
"@local/custom-node"
],
"services": {}
}"#,
)
.unwrap();
let config = ConfigService::load_from(&config_path).await.unwrap();
assert_eq!(config.nodes.len(), 2);
assert!(config.nodes.contains("camera"));
assert!(config.nodes.contains("custom-node"));
}