mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-03-29 07:09:50 +08:00
* feat(db): add pricing config fields to proxy_config table - Add default_cost_multiplier field per app type - Add pricing_model_source field (request/response) - Add request_model field to proxy_request_logs table - Implement schema migration v5 * feat(api): add pricing config commands and provider meta fields - Add get/set commands for default cost multiplier - Add get/set commands for pricing model source - Extend ProviderMeta with cost_multiplier and pricing_model_source - Register new commands in Tauri invoke handler * fix(proxy): apply cost multiplier to total cost only - Move multiplier calculation from per-item to total cost - Add resolve_pricing_config for provider-level override - Include request_model and cost_multiplier in usage logs - Return new fields in get_request_logs API * feat(ui): add pricing config UI and usage log enhancements - Add pricing config section to provider advanced settings - Refactor PricingConfigPanel to compact table layout - Display all three apps (Claude/Codex/Gemini) in one view - Add multiplier column and request model display to logs - Add frontend API wrappers for pricing config * feat(i18n): add pricing config translations - Add zh/en/ja translations for pricing defaults config - Add translations for multiplier, requestModel, responseModel - Add provider pricing config translations * fix(pricing): align backfill cost calculation with real-time logic - Fix backfill to deduct cache_read_tokens from input (avoid double billing) - Apply multiplier only to total cost, not to each item - Add multiplier display in request detail panel with i18n support - Use AppError::localized for backend error messages - Fix init_proxy_config_rows to use per-app default values - Fix silent failure in set_default_cost_multiplier/set_pricing_model_source - Add clippy allow annotation for test mutex across await * style: format code with cargo fmt and prettier * fix(tests): correct error type assertions in proxy DAO tests The tests expected AppError::InvalidInput but the DAO functions use AppError::localized() which returns AppError::Localized variant. Updated assertions to match the correct error type with key validation. --------- Co-authored-by: Jason <farion1231@gmail.com>
79 lines
2.8 KiB
Rust
79 lines
2.8 KiB
Rust
use cc_switch_lib::{
|
||
get_default_cost_multiplier_test_hook, get_pricing_model_source_test_hook,
|
||
set_default_cost_multiplier_test_hook, set_pricing_model_source_test_hook, AppError,
|
||
};
|
||
|
||
#[path = "support.rs"]
|
||
mod support;
|
||
use support::{create_test_state, ensure_test_home, reset_test_fs, test_mutex};
|
||
|
||
// 测试使用 Mutex 进行串行化,跨 await 持锁是预期行为
|
||
#[allow(clippy::await_holding_lock)]
|
||
#[tokio::test]
|
||
async fn default_cost_multiplier_commands_round_trip() {
|
||
let _guard = test_mutex().lock().expect("acquire test mutex");
|
||
reset_test_fs();
|
||
let _home = ensure_test_home();
|
||
|
||
let state = create_test_state().expect("create test state");
|
||
|
||
let default = get_default_cost_multiplier_test_hook(&state, "claude")
|
||
.await
|
||
.expect("read default multiplier");
|
||
assert_eq!(default, "1");
|
||
|
||
set_default_cost_multiplier_test_hook(&state, "claude", "1.5")
|
||
.await
|
||
.expect("set multiplier");
|
||
let updated = get_default_cost_multiplier_test_hook(&state, "claude")
|
||
.await
|
||
.expect("read updated multiplier");
|
||
assert_eq!(updated, "1.5");
|
||
|
||
let err = set_default_cost_multiplier_test_hook(&state, "claude", "not-a-number")
|
||
.await
|
||
.expect_err("invalid multiplier should error");
|
||
// 错误已改为 Localized 类型(支持 i18n)
|
||
match err {
|
||
AppError::Localized { key, .. } => {
|
||
assert_eq!(key, "error.invalidMultiplier");
|
||
}
|
||
other => panic!("expected localized error, got {other:?}"),
|
||
}
|
||
}
|
||
|
||
// 测试使用 Mutex 进行串行化,跨 await 持锁是预期行为
|
||
#[allow(clippy::await_holding_lock)]
|
||
#[tokio::test]
|
||
async fn pricing_model_source_commands_round_trip() {
|
||
let _guard = test_mutex().lock().expect("acquire test mutex");
|
||
reset_test_fs();
|
||
let _home = ensure_test_home();
|
||
|
||
let state = create_test_state().expect("create test state");
|
||
|
||
let default = get_pricing_model_source_test_hook(&state, "claude")
|
||
.await
|
||
.expect("read default pricing model source");
|
||
assert_eq!(default, "response");
|
||
|
||
set_pricing_model_source_test_hook(&state, "claude", "request")
|
||
.await
|
||
.expect("set pricing model source");
|
||
let updated = get_pricing_model_source_test_hook(&state, "claude")
|
||
.await
|
||
.expect("read updated pricing model source");
|
||
assert_eq!(updated, "request");
|
||
|
||
let err = set_pricing_model_source_test_hook(&state, "claude", "invalid")
|
||
.await
|
||
.expect_err("invalid pricing model source should error");
|
||
// 错误已改为 Localized 类型(支持 i18n)
|
||
match err {
|
||
AppError::Localized { key, .. } => {
|
||
assert_eq!(key, "error.invalidPricingMode");
|
||
}
|
||
other => panic!("expected localized error, got {other:?}"),
|
||
}
|
||
}
|