From db132d11a7056e00a56ea5c4e097c3eb12c00da5 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Thu, 23 Apr 2026 18:37:37 -0400 Subject: [PATCH] migrate cli install tests off sparse settings layers --- lib/crates/fabro-cli/src/command_context.rs | 3 +- lib/crates/fabro-cli/src/commands/install.rs | 137 +++++++++--------- lib/crates/fabro-cli/tests/it/cmd/config.rs | 16 +- .../tests/it/support/auth_harness.rs | 23 +-- lib/crates/fabro-install/src/lib.rs | 12 +- 5 files changed, 96 insertions(+), 95 deletions(-) diff --git a/lib/crates/fabro-cli/src/command_context.rs b/lib/crates/fabro-cli/src/command_context.rs index 6dbf54d6b..8be555870 100644 --- a/lib/crates/fabro-cli/src/command_context.rs +++ b/lib/crates/fabro-cli/src/command_context.rs @@ -215,7 +215,8 @@ fn resolve_command_settings(loaded_settings: LoadedSettings) -> Result { - assert_eq!( - address - .as_ref() - .map(fabro_types::settings::InterpString::as_source), - Some("127.0.0.1:32276".to_string()) - ); - } - ServerListenLayer::Unix { .. } => panic!("expected tcp listen"), - } + let cfg: toml::Value = toml::from_str(&toml_str).expect("generated config should parse"); + assert_eq!( + cfg.get("server") + .and_then(toml::Value::as_table) + .and_then(|server| server.get("listen")) + .and_then(toml::Value::as_table) + .and_then(|listen| listen.get("type")) + .and_then(toml::Value::as_str), + Some("tcp") + ); + assert_eq!( + cfg.get("server") + .and_then(toml::Value::as_table) + .and_then(|server| server.get("listen")) + .and_then(toml::Value::as_table) + .and_then(|listen| listen.get("address")) + .and_then(toml::Value::as_str), + Some("127.0.0.1:32276") + ); } #[test] fn config_toml_has_cli_target_matching_listen_address() { - use fabro_types::settings::SettingsLayer; - use fabro_types::settings::cli::CliTargetLayer; let toml_str = format_config_toml(); - let cfg: SettingsLayer = fabro_config::parse_settings_layer(&toml_str).unwrap(); - let target = cfg - .cli - .as_ref() - .and_then(|c| c.target.as_ref()) - .expect("cli.target should be set"); - match target { - CliTargetLayer::Http { url } => { - assert_eq!( - url.as_ref() - .map(fabro_types::settings::InterpString::as_source), - Some("http://127.0.0.1:32276".to_string()) - ); - } - CliTargetLayer::Unix { .. } => panic!("expected http target"), - } + let cfg: toml::Value = toml::from_str(&toml_str).expect("generated config should parse"); + assert_eq!( + cfg.get("cli") + .and_then(toml::Value::as_table) + .and_then(|cli| cli.get("target")) + .and_then(toml::Value::as_table) + .and_then(|target| target.get("type")) + .and_then(toml::Value::as_str), + Some("http") + ); + assert_eq!( + cfg.get("cli") + .and_then(toml::Value::as_table) + .and_then(|cli| cli.get("target")) + .and_then(toml::Value::as_table) + .and_then(|target| target.get("url")) + .and_then(toml::Value::as_str), + Some("http://127.0.0.1:32276") + ); } #[test] @@ -2103,13 +2093,27 @@ name = "custom" ); } - fn parse_install_settings(source: &str) -> fabro_types::settings::SettingsLayer { - fabro_config::parse_settings_layer(source).expect("install settings fixture should parse") + fn auth_methods(source: &str) -> Option> { + toml::from_str::(source) + .expect("install settings fixture should parse") + .get("server") + .and_then(toml::Value::as_table) + .and_then(|server| server.get("auth")) + .and_then(toml::Value::as_table) + .and_then(|auth| auth.get("methods")) + .and_then(toml::Value::as_array) + .map(|methods| { + methods + .iter() + .filter_map(toml::Value::as_str) + .map(str::to_string) + .collect() + }) } #[test] fn dev_token_auth_enabled_when_methods_include_dev_token() { - let settings = parse_install_settings( + let methods = auth_methods( r#" _version = 1 @@ -2117,12 +2121,12 @@ _version = 1 methods = ["dev-token"] "#, ); - assert!(fabro_config::dev_token_auth_enabled(&settings)); + assert_eq!(methods, Some(vec!["dev-token".to_string()])); } #[test] fn dev_token_auth_enabled_when_mixed_with_github() { - let settings = parse_install_settings( + let methods = auth_methods( r#" _version = 1 @@ -2130,12 +2134,15 @@ _version = 1 methods = ["dev-token", "github"] "#, ); - assert!(fabro_config::dev_token_auth_enabled(&settings)); + assert_eq!( + methods, + Some(vec!["dev-token".to_string(), "github".to_string()]) + ); } #[test] fn dev_token_auth_enabled_false_for_github_only() { - let settings = parse_install_settings( + let methods = auth_methods( r#" _version = 1 @@ -2143,19 +2150,19 @@ _version = 1 methods = ["github"] "#, ); - assert!(!fabro_config::dev_token_auth_enabled(&settings)); + assert_eq!(methods, Some(vec!["github".to_string()])); } #[test] fn dev_token_auth_enabled_false_when_methods_absent() { - let settings = parse_install_settings( + let methods = auth_methods( " _version = 1 [server.auth] ", ); - assert!(!fabro_config::dev_token_auth_enabled(&settings)); + assert_eq!(methods, None); } #[test] diff --git a/lib/crates/fabro-cli/tests/it/cmd/config.rs b/lib/crates/fabro-cli/tests/it/cmd/config.rs index d06395688..ce6f49496 100644 --- a/lib/crates/fabro-cli/tests/it/cmd/config.rs +++ b/lib/crates/fabro-cli/tests/it/cmd/config.rs @@ -5,9 +5,7 @@ use std::path::PathBuf; -use fabro_config::parse_settings_layer; use fabro_test::{fabro_snapshot, test_context}; -use fabro_types::settings::SettingsLayer; use httpmock::MockServer; use predicates::prelude::*; @@ -50,9 +48,8 @@ fn server_storage_root(settings: &serde_json::Value) -> &str { .expect("server.storage.root") } -fn server_settings_layer_fixture() -> SettingsLayer { - parse_settings_layer( - r#" +fn server_settings_toml_fixture() -> &'static str { + r#" _version = 1 [server.auth] @@ -68,15 +65,12 @@ provider = "openai" [run.inputs] server_only = "1" shared = "server" -"#, - ) - .expect("server settings fixture should parse") +"# } fn resolved_server_settings_fixture() -> serde_json::Value { - let settings = - fabro_config::ServerSettingsBuilder::from_layer(&server_settings_layer_fixture()) - .expect("server settings fixture should resolve"); + let settings = fabro_config::ServerSettingsBuilder::from_toml(server_settings_toml_fixture()) + .expect("server settings fixture should resolve"); serde_json::to_value(settings).expect("resolved settings payload should serialize") } diff --git a/lib/crates/fabro-cli/tests/it/support/auth_harness.rs b/lib/crates/fabro-cli/tests/it/support/auth_harness.rs index 110b7ab79..91bc83432 100644 --- a/lib/crates/fabro-cli/tests/it/support/auth_harness.rs +++ b/lib/crates/fabro-cli/tests/it/support/auth_harness.rs @@ -17,13 +17,13 @@ use axum::extract::{Request, State as AxumState}; use axum::middleware::{self, Next}; use axum::response::Response as AxumResponse; use chrono::{Duration as ChronoDuration, Utc}; -use fabro_config::{ServerSettingsBuilder, parse_settings_layer}; +use fabro_config::{RunLayer, ServerSettingsBuilder}; use fabro_server::auth::GithubEndpoints; use fabro_server::ip_allowlist::IpAllowlistConfig; use fabro_server::jwt_auth::resolve_auth_mode_with_lookup; use fabro_server::server::{ RouterOptions, build_router_with_options, - create_app_state_with_env_lookup_and_server_secret_env, + create_app_state_with_runtime_settings_and_env_lookup_and_server_secret_env, }; use fabro_test::{GitHubAppState, TestContext, apply_test_isolation}; use fabro_types::RunAuthMethod; @@ -71,9 +71,7 @@ impl RealAuthHarness { let (api_listener, api_base_url) = bind_listener().await; let settings = auth_settings(&api_base_url, &github_client_id, auth_methods); - let resolved = ServerSettingsBuilder::from_layer(&settings) - .expect("settings should resolve") - .server; + let resolved = settings.server.clone(); let dev_token = dev_token.map(str::to_string); let auth_mode = resolve_auth_mode_with_lookup(&resolved, |name| match name { "SESSION_SECRET" => Some(TEST_SESSION_SECRET.to_string()), @@ -95,8 +93,13 @@ impl RealAuthHarness { if let Some(token) = dev_token.clone() { secrets.insert("FABRO_DEV_TOKEN".to_string(), token); } - let state = - create_app_state_with_env_lookup_and_server_secret_env(settings, 5, |_| None, &secrets); + let state = create_app_state_with_runtime_settings_and_env_lookup_and_server_secret_env( + settings, + RunLayer::default(), + 5, + |_| None, + &secrets, + ); let github_base = github_base_url(&twin.base_url); let router = build_router_with_options( state, @@ -357,13 +360,13 @@ fn auth_settings( api_base_url: &str, github_client_id: &str, auth_methods: &[&str], -) -> fabro_types::settings::SettingsLayer { +) -> fabro_types::ServerSettings { let auth_methods = auth_methods .iter() .map(|method| format!("\"{method}\"")) .collect::>() .join(", "); - parse_settings_layer(&format!( + ServerSettingsBuilder::from_toml(&format!( r#" _version = 1 @@ -380,7 +383,7 @@ url = "{api_base_url}" client_id = "{github_client_id}" "# )) - .expect("test settings should parse") + .expect("test settings should resolve") } fn github_base_url(base_url: &str) -> fabro_http::Url { diff --git a/lib/crates/fabro-install/src/lib.rs b/lib/crates/fabro-install/src/lib.rs index 3e21fa101..84bf86cce 100644 --- a/lib/crates/fabro-install/src/lib.rs +++ b/lib/crates/fabro-install/src/lib.rs @@ -492,16 +492,12 @@ mod tests { #[test] fn config_toml_has_auth_strategies() { - use fabro_types::settings::{ServerAuthMethod, SettingsLayer}; + use fabro_types::settings::ServerAuthMethod; let toml_str = format_config_toml(); - let cfg: SettingsLayer = fabro_config::parse_settings_layer(&toml_str).unwrap(); - let auth = cfg - .server - .as_ref() - .and_then(|s| s.auth.as_ref()) - .expect("server.auth should be set"); - assert_eq!(auth.methods, Some(vec![ServerAuthMethod::DevToken])); + let cfg = + ServerSettingsBuilder::from_toml(&toml_str).expect("generated config should resolve"); + assert_eq!(cfg.server.auth.methods, vec![ServerAuthMethod::DevToken]); } #[test]