re-uploading work

This commit is contained in:
2026-02-04 17:46:30 -06:00
commit 3b14c65998
1388 changed files with 381262 additions and 0 deletions

View File

@@ -0,0 +1,522 @@
//! Integration tests for CLI config and profile management commands
#![allow(deprecated)]
use assert_cmd::Command;
use predicates::prelude::*;
mod common;
use common::*;
#[tokio::test]
async fn test_config_show_default() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("list");
cmd.assert()
.success()
.stdout(predicate::str::contains("current_profile"))
.stdout(predicate::str::contains("api_url"));
}
#[tokio::test]
async fn test_config_show_json_output() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("--json")
.arg("config")
.arg("list");
cmd.assert()
.success()
.stdout(predicate::str::contains(r#""current_profile""#))
.stdout(predicate::str::contains(r#""api_url""#));
}
#[tokio::test]
async fn test_config_show_yaml_output() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("--yaml")
.arg("config")
.arg("list");
cmd.assert()
.success()
.stdout(predicate::str::contains("current_profile:"))
.stdout(predicate::str::contains("api_url:"));
}
#[tokio::test]
async fn test_config_get_specific_key() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("get")
.arg("api_url");
cmd.assert()
.success()
.stdout(predicate::str::contains(fixture.server_url()));
}
#[tokio::test]
async fn test_config_get_nonexistent_key() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("get")
.arg("nonexistent_key");
cmd.assert()
.failure()
.stderr(predicate::str::contains("Error"));
}
#[tokio::test]
async fn test_config_set_api_url() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("set")
.arg("api_url")
.arg("https://new-api.example.com");
cmd.assert()
.success()
.stdout(predicate::str::contains("Configuration updated"));
// Verify the change was persisted
let config_content =
std::fs::read_to_string(&fixture.config_path).expect("Failed to read config");
assert!(config_content.contains("https://new-api.example.com"));
}
#[tokio::test]
async fn test_config_set_output_format() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("set")
.arg("output_format")
.arg("json");
cmd.assert()
.success()
.stdout(predicate::str::contains("Configuration updated"));
// Verify the change was persisted
let config_content =
std::fs::read_to_string(&fixture.config_path).expect("Failed to read config");
assert!(config_content.contains("output_format: json"));
}
#[tokio::test]
async fn test_profile_list() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("profiles");
cmd.assert()
.success()
.stdout(predicate::str::contains("default"))
.stdout(predicate::str::contains("staging"))
.stdout(predicate::str::contains("production"));
}
#[tokio::test]
async fn test_profile_list_shows_current() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("profiles");
cmd.assert()
.success()
.stdout(predicate::str::contains("*").or(predicate::str::contains("(active)")));
}
#[tokio::test]
async fn test_profile_show_specific() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("show-profile")
.arg("staging");
cmd.assert()
.success()
.stdout(predicate::str::contains("staging.example.com"));
}
#[tokio::test]
async fn test_profile_show_nonexistent() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("show-profile")
.arg("nonexistent");
cmd.assert()
.failure()
.stderr(predicate::str::contains("Error"));
}
#[tokio::test]
async fn test_profile_add_new() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("add-profile")
.arg("testing")
.arg("--api-url")
.arg("https://test.example.com")
.arg("--description")
.arg("Testing environment");
cmd.assert()
.success()
.stdout(predicate::str::contains("Profile 'testing' added"));
// Verify the profile was added
let config_content =
std::fs::read_to_string(&fixture.config_path).expect("Failed to read config");
assert!(config_content.contains("testing:"));
assert!(config_content.contains("https://test.example.com"));
}
#[tokio::test]
async fn test_profile_add_without_description() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("add-profile")
.arg("newprofile")
.arg("--api-url")
.arg("https://new.example.com");
cmd.assert()
.success()
.stdout(predicate::str::contains("Profile 'newprofile' added"));
}
#[tokio::test]
async fn test_profile_use_switch() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("use")
.arg("staging");
cmd.assert()
.success()
.stdout(predicate::str::contains("Switched to profile 'staging'"));
// Verify the current profile was changed
let config_content =
std::fs::read_to_string(&fixture.config_path).expect("Failed to read config");
assert!(config_content.contains("current_profile: staging"));
}
#[tokio::test]
async fn test_profile_use_nonexistent() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("use")
.arg("nonexistent");
cmd.assert()
.failure()
.stderr(predicate::str::contains("does not exist"));
}
#[tokio::test]
async fn test_profile_remove() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("remove-profile")
.arg("staging");
cmd.assert()
.success()
.stdout(predicate::str::contains("Profile 'staging' removed"));
// Verify the profile was removed
let config_content =
std::fs::read_to_string(&fixture.config_path).expect("Failed to read config");
assert!(!config_content.contains("staging:"));
}
#[tokio::test]
async fn test_profile_remove_default_fails() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("remove-profile")
.arg("default");
cmd.assert()
.failure()
.stderr(predicate::str::contains("Cannot remove"));
}
#[tokio::test]
async fn test_profile_remove_active_fails() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
// Try to remove the currently active profile
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("remove-profile")
.arg("default");
cmd.assert()
.failure()
.stderr(predicate::str::contains("Cannot remove active profile"));
}
#[tokio::test]
async fn test_profile_remove_nonexistent() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("remove-profile")
.arg("nonexistent");
cmd.assert().success(); // Removing non-existent profile might be a no-op
}
#[tokio::test]
async fn test_profile_override_with_flag() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
// Use --profile flag to temporarily override
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("--profile")
.arg("staging")
.arg("config")
.arg("list");
cmd.assert().success();
// Verify current profile wasn't changed in the config file
let config_content =
std::fs::read_to_string(&fixture.config_path).expect("Failed to read config");
assert!(config_content.contains("current_profile: default"));
}
#[tokio::test]
async fn test_profile_override_with_env_var() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
// Use ATTUNE_PROFILE env var to temporarily override
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.env("ATTUNE_PROFILE", "production")
.arg("config")
.arg("list");
cmd.assert().success();
// Verify current profile wasn't changed in the config file
let config_content =
std::fs::read_to_string(&fixture.config_path).expect("Failed to read config");
assert!(config_content.contains("current_profile: default"));
}
#[tokio::test]
async fn test_profile_with_custom_output_format() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
// Switch to production which has json output format
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("use")
.arg("production");
cmd.assert().success();
// Verify the profile has custom output format
let config_content =
std::fs::read_to_string(&fixture.config_path).expect("Failed to read config");
assert!(config_content.contains("output_format: json"));
}
#[tokio::test]
async fn test_config_list_all_keys() {
let fixture = TestFixture::new().await;
fixture.write_authenticated_config("test_token", "test_refresh");
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("list");
cmd.assert()
.success()
.stdout(predicate::str::contains("api_url"))
.stdout(predicate::str::contains("output_format"))
.stdout(predicate::str::contains("auth_token"));
}
#[tokio::test]
async fn test_config_masks_sensitive_data() {
let fixture = TestFixture::new().await;
fixture.write_authenticated_config("secret_token_123", "secret_refresh_456");
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("get")
.arg("auth_token");
cmd.assert()
.success()
.stdout(predicate::str::contains("***"));
}
#[tokio::test]
async fn test_profile_add_duplicate_overwrites() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
// Add a profile with the same name as existing one
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("add-profile")
.arg("staging")
.arg("--api-url")
.arg("https://new-staging.example.com");
cmd.assert().success();
// Verify the profile was updated
let config_content =
std::fs::read_to_string(&fixture.config_path).expect("Failed to read config");
assert!(config_content.contains("https://new-staging.example.com"));
}
#[tokio::test]
async fn test_profile_list_json_output() {
let fixture = TestFixture::new().await;
fixture.write_multi_profile_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("--json")
.arg("config")
.arg("profiles");
cmd.assert()
.success()
.stdout(predicate::str::contains(r#""default""#))
.stdout(predicate::str::contains(r#""staging""#));
}
#[tokio::test]
async fn test_config_path_display() {
let fixture = TestFixture::new().await;
fixture.write_default_config();
let mut cmd = Command::cargo_bin("attune").unwrap();
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
.env("HOME", fixture.config_dir_path())
.arg("config")
.arg("path");
cmd.assert()
.success()
.stdout(predicate::str::contains("config.yaml"));
}