use anyhow::{Context, Result, anyhow};
use cleansh::cli::SyncProfilesCommand;
use cleansh::commands::sync::run_sync_profiles_command;
use cleansh::ui::theme::{ThemeMap, ThemeStyle};
use mockito::Server;
use std::fs;
use tempfile::tempdir;
use std::sync::Mutex;
static TEST_MUTEX: Mutex<()> = Mutex::new(());
fn mock_theme_map() -> ThemeMap {
ThemeStyle::default_theme_map()
}
fn setup_test_environment() -> Result<tempfile::TempDir> {
let dir = tempdir()?;
unsafe { std::env::set_var("HOME", dir.path()); }
Ok(dir)
}
fn set_and_restore_env<F, T>(key: &str, value: &str, test_function: F) -> T
where
F: FnOnce() -> T,
{
let _guard = TEST_MUTEX.lock().unwrap();
unsafe { std::env::set_var(key, value); }
let result = test_function();
unsafe { std::env::remove_var(key); }
result
}
#[test]
fn test_sync_profiles_success() -> Result<()> {
let mut server = Server::new();
let expected_api_key = "valid-api-key";
let _m = server
.mock("GET", "/orgs/your-organization-id/profiles")
.match_header("authorization", format!("Bearer {}", expected_api_key).as_str())
.with_status(200)
.with_header("content-type", "application/x-yaml")
.with_body("profiles:\n - name: test-profile\n rules: []")
.create();
let _dir = setup_test_environment()?;
let result = set_and_restore_env("ORG_SERVER_URL", &server.url(), || {
let sync_opts = SyncProfilesCommand {
org_key: expected_api_key.to_string(),
org_id: "your-organization-id".to_string(),
};
run_sync_profiles_command(&sync_opts, &mock_theme_map())
.with_context(|| "Sync command should have succeeded")?;
let config_dir = dirs::config_dir()
.ok_or_else(|| anyhow!("Could not determine config directory for test"))?;
let profile_path = config_dir.join("cleansh").join("profiles").join("synced_profiles.yaml");
assert!(
profile_path.exists(),
"Synced profiles file should exist at: {}", profile_path.display()
);
let content = fs::read_to_string(&profile_path)?;
assert!(
content.contains("test-profile"),
"Synced profiles content is incorrect."
);
fs::remove_file(&profile_path)?;
Ok(())
});
result
}
#[test]
fn test_sync_profiles_auth_failure() -> Result<()> {
let mut server = Server::new();
let _m = server
.mock("GET", "/orgs/your-organization-id/profiles")
.with_status(401)
.create();
let _dir = setup_test_environment()?;
let result = set_and_restore_env("ORG_SERVER_URL", &server.url(), || {
let sync_opts = SyncProfilesCommand {
org_key: "invalid-api-key".to_string(),
org_id: "your-organization-id".to_string(),
};
let result = run_sync_profiles_command(&sync_opts, &mock_theme_map());
assert!(result.is_err(), "Sync command should fail with a 401 error.");
let error_message = result.as_ref().unwrap_err().to_string();
assert!(
error_message.contains("Authentication Failed (401 Unauthorized)"),
"Incorrect error message for 401."
);
let config_dir = dirs::config_dir()
.ok_or_else(|| anyhow!("Could not determine config directory for test"))?;
let profile_path = config_dir.join("cleansh").join("profiles").join("synced_profiles.yaml");
if profile_path.exists() {
fs::remove_file(&profile_path)?;
}
Ok(())
});
result
}