oauth-db-cli 0.1.0

Command-line tool for managing OAuth-DB platform
Documentation
use assert_cmd::Command;
use std::path::PathBuf;
use tempfile::TempDir;
use std::fs;

/// 测试上下文,管理测试环境
pub struct TestContext {
    pub temp_dir: TempDir,
    pub config_dir: PathBuf,
    pub server_url: String,
}

impl TestContext {
    /// 创建新的测试上下文
    pub fn new(server_url: String) -> Self {
        let temp_dir = TempDir::new().unwrap();
        // 使用与 directories crate 相同的路径结构
        let config_dir = temp_dir.path().join(".config").join("oauth-db").join("oauth-db-cli");
        fs::create_dir_all(&config_dir).unwrap();

        Self {
            temp_dir,
            config_dir,
            server_url,
        }
    }

    /// 获取配置文件路径
    pub fn config_path(&self) -> PathBuf {
        self.config_dir.join("config.toml")
    }

    /// 获取账号文件路径
    pub fn accounts_path(&self) -> PathBuf {
        self.config_dir.join("accounts.json")
    }

    /// 写入测试配置
    pub fn write_config(&self) {
        let config = format!(
            r#"
[server]
url = "{}"

[output]
format = "table"
color = true

[log]
level = "info"
"#,
            self.server_url
        );
        fs::write(self.config_path(), config).unwrap();
    }

    /// 写入测试账号(模拟已登录状态)
    pub fn write_account(&self, name: &str, token: &str) {
        self.write_account_with_default(name, token, true);
    }

    /// 写入测试账号,指定是否为默认账号
    pub fn write_account_with_default(&self, name: &str, token: &str, is_default: bool) {
        let username = name.split('@').next().unwrap_or(name);
        let config = format!(
            r#"
[server]
url = "{}"

[output]
format = "table"
color = true

[log]
level = "info"

[[accounts]]
name = "{}"
server = "{}"
username = "{}"
token = "{}"
default = {}
"#,
            self.server_url, name, self.server_url, username, token, is_default
        );
        fs::write(self.config_path(), config).unwrap();
    }

    /// 写入多个测试账号
    /// accounts: Vec<(name, token, is_default)>
    pub fn write_multiple_accounts(&self, accounts: Vec<(&str, &str, bool)>) {
        let mut config = format!(
            r#"
[server]
url = "{}"

[output]
format = "table"
color = true

[log]
level = "info"
"#,
            self.server_url
        );

        for (name, token, is_default) in accounts {
            let username = name.split('@').next().unwrap_or(name);
            config.push_str(&format!(
                r#"
[[accounts]]
name = "{}"
server = "{}"
username = "{}"
token = "{}"
default = {}
"#,
                name, self.server_url, username, token, is_default
            ));
        }

        fs::write(self.config_path(), config).unwrap();
    }

    /// 获取环境变量
    pub fn env_vars(&self) -> Vec<(&str, String)> {
        let config_home = self.temp_dir.path().join(".config");
        vec![
            ("HOME", self.temp_dir.path().to_string_lossy().to_string()),
            ("XDG_CONFIG_HOME", config_home.to_string_lossy().to_string()),
            ("OAUTH_DB_SERVER", self.server_url.clone()),
        ]
    }
}

/// 创建 CLI 命令
pub fn cli_cmd() -> Command {
    Command::cargo_bin("oauth-db").unwrap()
}

/// 设置测试环境并创建命令
pub fn setup_test_cmd(ctx: &TestContext) -> Command {
    let mut cmd = cli_cmd();
    for (key, value) in ctx.env_vars() {
        cmd.env(key, value);
    }
    cmd
}

/// 生成唯一的测试名称
pub fn unique_name(prefix: &str) -> String {
    format!("{}-{}", prefix, chrono::Utc::now().timestamp_millis())
}