use super::helpers::{fixture_path, AftProcess};
#[test]
fn edit_symbol_with_lsp_hints_disambiguates() {
let mut aft = AftProcess::spawn();
let fixture = fixture_path("ambiguous.ts");
let dir = tempfile::tempdir().unwrap();
let target = dir.path().join("ambiguous.ts");
std::fs::copy(&fixture, &target).unwrap();
let resp = aft.send(&format!(
r#"{{"id":"cfg","command":"configure","harness":"opencode","project_root":{}}}"#,
crate::helpers::json_string(&dir.path().display())
));
assert_eq!(resp["success"], true, "configure failed: {:?}", resp);
let resp = aft.send(&format!(
r#"{{"id":"lsp-1","command":"edit_symbol","file":{},"symbol":"process","operation":"replace","content":"export function process(data: string): string {{\n return data.toLowerCase();\n}}","lsp_hints":{{"symbols":[{{"name":"process","file":{},"line":2}}]}}}}"#,
crate::helpers::json_string(&target.display()),
crate::helpers::json_string(&target.display())
));
assert_eq!(resp["success"], true, "expected success, got: {:?}", resp);
assert_eq!(resp["symbol"], "process");
aft.shutdown();
}
#[test]
fn edit_symbol_without_lsp_hints_returns_candidates() {
let mut aft = AftProcess::spawn();
let fixture = fixture_path("ambiguous.ts");
let dir = fixture.parent().unwrap().parent().unwrap();
let resp = aft.send(&format!(
r#"{{"id":"cfg","command":"configure","harness":"opencode","project_root":{}}}"#,
crate::helpers::json_string(&dir.display())
));
assert_eq!(resp["success"], true, "configure failed: {:?}", resp);
let resp = aft.send(&format!(
r#"{{"id":"no-hints","command":"edit_symbol","file":{},"symbol":"process","operation":"replace","content":"export function process(data: string): string {{\n return data.toLowerCase();\n}}"}}"#,
crate::helpers::json_string(&fixture.display())
));
assert_eq!(
resp["code"], "ambiguous_symbol",
"expected ambiguous, got: {:?}",
resp
);
assert!(
resp["candidates"].is_array(),
"expected candidates array: {:?}",
resp
);
assert!(
resp["candidates"].as_array().unwrap().len() >= 2,
"expected >= 2 candidates"
);
aft.shutdown();
}
#[test]
fn edit_symbol_with_malformed_lsp_hints_falls_back() {
let mut aft = AftProcess::spawn_with_stderr();
let fixture = fixture_path("ambiguous.ts");
let dir = fixture.parent().unwrap().parent().unwrap();
let resp = aft.send(&format!(
r#"{{"id":"cfg","command":"configure","harness":"opencode","project_root":{}}}"#,
crate::helpers::json_string(&dir.display())
));
assert_eq!(resp["success"], true, "configure failed: {:?}", resp);
let resp = aft.send(&format!(
r#"{{"id":"bad-hints","command":"edit_symbol","file":{},"symbol":"process","operation":"replace","content":"export function process(data: string): string {{\n return data.toLowerCase();\n}}","lsp_hints":{{"not_symbols":true}}}}"#,
crate::helpers::json_string(&fixture.display())
));
assert_eq!(
resp["code"], "ambiguous_symbol",
"expected ambiguous fallback, got: {:?}",
resp
);
let (status, stderr) = aft.stderr_output();
assert!(status.success());
assert!(
stderr.contains("ignoring malformed data"),
"expected malformed warning in stderr, got: {}",
stderr
);
}
#[test]
fn zoom_with_lsp_hints_disambiguates() {
let mut aft = AftProcess::spawn();
let fixture = fixture_path("ambiguous.ts");
let dir = fixture.parent().unwrap().parent().unwrap();
let resp = aft.send(&format!(
r#"{{"id":"cfg","command":"configure","harness":"opencode","project_root":{}}}"#,
crate::helpers::json_string(&dir.display())
));
assert_eq!(resp["success"], true, "configure failed: {:?}", resp);
let resp = aft.send(&format!(
r#"{{"id":"zoom-lsp","command":"zoom","file":{},"symbol":"process","lsp_hints":{{"symbols":[{{"name":"process","file":{},"line":7}}]}}}}"#,
crate::helpers::json_string(&fixture.display()),
crate::helpers::json_string(&fixture.display())
));
assert_eq!(
resp["success"], true,
"expected zoom success, got: {:?}",
resp
);
assert_eq!(resp["name"], "process");
aft.shutdown();
}