focus/crates/focus-tui/tests/format_tests.rs

111 lines
3.4 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 摘要与格式化辅助的测试。
//! 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));
}