#[test] fn overview_factory_preset_matches_registry_and_operator_visibility() { let order = default_admin_dashboard_widgets(); let hidden = default_hidden_dashboard_widgets(); let unique: std::collections::HashSet<&str> = order.iter().map(String::as_str).collect(); assert_eq!(unique.len(), order.len()); assert_eq!(order.len(), DASHBOARD_WIDGETS.len()); assert_eq!(order.first().map(String::as_str), Some("requests")); assert_eq!(order, DASHBOARD_DEFAULT_PRESET.dashboard_widgets); assert_eq!(hidden, DASHBOARD_DEFAULT_PRESET.dashboard_hidden_widgets); assert_eq!(default_admin_dashboard_density(), "compact"); assert_eq!(DASHBOARD_DEFAULT_PRESET.overview_samples, 600); for id in [ "backend_traffic", "backend_latency", "extra_response_latency", "wide_transform_activity", "wide_compression_activity", "cache", "backend_table", ] { assert!(order.contains(&id.to_owned()), "not registered: {id}"); assert!( !hidden.contains(&id.to_owned()), "should start visible: {id}" ); } for id in [ "bandwidth", "backend_health", "extra_process_cpu", "stream_traffic", "wide_cache_activity", "cache_outcomes", "www_status", "www_requests", "www_top_services", ] { assert!(hidden.contains(&id.to_owned()), "should start hidden: {id}"); } assert!(hidden.iter().all(|id| order.contains(id))); assert!(validate_admin_preferences(&AdminPreferences::default()).is_ok()); } #[test] fn interface_themes_include_optional_black_and_cream_without_changing_default() { let mut preferences = AdminPreferences::default(); assert_eq!(preferences.theme, "dark"); for theme in ["dark", "ultra_dark", "light", "cream"] { preferences.theme = theme.to_owned(); assert!(validate_admin_preferences(&preferences).is_ok(), "{theme}"); } preferences.theme = "sepia".to_owned(); assert!(validate_admin_preferences(&preferences).is_err()); } #[test] fn corner_style_defaults_and_rejects_unknown_presets() { let mut prefs = AdminPreferences::default(); assert_eq!(prefs.corner_style, "default"); for preset in ["default", "square", "subtle", "rounded", "extra"] { prefs.corner_style = preset.to_string(); assert!(validate_admin_preferences(&prefs).is_ok(), "{preset}"); } prefs.corner_style = "oversized".to_string(); assert!(validate_admin_preferences(&prefs).is_err()); let old_json = r#"{"theme":"ultra_dark"}"#; let old: AdminPreferences = serde_json::from_str(old_json).unwrap(); assert_eq!(old.corner_style, "default"); assert!(validate_admin_preferences(&old).is_ok()); } #[test] fn old_widget_preferences_preserve_order_opt_in_and_survive_unknown_ids() { let mut prefs = AdminPreferences::default(); prefs.dashboard_widgets = vec![ "errors".into(), "from_future_release".into(), "requests".into(), "errors".into(), ]; prefs.dashboard_hidden_widgets = vec![ "errors".into(), "from_future_release".into(), "errors".into(), ]; reconcile_dashboard_widgets(&mut prefs); assert_eq!(prefs.dashboard_widgets[0], "errors"); assert_eq!(prefs.dashboard_widgets[1], "requests"); assert!(!prefs .dashboard_widgets .contains(&"from_future_release".into())); assert!(!prefs .dashboard_hidden_widgets .contains(&"from_future_release".into())); assert_eq!( prefs .dashboard_hidden_widgets .iter() .filter(|id| *id == "errors") .count(), 1 ); assert!(prefs .dashboard_hidden_widgets .contains(&"stream_overview".into())); assert!(prefs .dashboard_hidden_widgets .contains(&"stream_backend_health".into())); assert!(prefs .dashboard_hidden_widgets .contains(&"backend_health".into())); assert!(prefs .dashboard_hidden_widgets .contains(&"backend_protocols".into())); assert!(prefs .dashboard_hidden_widgets .contains(&"backend_requests".into())); assert!(prefs .dashboard_hidden_widgets .contains(&"backend_capacity".into())); assert!(prefs .dashboard_hidden_widgets .contains(&"extra_process_cpu".into())); assert!(prefs.dashboard_widgets.contains(&"backend_table".into())); // 0.33.0 WWW cards stay opt-in when upgrading an old saved custom layout. for id in [ "www_status", "www_kind", "www_capacity", "www_methods", "www_error_rate", "www_php_requests", "www_requests", "www_latency", "www_failures", "www_traffic", "www_top_services", "www_status_trend", ] { assert!(prefs.dashboard_widgets.contains(&id.into()), "missing {id}"); assert!( prefs.dashboard_hidden_widgets.contains(&id.into()), "visible on upgrade: {id}" ); } assert!(!prefs .dashboard_hidden_widgets .contains(&"backend_table".into())); for id in [ "backend_http5xx", "backend_timeouts", "backend_network", "backend_retries", "backend_queue", "backend_rotations", ] { assert!(prefs.dashboard_hidden_widgets.contains(&id.into())); } assert!(validate_admin_preferences(&prefs).is_ok()); } #[test] fn saved_dashboard_order_and_visibility_survive_new_factory_preset() { let mut prefs: AdminPreferences = serde_json::from_str( r#"{ "dashboard_density":"normal", "dashboard_widgets":["errors","requests","backend_traffic"], "dashboard_hidden_widgets":["backend_traffic"] }"#, ) .unwrap(); reconcile_dashboard_widgets(&mut prefs); assert_eq!(prefs.dashboard_density, "normal"); assert_eq!( &prefs.dashboard_widgets[..3], &["errors", "requests", "backend_traffic"] ); assert!(!prefs .dashboard_hidden_widgets .contains(&"errors".to_owned())); assert!(!prefs .dashboard_hidden_widgets .contains(&"requests".to_owned())); assert!(prefs .dashboard_hidden_widgets .contains(&"backend_traffic".to_owned())); // WWW was absent from the saved document and is introduced only as opt-in. assert!(prefs .dashboard_hidden_widgets .contains(&"www_status".to_owned())); assert!(prefs .dashboard_hidden_widgets .contains(&"cache_outcomes".to_owned())); assert!(validate_admin_preferences(&prefs).is_ok()); } #[test] fn explicit_visible_stream_opt_in_is_not_reset_when_normalizing_saved_order() { let mut prefs = AdminPreferences::default(); prefs.dashboard_widgets = default_admin_dashboard_widgets(); prefs.dashboard_hidden_widgets.clear(); reconcile_dashboard_widgets(&mut prefs); assert!(prefs.dashboard_hidden_widgets.is_empty()); assert!(prefs.dashboard_widgets.contains(&"cache_outcomes".into())); assert_eq!(prefs.dashboard_widgets, default_admin_dashboard_widgets()); assert!(validate_admin_preferences(&prefs).is_ok()); } #[test] fn dashboard_width_preferences_preserve_legacy_and_allow_custom_grids() { let old: AdminPreferences = serde_json::from_str(r#"{"theme":"dark"}"#).unwrap(); assert!(old.dashboard_widget_sizes.is_none()); let mut prefs = AdminPreferences::default(); prefs.dashboard_widget_sizes = Some(std::collections::BTreeMap::new()); assert!(validate_admin_preferences(&prefs).is_ok()); for (id, span) in [ ("http_protocol", 4), ("http_protocol", 3), ("requests", 4), ("www_requests", 3), ("backend_table", 6), ] { prefs .dashboard_widget_sizes .as_mut() .unwrap() .insert(id.into(), span); } assert!(validate_admin_preferences(&prefs).is_ok()); let saved = serde_json::to_string(&prefs).unwrap(); let restored: AdminPreferences = serde_json::from_str(&saved).unwrap(); assert_eq!( restored.dashboard_widget_sizes, prefs.dashboard_widget_sizes ); prefs .dashboard_widget_sizes .as_mut() .unwrap() .insert("backend_table".into(), 2); assert!(validate_admin_preferences(&prefs).is_err()); prefs .dashboard_widget_sizes .as_mut() .unwrap() .insert("backend_table".into(), 12); prefs .dashboard_widget_sizes .as_mut() .unwrap() .insert("not_a_card".into(), 3); assert!(validate_admin_preferences(&prefs).is_err()); reconcile_dashboard_widgets(&mut prefs); assert!(!prefs .dashboard_widget_sizes .as_ref() .unwrap() .contains_key("not_a_card")); assert!(validate_admin_preferences(&prefs).is_ok()); }