summaryrefslogtreecommitdiff
path: root/src/integration/tests.rs
diff options
context:
space:
mode:
authorakbash <akbash@herdr.dev>2026-09-16 23:22:37 +0300
committerGitHub <noreply@github.com>2026-09-16 22:22:37 +0200
commit266d6f6d876ab3eb020b88ef6caee0f91776db37 (patch)
treed5ca72f86c30fac4211209a1d2377511e1107fc2 /src/integration/tests.rs
parent956f23ff6b72d16fe66169730b76bf565d12d449 (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.rs118
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);