Files
galaxy/crates/integration/src/test/settings_file_errors.rs
T

238 lines
10 KiB
Rust

//! Integration tests for the settings file error banner.
//!
//! These tests verify that the workspace shows a warning banner when
//! `settings.toml` contains errors — either the entire file is unparsable
//! or individual setting values are invalid — and that the banner clears
//! when the file is fixed.
use std::time::Duration;
use galaxyui_core::async_assert;
use galaxyui_core::integration::TestStep;
use warp::features::FeatureFlag;
use warp::integration_testing::step::new_step_with_default_assertions;
use warp::integration_testing::terminal::wait_until_bootstrapped_single_pane_for_tab;
use warp::integration_testing::view_getters::workspace_view;
use super::{new_builder, Builder};
/// Helper: returns the path to the TOML settings file.
fn toml_file_path() -> std::path::PathBuf {
warp::settings::user_preferences_toml_file_path()
}
// ---------------------------------------------------------------------------
// Startup: whole file unparsable
// ---------------------------------------------------------------------------
/// Verifies that when `settings.toml` contains invalid TOML syntax on
/// startup, the workspace shows the settings error banner.
pub fn test_settings_error_banner_on_startup_with_invalid_toml() -> Builder {
FeatureFlag::SettingsFile.set_enabled(true);
new_builder()
.with_setup(move |_utils| {
// Write syntactically invalid TOML before the app starts.
let path = toml_file_path();
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).expect("should create config dir");
}
std::fs::write(&path, "this is [not valid toml =").expect("should write invalid TOML");
})
.with_step(
wait_until_bootstrapped_single_pane_for_tab(0).add_named_assertion(
"Settings error banner should be visible on startup",
|app, window_id| {
let workspace = workspace_view(app, window_id);
workspace.read(app, |view, _| {
async_assert!(
view.has_settings_file_error_banner(),
"Workspace should show settings error banner for unparsable TOML"
)
})
},
),
)
}
// ---------------------------------------------------------------------------
// Startup: individual invalid value
// ---------------------------------------------------------------------------
/// Verifies that when `settings.toml` contains a syntactically valid TOML
/// file but with an invalid value for a known setting, the workspace shows
/// the settings error banner.
pub fn test_settings_error_banner_on_startup_with_invalid_value() -> Builder {
FeatureFlag::SettingsFile.set_enabled(true);
new_builder()
.with_setup(move |_utils| {
// Write valid TOML with an invalid value for a bool setting.
// `font_size` expects a float; "not_a_number" will fail deserialization.
let path = toml_file_path();
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).expect("should create config dir");
}
std::fs::write(&path, "[appearance.text]\nfont_size = \"not_a_number\"\n")
.expect("should write TOML with invalid value");
})
.with_step(
wait_until_bootstrapped_single_pane_for_tab(0).add_named_assertion(
"Settings error banner should be visible for invalid value",
|app, window_id| {
let workspace = workspace_view(app, window_id);
workspace.read(app, |view, _| {
async_assert!(
view.has_settings_file_error_banner(),
"Workspace should show settings error banner for invalid setting value"
)
})
},
),
)
}
// ---------------------------------------------------------------------------
// Reload: whole file becomes unparsable
// ---------------------------------------------------------------------------
/// Verifies that when `settings.toml` becomes unparsable after a file
/// change, the settings error banner appears; and when the file is fixed,
/// the banner disappears.
pub fn test_settings_error_banner_on_reload_with_invalid_toml() -> Builder {
FeatureFlag::SettingsFile.set_enabled(true);
new_builder()
.with_setup(move |utils| {
// Use a short watcher delay so the reload fires quickly.
utils.set_env("WARP_CONFIG_WATCHER_DELAY_MS", Some("10".to_string()));
// Create a valid settings file so the watcher is already tracking
// it. The reload tests modify this file rather than creating a new
// one, which is more reliable for filesystem watchers.
let path = toml_file_path();
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).expect("should create config dir");
}
std::fs::write(&path, "# valid empty settings\n")
.expect("should write initial valid TOML");
})
.with_step(wait_until_bootstrapped_single_pane_for_tab(0))
// Step 1: No banner initially.
.with_step(
new_step_with_default_assertions("No settings error banner initially")
.add_named_assertion("Banner should not be visible", |app, window_id| {
let workspace = workspace_view(app, window_id);
workspace.read(app, |view, _| {
async_assert!(
!view.has_settings_file_error_banner(),
"Should not show settings error banner with no errors"
)
})
}),
)
// Step 2: Overwrite with invalid TOML to trigger the error banner.
.with_step(
TestStep::new("Write invalid TOML to settings file")
.set_timeout(Duration::from_secs(30))
.with_setup(|_utils| {
let path = toml_file_path();
std::fs::write(&path, "broken [toml =").expect("should write invalid TOML");
})
.add_named_assertion(
"Banner should appear after reload with invalid TOML",
|app, window_id| {
let workspace = workspace_view(app, window_id);
workspace.read(app, |view, _| {
async_assert!(
view.has_settings_file_error_banner(),
"Workspace should show settings error banner after reload"
)
})
},
),
)
// Step 3: Fix the file — banner should disappear.
.with_step(
TestStep::new("Fix the settings file")
.set_timeout(Duration::from_secs(30))
.with_setup(|_utils| {
let path = toml_file_path();
std::fs::write(&path, "# valid empty TOML\n").expect("should write valid TOML");
})
.add_named_assertion(
"Banner should disappear after file is fixed",
|app, window_id| {
let workspace = workspace_view(app, window_id);
workspace.read(app, |view, _| {
async_assert!(
!view.has_settings_file_error_banner(),
"Banner should clear when settings file is fixed"
)
})
},
),
)
}
// ---------------------------------------------------------------------------
// Reload: individual value becomes invalid
// ---------------------------------------------------------------------------
/// Verifies that when an individual setting value becomes invalid after a
/// file change, the settings error banner appears.
pub fn test_settings_error_banner_on_reload_with_invalid_value() -> Builder {
FeatureFlag::SettingsFile.set_enabled(true);
new_builder()
.with_setup(move |utils| {
utils.set_env("WARP_CONFIG_WATCHER_DELAY_MS", Some("10".to_string()));
// Create the settings file at startup so the watcher tracks it.
let path = toml_file_path();
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).expect("should create config dir");
}
std::fs::write(&path, "[appearance.text]\nfont_size = 14.0\n")
.expect("should write initial valid TOML");
})
.with_step(wait_until_bootstrapped_single_pane_for_tab(0))
// Step 1: Verify no banner with valid settings.
.with_step(
new_step_with_default_assertions("No banner with valid settings").add_named_assertion(
"No banner with valid settings",
|app, window_id| {
let workspace = workspace_view(app, window_id);
workspace.read(app, |view, _| {
async_assert!(
!view.has_settings_file_error_banner(),
"Should not show error banner with valid settings"
)
})
},
),
)
// Step 2: Change the value to something invalid.
.with_step(
TestStep::new("Write invalid setting value")
.set_timeout(Duration::from_secs(30))
.with_setup(|_utils| {
let path = toml_file_path();
std::fs::write(&path, "[appearance.text]\nfont_size = \"not_a_number\"\n")
.expect("should write invalid value");
})
.add_named_assertion(
"Banner should appear for invalid value",
|app, window_id| {
let workspace = workspace_view(app, window_id);
workspace.read(app, |view, _| {
async_assert!(
view.has_settings_file_error_banner(),
"Workspace should show error banner for invalid setting value"
)
})
},
),
)
}