use module_runtime::{ RuntimeProfileFieldError, RuntimeProfileTaskCycle, RuntimeTrackingScopeKind, build_runtime_profile_task_config_admin_upsert_input, build_runtime_tracking_daily_stat_id, }; fn build_task_scope_input( scope_kind: RuntimeTrackingScopeKind, ) -> Result { build_runtime_profile_task_config_admin_upsert_input( "admin-1".to_string(), "daily-login".to_string(), "每日登录".to_string(), "".to_string(), "daily_login".to_string(), RuntimeProfileTaskCycle::Daily, scope_kind, 1, 10, true, 10, 1_000, ) } #[test] fn admin_upsert_build_input_accepts_user_scope() { let input = build_task_scope_input(RuntimeTrackingScopeKind::User) .expect("个人任务 user scope 应允许保存"); assert_eq!(input.scope_kind, RuntimeTrackingScopeKind::User); } #[test] fn admin_upsert_build_input_rejects_non_user_scope_with_clear_message() { for scope_kind in [ RuntimeTrackingScopeKind::Site, RuntimeTrackingScopeKind::Module, RuntimeTrackingScopeKind::Work, ] { let error = build_task_scope_input(scope_kind).expect_err("非 user scope 应拒绝保存"); assert_eq!( error, RuntimeProfileFieldError::UnsupportedProfileTaskScopeKind ); assert!( error.to_string().contains("仅支持 user"), "错误信息应明确说明个人任务仅支持 user,实际为:{}", error ); } } #[test] fn tracking_daily_stat_id_keeps_work_scope_separate_from_user_scope() { let user_id = "user-1"; let work_id = "work-1"; let day_key = 20_000; let user_stat_id = build_runtime_tracking_daily_stat_id( "daily_login", RuntimeTrackingScopeKind::User, user_id, day_key, ); let work_stat_id = build_runtime_tracking_daily_stat_id( "daily_login", RuntimeTrackingScopeKind::Work, work_id, day_key, ); let invalid_work_with_user_id_stat_id = build_runtime_tracking_daily_stat_id( "daily_login", RuntimeTrackingScopeKind::Work, user_id, day_key, ); // 中文注释:Work 维度必须保留独立 scope_kind,不允许被静默当作 user_id 查询用户桶。 assert!(user_stat_id.contains(":user:user-1:")); assert!(work_stat_id.contains(":work:work-1:")); assert_ne!(user_stat_id, invalid_work_with_user_id_stat_id); }