migrate cli install tests off sparse settings layers

This commit is contained in:
Bryan Helmkamp 2026-04-23 18:37:37 -04:00
parent 8f47bc9317
commit db132d11a7
No known key found for this signature in database
5 changed files with 96 additions and 95 deletions

View file

@ -215,7 +215,8 @@ fn resolve_command_settings(loaded_settings: LoadedSettings) -> Result<ResolvedC
mod tests {
use std::path::PathBuf;
use fabro_types::settings::cli::{CliLayer, CliOutputLayer, OutputFormat, OutputVerbosity};
use fabro_config::{CliLayer, CliOutputLayer};
use fabro_types::settings::cli::{OutputFormat, OutputVerbosity};
use fabro_util::printer::Printer;
use tokio::sync::OnceCell;

View file

@ -1989,16 +1989,10 @@ mod tests {
#[test]
fn config_toml_roundtrips() {
use fabro_types::settings::SettingsLayer;
let toml_str = format_config_toml();
let cfg: SettingsLayer = fabro_config::parse_settings_layer(&toml_str)
.expect("generated config should parse as v2");
let methods = cfg
.server
.as_ref()
.and_then(|s| s.auth.as_ref())
.and_then(|a| a.methods.clone())
.expect("server.auth.methods should be set");
let cfg = fabro_config::ServerSettingsBuilder::from_toml(&toml_str)
.expect("generated config should resolve");
let methods = cfg.server.auth.methods;
assert_eq!(methods, vec![
fabro_types::settings::ServerAuthMethod::DevToken
]);
@ -2006,65 +2000,61 @@ mod tests {
#[test]
fn config_toml_has_auth_strategies() {
use fabro_types::settings::SettingsLayer;
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");
let cfg = fabro_config::ServerSettingsBuilder::from_toml(&toml_str)
.expect("generated config should resolve");
assert_eq!(
auth.methods,
Some(vec![fabro_types::settings::ServerAuthMethod::DevToken])
cfg.server.auth.methods,
vec![fabro_types::settings::ServerAuthMethod::DevToken]
);
}
#[test]
fn config_toml_has_tcp_listen_address() {
use fabro_types::settings::SettingsLayer;
use fabro_types::settings::server::ServerListenLayer;
let toml_str = format_config_toml();
let cfg: SettingsLayer = fabro_config::parse_settings_layer(&toml_str).unwrap();
let listen = cfg
.server
.as_ref()
.and_then(|s| s.listen.as_ref())
.expect("server.listen should be set");
match listen {
ServerListenLayer::Tcp { address } => {
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<Vec<String>> {
toml::from_str::<toml::Value>(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]

View file

@ -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")
}

View file

@ -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::<Vec<_>>()
.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 {

View file

@ -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]