Update: 将子项目从 submodule 转为完整内容
- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用 - 添加所有子项目的完整源代码 - 保留原始 .git 为 .git.bak 备份
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
//! Black-box integration tests for IClientPreferenceRepository.
|
||||
//!
|
||||
//! Tests exercise the public trait interface against an in-memory SQLite database.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use nomifun_db::{IClientPreferenceRepository, SqliteClientPreferenceRepository, init_database_memory};
|
||||
|
||||
async fn repo() -> Arc<dyn IClientPreferenceRepository> {
|
||||
let db = init_database_memory().await.unwrap();
|
||||
Arc::new(SqliteClientPreferenceRepository::new(db.pool().clone()))
|
||||
}
|
||||
|
||||
// -- Empty state --
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_all_returns_empty_when_no_preferences() {
|
||||
let r = repo().await;
|
||||
assert!(r.get_all().await.unwrap().is_empty());
|
||||
}
|
||||
|
||||
// -- Upsert and retrieval --
|
||||
|
||||
#[tokio::test]
|
||||
async fn upsert_then_get_all_returns_inserted_entries() {
|
||||
let r = repo().await;
|
||||
r.upsert_batch(&[("theme", "\"dark\""), ("companion.size", "360")])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let prefs = r.get_all().await.unwrap();
|
||||
assert_eq!(prefs.len(), 2);
|
||||
|
||||
let keys: Vec<&str> = prefs.iter().map(|p| p.key.as_str()).collect();
|
||||
assert!(keys.contains(&"theme"));
|
||||
assert!(keys.contains(&"companion.size"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn upsert_overwrites_existing_key() {
|
||||
let r = repo().await;
|
||||
r.upsert_batch(&[("k", "v1")]).await.unwrap();
|
||||
r.upsert_batch(&[("k", "v2")]).await.unwrap();
|
||||
|
||||
let prefs = r.get_all().await.unwrap();
|
||||
assert_eq!(prefs.len(), 1);
|
||||
assert_eq!(prefs[0].value, "v2");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn upsert_empty_batch_is_noop() {
|
||||
let r = repo().await;
|
||||
r.upsert_batch(&[]).await.unwrap();
|
||||
assert!(r.get_all().await.unwrap().is_empty());
|
||||
}
|
||||
|
||||
// -- Filtered retrieval --
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_by_keys_returns_only_matching() {
|
||||
let r = repo().await;
|
||||
r.upsert_batch(&[("a", "1"), ("b", "2"), ("c", "3")]).await.unwrap();
|
||||
|
||||
let prefs = r.get_by_keys(&["a", "c"]).await.unwrap();
|
||||
assert_eq!(prefs.len(), 2);
|
||||
|
||||
let keys: Vec<&str> = prefs.iter().map(|p| p.key.as_str()).collect();
|
||||
assert!(keys.contains(&"a"));
|
||||
assert!(keys.contains(&"c"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_by_keys_omits_nonexistent() {
|
||||
let r = repo().await;
|
||||
r.upsert_batch(&[("x", "1")]).await.unwrap();
|
||||
|
||||
let prefs = r.get_by_keys(&["x", "ghost"]).await.unwrap();
|
||||
assert_eq!(prefs.len(), 1);
|
||||
assert_eq!(prefs[0].key, "x");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_by_keys_empty_input_returns_empty() {
|
||||
let r = repo().await;
|
||||
r.upsert_batch(&[("x", "1")]).await.unwrap();
|
||||
|
||||
let prefs = r.get_by_keys(&[]).await.unwrap();
|
||||
assert!(prefs.is_empty());
|
||||
}
|
||||
|
||||
// -- Deletion --
|
||||
|
||||
#[tokio::test]
|
||||
async fn delete_keys_removes_specified_entries() {
|
||||
let r = repo().await;
|
||||
r.upsert_batch(&[("a", "1"), ("b", "2"), ("c", "3")]).await.unwrap();
|
||||
|
||||
r.delete_keys(&["a", "c"]).await.unwrap();
|
||||
|
||||
let prefs = r.get_all().await.unwrap();
|
||||
assert_eq!(prefs.len(), 1);
|
||||
assert_eq!(prefs[0].key, "b");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn delete_nonexistent_keys_is_noop() {
|
||||
let r = repo().await;
|
||||
r.upsert_batch(&[("x", "1")]).await.unwrap();
|
||||
r.delete_keys(&["ghost"]).await.unwrap();
|
||||
|
||||
assert_eq!(r.get_all().await.unwrap().len(), 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn delete_empty_keys_is_noop() {
|
||||
let r = repo().await;
|
||||
r.upsert_batch(&[("x", "1")]).await.unwrap();
|
||||
r.delete_keys(&[]).await.unwrap();
|
||||
|
||||
assert_eq!(r.get_all().await.unwrap().len(), 1);
|
||||
}
|
||||
|
||||
// -- Value types --
|
||||
|
||||
#[tokio::test]
|
||||
async fn stores_boolean_number_string_json_values() {
|
||||
let r = repo().await;
|
||||
r.upsert_batch(&[
|
||||
("bool_key", "true"),
|
||||
("num_key", "42"),
|
||||
("str_key", "\"hello\""),
|
||||
("null_key", "null"),
|
||||
])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let prefs = r.get_all().await.unwrap();
|
||||
assert_eq!(prefs.len(), 4);
|
||||
|
||||
let find = |k: &str| prefs.iter().find(|p| p.key == k).unwrap().value.as_str();
|
||||
assert_eq!(find("bool_key"), "true");
|
||||
assert_eq!(find("num_key"), "42");
|
||||
assert_eq!(find("str_key"), "\"hello\"");
|
||||
assert_eq!(find("null_key"), "null");
|
||||
}
|
||||
Reference in New Issue
Block a user