mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
refactor(types): centralize test SettingsLayer fixture builder
Add SettingsLayer::test_default() and SettingsLayer::ensure_test_auth_methods() to fabro-types behind a "test-support" feature, then collapse the five near-identical ensure_fixture_auth_methods/default_settings/test_default_settings helpers that the dev-token gating cleanup spread across fabro-config, fabro-server, and fabro-workflow. Why: the next required SettingsLayer field would otherwise need updating in five places. With the canonical helper in fabro-types, adding a required field becomes a one-line change. The cfg(any(test, feature = "test-support")) gate keeps the helpers out of production builds. Consumer crates enable the feature via dev-dependencies. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d0b3410b28
commit
2cb6235617
11 changed files with 58 additions and 122 deletions
|
|
@ -35,3 +35,4 @@ ulid.workspace = true
|
|||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
toml.workspace = true
|
||||
fabro-types = { path = "../fabro-types", features = ["test-support"] }
|
||||
|
|
|
|||
|
|
@ -1,34 +1,19 @@
|
|||
use fabro_config::parse_settings_layer;
|
||||
use fabro_config::user::default_storage_dir;
|
||||
use fabro_types::settings::server::{
|
||||
GithubIntegrationStrategy, IpAllowEntry, ObjectStoreSettings, ServerAuthMethod,
|
||||
ServerListenSettings,
|
||||
GithubIntegrationStrategy, IpAllowEntry, ObjectStoreSettings, ServerListenSettings,
|
||||
};
|
||||
use fabro_types::settings::{InterpString, SettingsLayer};
|
||||
use fabro_util::Home;
|
||||
|
||||
fn parse(source: &str) -> SettingsLayer {
|
||||
let mut layer = parse_settings_layer(source).expect("fixture should parse");
|
||||
if layer
|
||||
.server
|
||||
.as_ref()
|
||||
.and_then(|server| server.auth.as_ref())
|
||||
.and_then(|auth| auth.methods.as_ref())
|
||||
.is_none()
|
||||
{
|
||||
let server = layer.server.get_or_insert_with(Default::default);
|
||||
let auth = server.auth.get_or_insert_with(Default::default);
|
||||
auth.methods = Some(vec![ServerAuthMethod::DevToken]);
|
||||
}
|
||||
layer.ensure_test_auth_methods();
|
||||
layer
|
||||
}
|
||||
|
||||
fn empty_settings_with_auth_methods() -> SettingsLayer {
|
||||
parse(
|
||||
r"
|
||||
_version = 1
|
||||
",
|
||||
)
|
||||
SettingsLayer::test_default()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -91,3 +91,4 @@ async-trait.workspace = true
|
|||
tokio-util.workspace = true
|
||||
fabro-sandbox = { path = "../fabro-sandbox", features = ["test-support"] }
|
||||
fabro-test = { workspace = true }
|
||||
fabro-types = { path = "../fabro-types", features = ["test-support"] }
|
||||
|
|
|
|||
|
|
@ -956,31 +956,12 @@ mod tests {
|
|||
fn server_settings_fixture(source: &str) -> SettingsLayer {
|
||||
let mut layer =
|
||||
fabro_config::parse_settings_layer(source).expect("v2 fixture should parse");
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer.ensure_test_auth_methods();
|
||||
layer
|
||||
}
|
||||
|
||||
fn ensure_fixture_auth_methods(layer: &mut SettingsLayer) {
|
||||
use fabro_types::settings::server::{ServerAuthLayer, ServerAuthMethod, ServerLayer};
|
||||
|
||||
if layer
|
||||
.server
|
||||
.as_ref()
|
||||
.and_then(|server| server.auth.as_ref())
|
||||
.and_then(|auth| auth.methods.as_ref())
|
||||
.is_some()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let server = layer.server.get_or_insert_with(ServerLayer::default);
|
||||
let auth = server.auth.get_or_insert_with(ServerAuthLayer::default);
|
||||
auth.methods = Some(vec![ServerAuthMethod::DevToken]);
|
||||
}
|
||||
|
||||
fn default_settings_fixture() -> SettingsLayer {
|
||||
let mut layer = SettingsLayer::default();
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer
|
||||
SettingsLayer::test_default()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -912,30 +912,7 @@ mod tests {
|
|||
|
||||
fn parse_settings(source: &str) -> SettingsLayer {
|
||||
let mut layer = parse_settings_layer(source).expect("v2 fixture should parse");
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer
|
||||
}
|
||||
|
||||
fn ensure_fixture_auth_methods(layer: &mut SettingsLayer) {
|
||||
use fabro_types::settings::server::{ServerAuthLayer, ServerAuthMethod, ServerLayer};
|
||||
|
||||
if layer
|
||||
.server
|
||||
.as_ref()
|
||||
.and_then(|server| server.auth.as_ref())
|
||||
.and_then(|auth| auth.methods.as_ref())
|
||||
.is_some()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let server = layer.server.get_or_insert_with(ServerLayer::default);
|
||||
let auth = server.auth.get_or_insert_with(ServerAuthLayer::default);
|
||||
auth.methods = Some(vec![ServerAuthMethod::DevToken]);
|
||||
}
|
||||
|
||||
fn default_settings() -> SettingsLayer {
|
||||
let mut layer = SettingsLayer::default();
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer.ensure_test_auth_methods();
|
||||
layer
|
||||
}
|
||||
|
||||
|
|
@ -1031,7 +1008,8 @@ enabled = false
|
|||
|
||||
#[test]
|
||||
fn resolve_bind_request_from_settings_defaults_to_socket_when_listen_is_absent() {
|
||||
let bind = resolve_bind_request_from_settings(&default_settings(), None).expect("bind");
|
||||
let bind =
|
||||
resolve_bind_request_from_settings(&SettingsLayer::test_default(), None).expect("bind");
|
||||
|
||||
assert_eq!(bind, BindRequest::Unix(Home::from_env().socket_path()));
|
||||
}
|
||||
|
|
@ -1073,7 +1051,7 @@ address = "127.0.0.1:32276"
|
|||
|
||||
#[test]
|
||||
fn resolve_bind_request_from_settings_preserves_host_only_cli_bind() {
|
||||
let settings = default_settings();
|
||||
let settings = SettingsLayer::test_default();
|
||||
|
||||
let bind = resolve_bind_request_from_settings(&settings, Some("127.0.0.1")).expect("bind");
|
||||
|
||||
|
|
|
|||
|
|
@ -63,8 +63,7 @@ use fabro_store::{
|
|||
};
|
||||
use fabro_types::settings::run::RunMode;
|
||||
use fabro_types::settings::server::{
|
||||
GithubIntegrationSettings, GithubIntegrationStrategy, ServerAuthLayer, ServerAuthMethod,
|
||||
ServerLayer,
|
||||
GithubIntegrationSettings, GithubIntegrationStrategy, ServerAuthMethod,
|
||||
};
|
||||
use fabro_types::settings::{
|
||||
InterpString, ServerSettings as ResolvedServerSettings, SettingsLayer,
|
||||
|
|
@ -2581,18 +2580,10 @@ fn default_test_app_state_config(
|
|||
}
|
||||
|
||||
fn ensure_test_auth_methods(settings: &Arc<RwLock<SettingsLayer>>) {
|
||||
let mut settings = settings.write().expect("test settings lock poisoned");
|
||||
if settings
|
||||
.server
|
||||
.as_ref()
|
||||
.and_then(|server| server.auth.as_ref())
|
||||
.and_then(|auth| auth.methods.as_ref())
|
||||
.is_none()
|
||||
{
|
||||
let server = settings.server.get_or_insert_with(ServerLayer::default);
|
||||
let auth = server.auth.get_or_insert_with(ServerAuthLayer::default);
|
||||
auth.methods = Some(vec![ServerAuthMethod::DevToken]);
|
||||
}
|
||||
settings
|
||||
.write()
|
||||
.expect("test settings lock poisoned")
|
||||
.ensure_test_auth_methods();
|
||||
}
|
||||
|
||||
pub fn create_app_state_with_store(
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ doctest = false
|
|||
[features]
|
||||
default = []
|
||||
clap = ["dep:clap"]
|
||||
test-support = []
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
|||
|
|
@ -32,3 +32,36 @@ pub struct SettingsLayer {
|
|||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub features: Option<FeaturesLayer>,
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
impl SettingsLayer {
|
||||
/// A default layer that resolves cleanly: populates `server.auth.methods`
|
||||
/// with `["dev-token"]`. Use anywhere a test needs a starter
|
||||
/// `SettingsLayer` that the strict resolver will accept.
|
||||
#[must_use]
|
||||
pub fn test_default() -> Self {
|
||||
let mut layer = Self::default();
|
||||
layer.ensure_test_auth_methods();
|
||||
layer
|
||||
}
|
||||
|
||||
/// If `server.auth.methods` is unset, populate it with `["dev-token"]`.
|
||||
/// Existing methods (set by a fixture) are preserved. Use to make a
|
||||
/// parsed-from-TOML layer resolve cleanly without overriding test intent.
|
||||
pub fn ensure_test_auth_methods(&mut self) {
|
||||
use super::server::{ServerAuthLayer, ServerAuthMethod, ServerLayer as ServerLayerTy};
|
||||
|
||||
if self
|
||||
.server
|
||||
.as_ref()
|
||||
.and_then(|server| server.auth.as_ref())
|
||||
.and_then(|auth| auth.methods.as_ref())
|
||||
.is_some()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let server = self.server.get_or_insert_with(ServerLayerTy::default);
|
||||
let auth = server.auth.get_or_insert_with(ServerAuthLayer::default);
|
||||
auth.methods = Some(vec![ServerAuthMethod::DevToken]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,3 +75,4 @@ assert_cmd = "2"
|
|||
predicates = "3"
|
||||
fabro-macros = { path = "../fabro-macros" }
|
||||
fabro-test = { workspace = true }
|
||||
fabro-types = { path = "../fabro-types", features = ["test-support"] }
|
||||
|
|
|
|||
|
|
@ -463,9 +463,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn test_default_settings() -> SettingsLayer {
|
||||
let mut layer = SettingsLayer::default();
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer
|
||||
SettingsLayer::test_default()
|
||||
}
|
||||
|
||||
fn validate_dot(dot_source: &str, settings: SettingsLayer) -> Validated {
|
||||
|
|
@ -798,7 +796,7 @@ mod tests {
|
|||
}),
|
||||
..SettingsLayer::default()
|
||||
};
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer.ensure_test_auth_methods();
|
||||
layer
|
||||
},
|
||||
cwd: dir.path().to_path_buf(),
|
||||
|
|
@ -895,7 +893,7 @@ mod tests {
|
|||
}),
|
||||
..SettingsLayer::default()
|
||||
};
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer.ensure_test_auth_methods();
|
||||
layer
|
||||
},
|
||||
cwd: dir.path().to_path_buf(),
|
||||
|
|
@ -970,27 +968,10 @@ mod tests {
|
|||
}),
|
||||
..SettingsLayer::default()
|
||||
};
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer.ensure_test_auth_methods();
|
||||
layer
|
||||
}
|
||||
|
||||
pub(super) fn ensure_fixture_auth_methods(layer: &mut SettingsLayer) {
|
||||
use fabro_types::settings::server::{ServerAuthLayer, ServerAuthMethod, ServerLayer};
|
||||
|
||||
if layer
|
||||
.server
|
||||
.as_ref()
|
||||
.and_then(|server| server.auth.as_ref())
|
||||
.and_then(|auth| auth.methods.as_ref())
|
||||
.is_some()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let server = layer.server.get_or_insert_with(ServerLayer::default);
|
||||
let auth = server.auth.get_or_insert_with(ServerAuthLayer::default);
|
||||
auth.methods = Some(vec![ServerAuthMethod::DevToken]);
|
||||
}
|
||||
|
||||
fn dry_run_with_storage(storage_dir: &Path) -> SettingsLayer {
|
||||
use fabro_types::settings::run::{RunExecutionLayer, RunLayer, RunMode};
|
||||
use fabro_types::settings::server::{ServerLayer, ServerStorageLayer};
|
||||
|
|
@ -1010,7 +991,7 @@ mod tests {
|
|||
}),
|
||||
..SettingsLayer::default()
|
||||
};
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer.ensure_test_auth_methods();
|
||||
layer
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1020,23 +1020,6 @@ mod tests {
|
|||
))
|
||||
}
|
||||
|
||||
fn ensure_fixture_auth_methods(layer: &mut SettingsLayer) {
|
||||
use fabro_types::settings::server::{ServerAuthLayer, ServerAuthMethod, ServerLayer};
|
||||
|
||||
if layer
|
||||
.server
|
||||
.as_ref()
|
||||
.and_then(|server| server.auth.as_ref())
|
||||
.and_then(|auth| auth.methods.as_ref())
|
||||
.is_some()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let server = layer.server.get_or_insert_with(ServerLayer::default);
|
||||
let auth = server.auth.get_or_insert_with(ServerAuthLayer::default);
|
||||
auth.methods = Some(vec![ServerAuthMethod::DevToken]);
|
||||
}
|
||||
|
||||
async fn persisted_workflow(dot: &str, run_dir: &Path) -> (Persisted, Arc<Database>) {
|
||||
let store = memory_store();
|
||||
let created = crate::operations::create(&store, crate::operations::CreateRunInput {
|
||||
|
|
@ -1055,7 +1038,7 @@ mod tests {
|
|||
}),
|
||||
..SettingsLayer::default()
|
||||
};
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer.ensure_test_auth_methods();
|
||||
layer
|
||||
},
|
||||
cwd: run_dir
|
||||
|
|
@ -1238,7 +1221,7 @@ mod tests {
|
|||
}),
|
||||
..SettingsLayer::default()
|
||||
};
|
||||
ensure_fixture_auth_methods(&mut layer);
|
||||
layer.ensure_test_auth_methods();
|
||||
layer
|
||||
},
|
||||
cwd: temp.path().to_path_buf(),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue