Files
cc-switch/src-tauri/tests/support.rs
T
Jason 7097a0d710 fix: replace implicit app inference with explicit selection for Skills import and sync
Skills import previously inferred app enablement from filesystem presence,
causing incorrect multi-app activation when the same skill directory existed
under multiple app paths. Now the frontend submits explicit app selections
via ImportSkillSelection, and schema migration preserves a snapshot of
legacy app mappings to avoid lossy reconstruction.

Also adds reconciliation to sync_to_app (removes disabled/orphaned symlinks)
and MCP sync_all_enabled (removes disabled servers from live config).
2026-03-14 23:41:36 +08:00

79 lines
2.6 KiB
Rust

use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex, OnceLock};
use cc_switch_lib::{
update_settings, AppSettings, AppState, Database, MultiAppConfig, ProxyService,
};
/// 为测试设置隔离的 HOME 目录,避免污染真实用户数据。
pub fn ensure_test_home() -> &'static Path {
static HOME: OnceLock<PathBuf> = OnceLock::new();
HOME.get_or_init(|| {
let base = std::env::temp_dir().join("cc-switch-test-home");
if base.exists() {
let _ = std::fs::remove_dir_all(&base);
}
std::fs::create_dir_all(&base).expect("create test home");
// Windows 上 `dirs::home_dir()` 不受 HOME/USERPROFILE 影响(走 Known Folder API),
// 用 CC_SWITCH_TEST_HOME 显式覆盖,以确保测试不会污染真实用户目录。
std::env::set_var("CC_SWITCH_TEST_HOME", &base);
std::env::set_var("HOME", &base);
#[cfg(windows)]
std::env::set_var("USERPROFILE", &base);
base
})
.as_path()
}
/// 清理测试目录中生成的配置文件与缓存。
pub fn reset_test_fs() {
let home = ensure_test_home();
for sub in [
".claude",
".codex",
".cc-switch",
".gemini",
".config",
".openclaw",
] {
let path = home.join(sub);
if path.exists() {
if let Err(err) = std::fs::remove_dir_all(&path) {
eprintln!("failed to clean {}: {}", path.display(), err);
}
}
}
let claude_json = home.join(".claude.json");
if claude_json.exists() {
let _ = std::fs::remove_file(&claude_json);
}
// 重置内存中的设置缓存,确保测试环境不受上一次调用影响
let _ = update_settings(AppSettings::default());
}
/// 全局互斥锁,避免多测试并发写入相同的 HOME 目录。
pub fn test_mutex() -> &'static Mutex<()> {
static MUTEX: OnceLock<Mutex<()>> = OnceLock::new();
MUTEX.get_or_init(|| Mutex::new(()))
}
/// 创建测试用的 AppState,包含一个空的数据库
#[allow(dead_code)]
pub fn create_test_state() -> Result<AppState, Box<dyn std::error::Error>> {
let db = Arc::new(Database::init()?);
let proxy_service = ProxyService::new(db.clone());
Ok(AppState { db, proxy_service })
}
/// 创建测试用的 AppState,并从 MultiAppConfig 迁移数据
#[allow(dead_code)]
pub fn create_test_state_with_config(
config: &MultiAppConfig,
) -> Result<AppState, Box<dyn std::error::Error>> {
let db = Arc::new(Database::init()?);
db.migrate_from_json(config)?;
let proxy_service = ProxyService::new(db.clone());
Ok(AppState { db, proxy_service })
}