diff options
| author | akbash <akbash@herdr.dev> | 2026-09-16 23:22:37 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-16 22:22:37 +0200 |
| commit | 266d6f6d876ab3eb020b88ef6caee0f91776db37 (patch) | |
| tree | d5ca72f86c30fac4211209a1d2377511e1107fc2 /src/integration/tests.rs | |
| parent | 956f23ff6b72d16fe66169730b76bf565d12d449 (diff) | |
fix: respect opencode tui.json registrations (#4250)
refs #4240
Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Diffstat (limited to 'src/integration/tests.rs')
| -rw-r--r-- | src/integration/tests.rs | 118 |
1 files changed, 115 insertions, 3 deletions
diff --git a/src/integration/tests.rs b/src/integration/tests.rs index 1a102992..f7e2154e 100644 --- a/src/integration/tests.rs +++ b/src/integration/tests.rs @@ -2326,6 +2326,69 @@ fn install_opencode_writes_server_and_tui_plugins() { let _ = fs::remove_dir_all(base); } +#[cfg(unix)] +#[test] +fn opencode_reuses_json_registration_in_symlinked_config_directory() { + let _lock = integration_env_lock(); + let base = unique_base(); + let home = base.join("home"); + let dotfiles = base.join("dotfiles"); + let dir = home.join(".config/opencode"); + fs::create_dir_all(home.join(".config")).unwrap(); + fs::create_dir_all(&dotfiles).unwrap(); + std::os::unix::fs::symlink(&dotfiles, &dir).unwrap(); + std::env::set_var("HOME", &home); + let json_path = dir.join("tui.json"); + let original = "{\n // User preferences\n \"theme\":\"system\",\n \"plugin\":[\"other\",[\"./herdr-tui-session.js\",{\"enabled\":true}]]\n}\n"; + fs::write(&json_path, original).unwrap(); + + for _ in 0..2 { + let installed = install_opencode().unwrap(); + assert_eq!(installed.tui_config_path, json_path); + assert!(installed.cli_config_path.is_none()); + assert!(!dir.join("tui.jsonc").exists()); + assert_eq!(fs::read_to_string(&json_path).unwrap(), original); + assert_eq!( + integration_status_at( + crate::api::schema::IntegrationTarget::Opencode, + installed.plugin_path, + OPENCODE_INTEGRATION_VERSION, + ) + .state, + IntegrationStatusKind::Current + ); + } + + // Older installs may have registered the same plugin in both files. + let jsonc_path = dir.join("tui.jsonc"); + fs::write( + &jsonc_path, + r#"{"plugin":["./herdr-tui-session.js","another"]}"#, + ) + .unwrap(); + assert_eq!(install_opencode().unwrap().tui_config_path, jsonc_path); + let result = uninstall_opencode().unwrap(); + assert_eq!( + result.updated_tui_configs, + vec![jsonc_path.clone(), json_path.clone()] + ); + let json = fs::read_to_string(&json_path).unwrap(); + assert!(json.contains("// User preferences")); + assert!(!json.contains("herdr-tui-session.js")); + assert!(json.contains("\"other\"")); + assert!(json.contains("\"system\"")); + assert_eq!( + serde_json::from_str::<Value>(&fs::read_to_string(jsonc_path).unwrap()).unwrap(), + json!({"plugin":["another"]}) + ); + assert!(uninstall_opencode().unwrap().updated_tui_configs.is_empty()); + assert_eq!(fs::read_link(&dir).unwrap(), dotfiles); + assert!(!result.plugin_path.exists()); + assert!(!result.tui_plugin_path.exists()); + std::env::remove_var("HOME"); + fs::remove_dir_all(base).unwrap(); +} + #[test] fn opencode_install_defers_v2_registration_while_migration_pending() { let _lock = integration_env_lock(); @@ -2427,6 +2490,42 @@ fn opencode_hard_link_rejection_precedes_install_and_uninstall_asset_changes() { fs::remove_dir_all(base).unwrap(); } +#[test] +fn opencode_json_config_validation_precedes_asset_changes() { + let _lock = integration_env_lock(); + let base = unique_base(); + let home = base.join("home"); + let dir = home.join(".config/opencode"); + fs::create_dir_all(dir.join("plugins")).unwrap(); + std::env::set_var("HOME", &home); + let plugin = dir.join("plugins").join(OPENCODE_PLUGIN_INSTALL_NAME); + fs::write(&plugin, "previous integration").unwrap(); + let config = dir.join("tui.json"); + fs::write(&config, r#"{"plugin":{}}"#).unwrap(); + assert!(install_opencode() + .unwrap_err() + .to_string() + .contains("plugin list")); + assert_eq!(fs::read_to_string(&plugin).unwrap(), "previous integration"); + let original = r#"{"plugin":["./herdr-tui-session.js"]}"#; + fs::write(&config, original).unwrap(); + let alias = base.join("linked-config"); + fs::hard_link(&config, &alias).unwrap(); + for error in [ + install_opencode().unwrap_err(), + uninstall_opencode().unwrap_err(), + ] { + assert!(error.to_string().contains("multiple hard links")); + assert!(error.to_string().contains("tui.json")); + } + assert_eq!(fs::read_to_string(&plugin).unwrap(), "previous integration"); + assert_eq!(fs::read_to_string(&alias).unwrap(), original); + assert!(!dir.join("tui.jsonc").exists()); + assert!(!dir.join(OPENCODE_TUI_PLUGIN_INSTALL_NAME).exists()); + std::env::remove_var("HOME"); + fs::remove_dir_all(base).unwrap(); +} + #[cfg(windows)] #[test] fn opencode_recovery_copy_blocks_retry_before_parsing_or_asset_changes() { @@ -2539,12 +2638,15 @@ fn uninstall_opencode_removes_plugins_and_managed_tui_config_entry() { assert!(result.removed_plugin); assert!(result.removed_tui_plugin); - assert!(result.updated_tui_config); + assert_eq!( + result.updated_tui_configs, + vec![installed.tui_config_path.clone()] + ); assert!(!result.plugin_path.exists()); assert!(!result.tui_plugin_path.exists()); - assert!(result.tui_config_path.exists()); + assert!(installed.tui_config_path.exists()); let tui_config: Value = - serde_json::from_str(&fs::read_to_string(&result.tui_config_path).unwrap()).unwrap(); + serde_json::from_str(&fs::read_to_string(&installed.tui_config_path).unwrap()).unwrap(); assert_eq!(tui_config, json!({})); assert_eq!(installed.plugin_path, result.plugin_path); @@ -2588,6 +2690,12 @@ fn uninstall_opencode_removes_plugins_when_tui_config_is_invalid() { fs::write(&plugin_path, OPENCODE_PLUGIN_ASSET).unwrap(); fs::write(&tui_plugin_path, OPENCODE_TUI_PLUGIN_ASSET).unwrap(); fs::write(opencode_dir.join("tui.jsonc"), "{\"plugin\":").unwrap(); + let json_path = opencode_dir.join("tui.json"); + fs::write( + &json_path, + r#"{"plugin":["./herdr-tui-session.js","other"]}"#, + ) + .unwrap(); std::env::set_var("HOME", &home); let err = uninstall_opencode().unwrap_err().to_string(); @@ -2595,6 +2703,10 @@ fn uninstall_opencode_removes_plugins_when_tui_config_is_invalid() { assert!(err.contains("failed to parse OpenCode TUI config")); assert!(!plugin_path.exists()); assert!(!tui_plugin_path.exists()); + assert_eq!( + serde_json::from_str::<Value>(&fs::read_to_string(json_path).unwrap()).unwrap(), + json!({"plugin":["other"]}) + ); std::env::remove_var("HOME"); let _ = fs::remove_dir_all(base); |
