142 lines
4.5 KiB
Rust
142 lines
4.5 KiB
Rust
//! 摘要与格式化辅助的测试。
|
||
//! Tests for summary & formatting helpers.
|
||
|
||
use focus_json::JsonValue;
|
||
use focus_tui::format::{
|
||
caret_position, display_width, format_duration, format_tokens, summarize_tool, truncate,
|
||
truncate_lines, wrap_text,
|
||
};
|
||
|
||
fn obj(pairs: &[(&str, JsonValue)]) -> JsonValue {
|
||
let mut o = JsonValue::obj();
|
||
for (k, v) in pairs {
|
||
o.insert(*k, v.clone()).ok();
|
||
}
|
||
o
|
||
}
|
||
|
||
#[test]
|
||
fn tool_summaries_show_concrete_content() {
|
||
// read → 路径 + 行范围。
|
||
// read → path + line range.
|
||
let args = obj(&[
|
||
("path", "src/main.rs".into()),
|
||
("startLine", 10u64.into()),
|
||
("endLine", 20u64.into()),
|
||
]);
|
||
assert_eq!(
|
||
summarize_tool("read", &args),
|
||
"read src/main.rs lines 10-20"
|
||
);
|
||
|
||
// write → 路径 + 字节数。
|
||
// write → path + byte count.
|
||
let args = obj(&[("path", "a.txt".into()), ("content", "hello world".into())]);
|
||
assert_eq!(summarize_tool("write", &args), "write a.txt (11 bytes)");
|
||
|
||
// edit → 路径 + 编辑数。
|
||
// edit → path + edit count.
|
||
let edits = JsonValue::Arr(vec![JsonValue::obj(), JsonValue::obj()]);
|
||
let args = obj(&[("path", "b.rs".into()), ("edits", edits)]);
|
||
assert_eq!(summarize_tool("edit", &args), "edit b.rs (2 edits)");
|
||
|
||
// shell → 命令(截断)。
|
||
// shell → the command (truncated).
|
||
let args = obj(&[("command", "cargo test --workspace".into())]);
|
||
assert_eq!(
|
||
summarize_tool("shell", &args),
|
||
"shell: cargo test --workspace"
|
||
);
|
||
|
||
// 未知工具 → 紧凑 JSON。
|
||
// Unknown tool → compact JSON.
|
||
let args = obj(&[("x", 1u64.into())]);
|
||
assert_eq!(summarize_tool("weird", &args), "weird {\"x\":1}");
|
||
}
|
||
|
||
#[test]
|
||
fn durations() {
|
||
assert_eq!(format_duration(0), "0ms");
|
||
assert_eq!(format_duration(450), "450ms");
|
||
assert_eq!(format_duration(12_300), "12.3s");
|
||
assert_eq!(format_duration(125_000), "2m 05s");
|
||
}
|
||
|
||
#[test]
|
||
fn token_formatting() {
|
||
assert_eq!(format_tokens(0), "0");
|
||
assert_eq!(format_tokens(999), "999");
|
||
assert_eq!(format_tokens(12_345), "12,345");
|
||
assert_eq!(format_tokens(1_000_000), "1,000,000");
|
||
}
|
||
|
||
#[test]
|
||
fn truncation() {
|
||
assert_eq!(truncate("hello", 10), "hello");
|
||
assert_eq!(truncate("hello world", 5), "hello…");
|
||
let multi = "a\nb\nc\nd\ne\nf\ng";
|
||
let out = truncate_lines(multi, 4, 100);
|
||
assert!(out.contains("truncated"), "got: {}", out);
|
||
assert!(out.contains('a'));
|
||
assert!(out.contains('g'));
|
||
}
|
||
|
||
#[test]
|
||
fn wrapping_and_width() {
|
||
assert_eq!(display_width("abc"), 3);
|
||
assert_eq!(display_width("中文"), 4);
|
||
let wrapped = wrap_text("aaaaaa", 3);
|
||
assert_eq!(wrapped, vec!["aaa".to_string(), "aaa".to_string()]);
|
||
// 保留显式换行。
|
||
// Preserve explicit newlines.
|
||
let wrapped = wrap_text("ab\ncd", 10);
|
||
assert_eq!(wrapped, vec!["ab".to_string(), "cd".to_string()]);
|
||
}
|
||
|
||
#[test]
|
||
fn caret_positioning() {
|
||
// 单行:caret 在末尾。
|
||
// Single line: caret at the end.
|
||
let (row, col, total) = caret_position("hello", 5, 10);
|
||
assert_eq!((row, col, total), (0, 5, 1));
|
||
// 换行后:caret 在第二行开头。
|
||
// After a newline: caret at the start of line 2.
|
||
let (row, col, total) = caret_position("ab\ncd", 3, 10);
|
||
assert_eq!((row, col, total), (1, 0, 2));
|
||
// 超宽行会折行。
|
||
// Over-wide lines wrap.
|
||
let (row, col, total) = caret_position("aaaaaa", 6, 3);
|
||
assert_eq!((row, col, total), (1, 3, 2));
|
||
}
|
||
|
||
#[test]
|
||
fn args_human_format_no_raw_json() {
|
||
use focus_tui::format::format_args_human;
|
||
|
||
// shell:命令按原样。
|
||
// shell: the command verbatim.
|
||
let args = obj(&[("command", "ls -la".into())]);
|
||
assert_eq!(
|
||
format_args_human(&args),
|
||
vec!["command: ls -la".to_string()]
|
||
);
|
||
|
||
// read:路径。
|
||
// read: the path.
|
||
let args = obj(&[("path", "/a/b.txt".into())]);
|
||
assert_eq!(format_args_human(&args), vec!["path: /a/b.txt".to_string()]);
|
||
|
||
// edit:多组修改以人类可读展示(非 JSON)。
|
||
// edit: multiple edits shown human-readably (not JSON).
|
||
let mut e1 = JsonValue::obj();
|
||
e1.insert("oldString", "foo".into()).ok();
|
||
e1.insert("newString", "bar".into()).ok();
|
||
let edits = JsonValue::Arr(vec![e1]);
|
||
let args = obj(&[("path", "f.txt".into()), ("edits", edits)]);
|
||
let lines = format_args_human(&args);
|
||
assert_eq!(lines[0], "path: f.txt");
|
||
assert_eq!(lines[1], "edits: 共 1 处修改");
|
||
assert!(lines[2].contains("foo"), "got {:?}", lines);
|
||
assert!(lines[2].contains("bar"), "got {:?}", lines);
|
||
}
|