Files
codex/codex-rs/tui/src/local_settings_tests.rs
T
Eric Traut 9d57be71ba Separate TUI preferences from server configuration (#42202)
## Why

TUI preferences and persistence paths belong to the local client, while thread
configuration and account requirements may come from the active app server.
Keeping both in the same resolved `Config` can replace live local preferences
when a thread is resumed, forked, reconnected, or switched.

## What changed

- Add `LocalSettings` as the TUI-owned source for UI, history, notice, and local
  persistence settings, and preserve it across session lifecycle transitions.
- Write preference changes to the selected user config file and reload local
  settings from disk when changing roots.
- Use the app server's account response for authentication-dependent onboarding
  and status UI instead of the local model-provider configuration.
- Retain platform family and OS metadata reported by remote app servers.

## Testing

- Cover local setting defaults, overrides, persistence destinations, reloads,
  and preservation across widget replacement and root switching.
- Cover remote platform metadata and server-controlled authentication UI.

GitOrigin-RevId: dbc2965fb1d6cbecb3f973f6133f3dcd4467b753
2026-09-02 04:20:38 +00:00

107 lines
3.7 KiB
Rust

use super::*;
use crate::legacy_core::config::ConfigBuilder;
use crate::legacy_core::config::edit::ConfigEditsBuilder;
use codex_config::LoaderOverrides;
use codex_config::types::SessionPickerViewMode;
use pretty_assertions::assert_eq;
#[tokio::test]
async fn local_load_preserves_defaults_and_resolved_overrides() -> anyhow::Result<()> {
for config_text in [
"",
r#"
[tui]
animations = false
show_tooltips = false
auto_recap = false
vim_mode_default = true
terminal_resize_reflow_max_rows = 0
session_picker_view = "comfortable"
[history]
persistence = "none"
max_bytes = 4096
[notice]
fast_default_opt_out = true
"#,
] {
let home = tempfile::tempdir()?;
std::fs::write(home.path().join("config.toml"), config_text)?;
let config = ConfigBuilder::default()
.codex_home(home.path().to_path_buf())
.loader_overrides(LoaderOverrides {
ignore_project_config: true,
..LoaderOverrides::without_managed_config_for_tests()
})
.cli_overrides(vec![("tui.disable_paste_burst".into(), true.into())])
.build()
.await?;
let local = LocalSettings::from(&config);
let mut expected: Tui = toml::from_str("")?;
expected.disable_paste_burst = Some(true);
expected.session_picker_view = Some(SessionPickerViewMode::Dense);
if !config_text.is_empty() {
expected.animations = false;
expected.show_tooltips = false;
expected.auto_recap = false;
expected.vim_mode_default = true;
expected.terminal_resize_reflow_max_rows = Some(0);
expected.session_picker_view = Some(SessionPickerViewMode::Comfortable);
}
assert_eq!(local.tui, expected);
assert_eq!(
local.terminal_resize_reflow(),
config.terminal_resize_reflow
);
assert_eq!(
(&local.history, &local.notices),
(&config.history, &config.notices)
);
}
Ok(())
}
#[tokio::test]
async fn local_writes_preserve_selected_user_file_and_home_destinations() -> anyhow::Result<()> {
let home = tempfile::tempdir()?;
let selected = AbsolutePathBuf::from_absolute_path(home.path().join("work.config.toml"))?;
std::fs::write(&selected, "[tui]\ntheme = \"dracula\"\n")?;
let overrides = LoaderOverrides {
user_config_path: Some(selected.clone()),
user_config_profile: Some("work".parse()?),
ignore_project_config: true,
..LoaderOverrides::without_managed_config_for_tests()
};
let config = ConfigBuilder::default()
.codex_home(home.path().to_path_buf())
.loader_overrides(overrides.clone())
.build()
.await?;
let local = LocalSettings::from(&config);
assert_eq!(local.user_config_path, selected);
ConfigEditsBuilder::for_config_path(local.user_config_path.as_path())
.with_edits([crate::legacy_core::config::edit::syntax_theme_edit("nord")])
.apply()
.await?;
ConfigEditsBuilder::new(local.codex_home.as_path())
.set_session_picker_view(SessionPickerViewMode::Comfortable)
.apply()
.await?;
let reloaded = ConfigBuilder::default()
.codex_home(home.path().to_path_buf())
.loader_overrides(overrides)
.build()
.await?;
assert_eq!(
LocalSettings::from(&reloaded).tui.theme.as_deref(),
Some("nord")
);
let home_config: toml::Value =
toml::from_str(&std::fs::read_to_string(home.path().join("config.toml"))?)?;
assert_eq!(
home_config["tui"]["session_picker_view"].as_str(),
Some("comfortable")
);
assert_eq!(home_config["tui"].get("theme"), None);
Ok(())
}