test: cover Kimi schema and ANSI normalization edge cases
This commit is contained in:
@@ -618,6 +618,12 @@ mod tests {
|
||||
/// are left untouched.
|
||||
pub fn sanitize_for_kimi(schema: &mut serde_json::Value) {
|
||||
if let Some(obj) = schema.as_object_mut() {
|
||||
// Recurse first so a type injected into this object's alternatives is
|
||||
// not immediately removed again by processing that freshly-mutated item.
|
||||
for (_, v) in obj.iter_mut() {
|
||||
sanitize_for_kimi(v);
|
||||
}
|
||||
|
||||
// If this object has `type` + `anyOf`/`oneOf`, push `type` into
|
||||
// each item and remove it from the parent. Otherwise leave it alone.
|
||||
let should_push =
|
||||
@@ -635,10 +641,6 @@ pub fn sanitize_for_kimi(schema: &mut serde_json::Value) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Recurse into all sub-objects and arrays
|
||||
for (_, v) in obj.iter_mut() {
|
||||
sanitize_for_kimi(v);
|
||||
}
|
||||
} else if let Some(arr) = schema.as_array_mut() {
|
||||
for v in arr.iter_mut() {
|
||||
sanitize_for_kimi(v);
|
||||
@@ -676,6 +678,50 @@ mod kimi_tests {
|
||||
assert_eq!(any_of[1]["type"], "null");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kimi_sanitize_injects_missing_anyof_item_types() {
|
||||
let mut schema = json!({
|
||||
"type": "object",
|
||||
"anyOf": [
|
||||
{"properties": {"path": {"type": "string"}}},
|
||||
{"required": ["url"], "properties": {"url": {"type": "string"}}}
|
||||
]
|
||||
});
|
||||
|
||||
sanitize_for_kimi(&mut schema);
|
||||
|
||||
assert!(
|
||||
!schema.as_object().unwrap().contains_key("type"),
|
||||
"parent type should be removed"
|
||||
);
|
||||
let any_of = schema["anyOf"].as_array().unwrap();
|
||||
assert_eq!(any_of[0]["type"], "object");
|
||||
assert_eq!(any_of[1]["type"], "object");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kimi_sanitize_preserves_type_injected_into_nested_anyof_item() {
|
||||
let mut schema = json!({
|
||||
"type": "object",
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [
|
||||
{"properties": {"path": {"type": "string"}}}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
sanitize_for_kimi(&mut schema);
|
||||
|
||||
let outer_item = &schema["anyOf"][0];
|
||||
assert_eq!(outer_item["type"], "object");
|
||||
assert!(
|
||||
!schema.as_object().unwrap().contains_key("type"),
|
||||
"outer parent type should be removed"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kimi_sanitize_leaves_pure_object_untouched() {
|
||||
let original = json!({
|
||||
|
||||
@@ -181,7 +181,7 @@ pub(crate) fn footer_working_label_frame(now_ms: u64, fancy_animations: bool) ->
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::footer_working_label_frame;
|
||||
use super::{footer_working_label_frame, one_line_summary};
|
||||
|
||||
#[test]
|
||||
fn footer_working_label_frame_is_static_without_fancy_animations() {
|
||||
@@ -190,6 +190,13 @@ mod tests {
|
||||
assert_eq!(footer_working_label_frame(1_600, false), 0);
|
||||
assert_eq!(footer_working_label_frame(1_600, true), 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_line_summary_strips_ansi_before_collapsing_text() {
|
||||
let summary = one_line_summary("read \x1b[38;2;6;174;242mfile.rs\x1b[0m", 80);
|
||||
assert_eq!(summary, "read file.rs");
|
||||
assert!(!summary.contains("38;2"));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_noisy_subagent_progress(status: &str) -> bool {
|
||||
|
||||
@@ -1955,7 +1955,8 @@ mod tests {
|
||||
AutoSidebarState, SidebarAgentRow, SidebarHoverSection, SidebarHoverState,
|
||||
SidebarSubagentSummary, SidebarToolRow, SidebarWorkChecklistItem, SidebarWorkStrategyStep,
|
||||
SidebarWorkSummary, ToolRowOrder, auto_sidebar_panels, editorial_tool_rows,
|
||||
subagent_panel_lines, task_panel_lines, work_panel_empty_hint, work_panel_lines,
|
||||
normalize_activity_text, subagent_panel_lines, task_panel_lines, work_panel_empty_hint,
|
||||
work_panel_lines,
|
||||
};
|
||||
use crate::config::Config;
|
||||
use crate::palette::PaletteMode;
|
||||
@@ -2033,6 +2034,13 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_activity_text_strips_ansi_before_collapsing_text() {
|
||||
let text = normalize_activity_text("running \x1b[48;2;10;17;32mtool\x1b[0m now");
|
||||
assert_eq!(text, "running tool now");
|
||||
assert!(!text.contains("48;2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn editorial_rows_hide_older_failure_after_newer_success() {
|
||||
let rows = vec![
|
||||
|
||||
@@ -286,4 +286,14 @@ mod tests {
|
||||
let label = concise_shell_command_label("cd /tmp/repo && cargo test --workspace", 80);
|
||||
assert_eq!(label, "cargo test --workspace");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concise_shell_command_label_strips_ansi_before_collapsing_text() {
|
||||
let label = concise_shell_command_label(
|
||||
"cd /repo && \x1b[38;2;6;174;242mcargo test\x1b[0m --workspace",
|
||||
80,
|
||||
);
|
||||
assert_eq!(label, "cargo test --workspace");
|
||||
assert!(!label.contains("38;2"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user