use super::*;
#[test]
fn render_activity_tree_scrolls_to_selected_overflow_item() {
let mut state = MissionControlState::default();
for index in 0..10 {
state.apply_activity_event(ActivityEvent::Started {
id: ActivityId::new(format!("a{index}")),
parent_id: None,
kind: ActivityKind::Tool,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new(format!("item-{index}")),
});
}
state.selected = 9;
let backend = TestBackend::new(80, 16);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let rendered = terminal
.backend()
.buffer()
.content()
.iter()
.map(|cell| cell.symbol())
.collect::<String>();
assert!(rendered.contains("item-9"));
assert!(!rendered.contains("item-0"));
}
#[test]
fn render_selected_activity_detail_when_activity_selected_after_scrolling() {
let mut state = MissionControlState::default();
state.apply_activity_event(ActivityEvent::Started {
id: ActivityId::new("a1"),
parent_id: None,
kind: ActivityKind::Tool,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new("bash echo"),
});
state.apply_activity_event(ActivityEvent::Started {
id: ActivityId::new("a2"),
parent_id: None,
kind: ActivityKind::Tool,
status: ActivityStatus::Success,
metadata: ActivityMetadata::new("read file"),
});
state.selected = 1;
let backend = TestBackend::new(100, 30);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let rendered = terminal
.backend()
.buffer()
.content()
.iter()
.map(|cell| cell.symbol())
.collect::<String>();
assert!(rendered.contains("✓ SUCCESS"));
assert!(rendered.contains("id: a2"));
assert!(rendered.contains("label: read file"));
}
#[test]
fn render_activity_tree_includes_compact_metadata_without_raw_detail_noise() {
let mut state = MissionControlState::default();
let mut metadata = ActivityMetadata::new("bash cargo test");
metadata.detail = Some("bash preview: final output only".to_string());
metadata.fields = vec![
("exit_code".to_string(), "101".to_string()),
("output_lines".to_string(), "12".to_string()),
("timed_out".to_string(), "false".to_string()),
];
state.apply_activity_event(ActivityEvent::Started {
id: ActivityId::new("tool-1"),
parent_id: None,
kind: ActivityKind::Tool,
status: ActivityStatus::Failed,
metadata,
});
let backend = TestBackend::new(200, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let layout = layout_for(Rect::new(0, 0, 200, 20), &state);
let rendered = rendered_text_in_area(buffer, layout.activity_tree.expect("activity tree"));
assert!(rendered.contains("bash cargo test • exit 101 • lines 12"));
assert!(!rendered.contains("tool •"), "{rendered}");
assert!(!rendered.contains("timed out false"));
assert!(!rendered.contains("final output only"));
}
#[test]
fn render_read_activity_tree_uses_canonical_per_target_line_summaries() {
let mut state = MissionControlState::default();
let call = crate::providers::ToolCall {
id: "read-tree".to_string(),
name: "read".to_string(),
arguments: serde_json::json!({
"paths": ["src/first.ext:136", "nested/second.ext", "third.ext"]
}),
};
let result = crate::tools::ToolResult {
tool_name: "read".to_string(),
success: true,
content: String::new(),
metadata: serde_json::json!({
"offset": 1,
"results": [
{
"requested_path": "src/first.ext:136",
"source": "src/first.ext",
"selector": {"raw": false, "lines": {"type": "single", "line": 136}}
},
{
"requested_path": "nested/second.ext",
"source": "nested/second.ext",
"selector": null
},
{
"requested_path": "third.ext",
"source": "third.ext",
"selector": null
}
]
}),
display: crate::tools::ToolResultDisplay::default(),
};
state.apply_output_event(&OutputEvent::ToolStarted {
call: Box::new(call.clone()),
label: "read 3 files".to_string(),
});
let summary = crate::output::tool_display_summary(&call, &result);
state.apply_output_event(&OutputEvent::ToolResult {
changed_paths: Vec::new(),
call: Box::new(call),
result: Box::new(result),
summary: Box::new(summary),
});
let backend = TestBackend::new(200, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let layout = layout_for(Rect::new(0, 0, 200, 20), &state);
let rendered = rendered_text_in_area(buffer, layout.activity_tree.expect("activity tree"));
assert!(
rendered.contains("read 3 files • first.ext:136, second.ext:1 …"),
"{rendered}"
);
assert!(!rendered.contains("files 3"), "{rendered}");
assert!(!rendered.contains("offset"), "{rendered}");
}
#[test]
fn render_read_activity_tree_does_not_parse_existing_filename_suffixes() {
let mut state = MissionControlState::default();
let call = crate::providers::ToolCall {
id: "read-filename".to_string(),
name: "read".to_string(),
arguments: serde_json::json!({"path": "notes:raw"}),
};
let result = crate::tools::ToolResult {
tool_name: "read".to_string(),
success: true,
content: String::new(),
metadata: serde_json::json!({
"source": "notes:raw",
"path": "/workspace/notes:raw",
"offset": 11,
"selector": null,
"raw": false
}),
display: crate::tools::ToolResultDisplay::default(),
};
state.apply_output_event(&OutputEvent::ToolStarted {
call: Box::new(call.clone()),
label: "read notes:raw".to_string(),
});
let summary = crate::output::tool_display_summary(&call, &result);
state.apply_output_event(&OutputEvent::ToolResult {
changed_paths: Vec::new(),
call: Box::new(call),
result: Box::new(result),
summary: Box::new(summary),
});
let backend = TestBackend::new(160, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let layout = layout_for(Rect::new(0, 0, 160, 20), &state);
let rendered = rendered_text_in_area(buffer, layout.activity_tree.expect("activity tree"));
assert!(
rendered.contains("read notes:raw • notes:raw:11"),
"{rendered}"
);
assert!(!rendered.contains("notes:1"), "{rendered}");
}
#[test]
fn render_read_activity_tree_strips_signed_url_parts() {
let mut state = MissionControlState::default();
let signed_url = "HTTPS://user:password@example.com/docs?X-Amz-Signature=secret#fragment";
let call = crate::providers::ToolCall {
id: "read-signed".to_string(),
name: "read".to_string(),
arguments: serde_json::json!({"path": signed_url}),
};
let result = crate::tools::ToolResult {
tool_name: "read".to_string(),
success: true,
content: String::new(),
metadata: serde_json::json!({
"source": signed_url,
"offset": 1,
"selector": null
}),
display: crate::tools::ToolResultDisplay::default(),
};
state.apply_output_event(&OutputEvent::ToolStarted {
call: Box::new(call.clone()),
label: format!("read {signed_url}"),
});
let summary = crate::output::tool_display_summary(&call, &result);
state.apply_output_event(&OutputEvent::ToolResult {
changed_paths: Vec::new(),
call: Box::new(call),
result: Box::new(result),
summary: Box::new(summary),
});
let backend = TestBackend::new(200, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let layout = layout_for(Rect::new(0, 0, 200, 20), &state);
let rendered = rendered_text_in_area(buffer, layout.activity_tree.expect("activity tree"));
assert!(
rendered.contains("read https://example.com/docs"),
"{rendered}"
);
assert!(!rendered.contains("password"), "{rendered}");
assert!(!rendered.contains("X-Amz-Signature"), "{rendered}");
assert!(!rendered.contains("fragment"), "{rendered}");
}
#[test]
fn render_activity_tree_combines_agent_preview_and_read_metadata_at_realistic_widths() {
let mut state = MissionControlState::default();
let agent_id = ActivityId::new("agent-realistic-width");
state.apply_activity_event(ActivityEvent::Started {
id: agent_id.clone(),
parent_id: None,
kind: ActivityKind::Assistant,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new("assistant"),
});
state.apply_activity_event(ActivityEvent::FinalPreview {
id: agent_id.clone(),
preview: "Visible answer remains useful at realistic widths".to_string(),
metadata: None,
status: Some(ActivityStatus::Success),
});
let read_id = ActivityId::new("read-realistic-width");
let call = crate::providers::ToolCall {
id: read_id.as_str().to_string(),
name: "read".to_string(),
arguments: serde_json::json!({
"paths": [
"workspace/first-very-long-name.ext:136",
"nested/second-very-long-name.ext",
"third-very-long-name.ext"
]
}),
};
let result = crate::tools::ToolResult {
tool_name: "read".to_string(),
success: true,
content: String::new(),
metadata: serde_json::json!({
"offset": 1,
"results": [
{
"requested_path": "workspace/first-very-long-name.ext:136",
"source": "workspace/first-very-long-name.ext",
"selector": {"raw": false, "lines": {"type": "single", "line": 136}}
},
{
"requested_path": "nested/second-very-long-name.ext",
"source": "nested/second-very-long-name.ext",
"selector": null
},
{
"requested_path": "third-very-long-name.ext",
"source": "third-very-long-name.ext",
"selector": null
}
]
}),
display: crate::tools::ToolResultDisplay::default(),
};
state.apply_output_event(&OutputEvent::ToolStarted {
call: Box::new(call.clone()),
label: "read 3 files".to_string(),
});
let summary = crate::output::tool_display_summary(&call, &result);
state.apply_output_event(&OutputEvent::ToolResult {
changed_paths: Vec::new(),
call: Box::new(call),
result: Box::new(result),
summary: Box::new(summary),
});
for width in [80 + RIGHT_COLUMN_RAIL_WIDTH, 120 + RIGHT_COLUMN_RAIL_WIDTH] {
let backend = TestBackend::new(width, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let tree = layout_for(Rect::new(0, 0, width, 20), &state)
.activity_tree
.expect("activity tree");
let agent_row_area =
super::super::activity::activity_tree_row_area(tree, &state, &agent_id)
.expect("agent row");
let agent_row = (agent_row_area.x..agent_row_area.x + agent_row_area.width)
.map(|x| buffer[(x, agent_row_area.y)].symbol())
.collect::<String>();
assert!(
agent_row.contains("agent • V"),
"width {width}: {agent_row}"
);
let (x, y) =
super::find_text_in_area(buffer, agent_row_area, "V").expect("agent preview text");
assert_eq!(
buffer[(x, y)].fg,
state.theme.muted(false).fg.expect("muted style foreground")
);
let read_row_area = super::super::activity::activity_tree_row_area(tree, &state, &read_id)
.expect("read row");
let read_row = (read_row_area.x..read_row_area.x + read_row_area.width)
.map(|x| buffer[(x, read_row_area.y)].symbol())
.collect::<String>();
let trimmed_read_row = read_row.trim_end();
let metadata_suffix = trimmed_read_row
.split_once("read 3 files")
.map(|(_, suffix)| suffix)
.expect("read label");
assert!(
!metadata_suffix.ends_with('•'),
"width {width} has dangling metadata separator: {read_row}"
);
assert!(
metadata_suffix.is_empty() || metadata_suffix.ends_with('…'),
"width {width} has clipped read metadata: {read_row}"
);
}
}
#[test]
fn render_hash_edit_activity_tree_uses_operation_first_summary() {
let input = "[old.rs#ABCD]\nMV new.rs\n[tests.rs#ABCD]\nSWAP 1.=1:\n+PATCH_BODY_MUST_NOT_RENDER\n[legacy.rs#ABCD]\nREM";
let call = crate::providers::ToolCall {
id: "hash-edit-tree".to_string(),
name: "hash_edit".to_string(),
arguments: serde_json::json!({"input": input}),
};
let mut state = MissionControlState::default();
let mut metadata = ActivityMetadata::new("hash_edit");
metadata.fields = vec![("bytes".to_string(), "99".to_string())];
state.apply_activity_event(ActivityEvent::Started {
id: ActivityId::new("hash-edit-tree"),
parent_id: None,
kind: ActivityKind::Tool,
status: ActivityStatus::Running,
metadata,
});
state.apply_output_event(&OutputEvent::ToolStarted {
call: Box::new(call),
label: "hash_edit".to_string(),
});
let width = 200 + RIGHT_COLUMN_RAIL_WIDTH;
let render_tree = |state: &MissionControlState| {
let backend = TestBackend::new(width, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, state)).unwrap();
let buffer = terminal.backend().buffer();
let layout = layout_for(Rect::new(0, 0, width, 20), state);
rendered_text_in_area(buffer, layout.activity_tree.expect("activity tree"))
};
let expected = "hash_edit 3 files • Move old.rs → new.rs, Update tests.rs … +1";
for (status, status_mark) in [
(ActivityStatus::Running, "●"),
(ActivityStatus::Success, "✓"),
(ActivityStatus::Failed, "✗"),
] {
if status != ActivityStatus::Running {
state.apply_activity_event(ActivityEvent::Finished {
id: ActivityId::new("hash-edit-tree"),
status,
metadata: None,
});
}
let rendered = render_tree(&state);
assert!(
rendered.contains(&format!("{status_mark} {expected}")),
"{rendered}"
);
assert!(!rendered.contains("bytes 99"), "{rendered}");
assert!(!rendered.contains("SWAP"), "{rendered}");
assert!(
!rendered.contains("PATCH_BODY_MUST_NOT_RENDER"),
"{rendered}"
);
}
}
#[test]
fn render_hash_edit_activity_tree_preserves_original_malformed_bytes_after_redacted_tool_started() {
let secret = "credential-value-must-not-render";
let input = format!("not a hashline patch api_key={secret}");
assert_ne!(
input.len(),
crate::output::redact_sensitive_text(&input).len()
);
let call = crate::providers::ToolCall {
id: "hash-edit-malformed".to_string(),
name: "hash_edit".to_string(),
arguments: serde_json::json!({"input": input.clone()}),
};
let result = crate::tools::ToolResult {
tool_name: "hash_edit".to_string(),
success: false,
content: "invalid hashline patch".to_string(),
metadata: serde_json::json!({}),
display: crate::tools::ToolResultDisplay::default(),
};
let summary = crate::output::tool_display_summary(&call, &result);
let mut state = MissionControlState::default();
state.apply_output_event(&OutputEvent::ToolStarted {
call: Box::new(call.clone()),
label: "hash_edit".to_string(),
});
state.apply_output_event(&OutputEvent::ToolResult {
changed_paths: Vec::new(),
call: Box::new(call),
result: Box::new(result),
summary: Box::new(summary),
});
let backend = TestBackend::new(160, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let layout = layout_for(Rect::new(0, 0, 160, 20), &state);
let rendered = rendered_text_in_area(buffer, layout.activity_tree.expect("activity tree"));
assert!(
rendered.contains(&format!("✗ hash_edit • bytes {}", input.len())),
"{rendered}"
);
assert!(!rendered.contains(secret), "{rendered}");
}
#[test]
fn render_subagent_activity_tree_includes_identity_metadata() {
let mut state = MissionControlState::default();
let mut metadata = ActivityMetadata::new("g1 • inspect UI");
metadata.fields = vec![("identity".to_string(), "frontend-dev".to_string())];
let id = ActivityId::new("subagents/g1");
state.apply_activity_event(ActivityEvent::Started {
id: id.clone(),
parent_id: None,
kind: ActivityKind::SubagentTask,
status: ActivityStatus::Running,
metadata,
});
state.apply_activity_event(ActivityEvent::Delta {
id,
preview: "subagent task preview must stay off this row".to_string(),
});
let backend = TestBackend::new(200, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let layout = layout_for(Rect::new(0, 0, 200, 20), &state);
let rendered = rendered_text_in_area(buffer, layout.activity_tree.expect("activity tree"));
assert!(rendered.contains("g1 • inspect UI • identity: frontend-dev"));
assert!(
!rendered.contains("subagent task preview must stay off this row"),
"{rendered}"
);
}
#[test]
fn render_activity_tree_omits_nested_assistant_preview() {
let mut state = MissionControlState::default();
let parent_id = ActivityId::new("subagents/g1");
state.apply_activity_event(ActivityEvent::Started {
id: parent_id.clone(),
parent_id: None,
kind: ActivityKind::SubagentTask,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new("g1"),
});
let id = ActivityId::new("subagents/g1/assistant/0");
state.apply_activity_event(ActivityEvent::Started {
id: id.clone(),
parent_id: Some(parent_id),
kind: ActivityKind::Assistant,
status: ActivityStatus::Success,
metadata: ActivityMetadata::new("assistant"),
});
state.apply_activity_event(ActivityEvent::Delta {
id,
preview: "nested assistant preview must stay off this row".to_string(),
});
let backend = TestBackend::new(200, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let tree = layout_for(Rect::new(0, 0, 200, 20), &state)
.activity_tree
.expect("activity tree");
let rendered = rendered_text_in_area(buffer, tree);
assert!(
!rendered.contains("nested assistant preview must stay off this row"),
"{rendered}"
);
}
#[test]
fn render_activity_status_kind_and_selection_styles() {
let mut state = MissionControlState {
focus_pane: crate::tui::state::TuiFocusPane::ActivityTree,
..Default::default()
};
for (label, status, kind) in [
("queued-tool", ActivityStatus::Queued, ActivityKind::Tool),
(
"running-batch",
ActivityStatus::Running,
ActivityKind::SubagentBatch,
),
(
"success-task",
ActivityStatus::Success,
ActivityKind::SubagentTask,
),
(
"failed-assistant",
ActivityStatus::Failed,
ActivityKind::Assistant,
),
(
"canceled-diagnostic",
ActivityStatus::Canceled,
ActivityKind::Diagnostic,
),
] {
state.apply_activity_event(ActivityEvent::Started {
id: ActivityId::new(label),
parent_id: None,
kind,
status,
metadata: ActivityMetadata::new(label),
});
}
let backend = TestBackend::new(100, 30);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let rendered = terminal
.backend()
.buffer()
.content()
.iter()
.map(|cell| cell.symbol())
.collect::<String>();
for mark in ["○", "●", "✓", "✗", "⊘"] {
assert!(rendered.contains(mark), "missing {mark}: {rendered}");
}
}
#[test]
fn activity_tree_formats_single_and_grouped_reasoning_without_agent_duplication() {
let mut state = MissionControlState::default();
state.apply_activity_event(ActivityEvent::Started {
id: ActivityId::new("reasoning-one"),
parent_id: None,
kind: ActivityKind::Assistant,
status: ActivityStatus::Success,
metadata: ActivityMetadata::reasoning(&["checked inputs".to_string()]),
});
state.apply_activity_event(ActivityEvent::Started {
id: ActivityId::new("reasoning-two"),
parent_id: None,
kind: ActivityKind::Assistant,
status: ActivityStatus::Success,
metadata: ActivityMetadata::reasoning(&[
"checked inputs".to_string(),
"planned fix".to_string(),
]),
});
let backend = TestBackend::new(120, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let layout = layout_for(Rect::new(0, 0, 120, 20), &state);
let rendered = rendered_text_in_area(
terminal.backend().buffer(),
layout.activity_tree.expect("activity tree"),
);
assert!(
rendered.contains("reasoning • checked inputs"),
"{rendered}"
);
assert!(rendered.contains("reasoning summaries ×2"), "{rendered}");
assert!(!rendered.contains("agent • reasoning"), "{rendered}");
assert!(!rendered.contains("×1"), "{rendered}");
}
#[test]
fn render_activity_tree_shows_sanitized_assistant_preview_with_muted_style() {
let mut state = MissionControlState::default();
let id = ActivityId::new("assistant-preview");
state.apply_activity_event(ActivityEvent::Started {
id: id.clone(),
parent_id: None,
kind: ActivityKind::Assistant,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new("assistant"),
});
state.apply_activity_event(ActivityEvent::FinalPreview {
id,
preview: "\n \u{1b}[31mfirst answer\u{7}\u{1b}[0m\nsecond answer".to_string(),
metadata: None,
status: Some(ActivityStatus::Success),
});
let backend = TestBackend::new(180, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let tree = layout_for(Rect::new(0, 0, 180, 20), &state)
.activity_tree
.expect("activity tree");
let rendered = rendered_text_in_area(buffer, tree);
assert!(rendered.contains("agent • first answer"), "{rendered}");
assert!(!rendered.contains("second answer"), "{rendered}");
assert!(!rendered.contains('\u{1b}'), "{rendered}");
let (x, y) = super::find_text_in_area(buffer, tree, "first answer").expect("preview text");
let expected_style = state.theme.muted(false).fg.expect("muted style foreground");
assert_eq!(buffer[(x, y)].fg, expected_style);
}
#[test]
fn render_activity_tree_bounds_preview_to_80_column_tree_width() {
let mut state = MissionControlState::default();
let id = ActivityId::new("assistant-width");
state.apply_activity_event(ActivityEvent::Started {
id: id.clone(),
parent_id: None,
kind: ActivityKind::Assistant,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new("assistant"),
});
state.apply_activity_event(ActivityEvent::FinalPreview {
id,
preview: "This is a long assistant response whose tail must not be clipped".to_string(),
metadata: None,
status: Some(ActivityStatus::Success),
});
let backend = TestBackend::new(80, 24);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let tree = layout_for(Rect::new(0, 0, 80, 24), &state)
.activity_tree
.expect("activity tree");
let rendered = rendered_text_in_area(buffer, tree);
let row = rendered
.lines()
.find(|line| line.contains("agent"))
.expect("assistant row");
assert!(row.contains('…'), "{row}");
assert!(!row.contains("tail must not be clipped"), "{row}");
}
#[test]
fn render_activity_tree_omits_preview_when_narrow_row_has_no_room() {
let mut state = MissionControlState::default();
let id = ActivityId::new("assistant-narrow");
state.apply_activity_event(ActivityEvent::Started {
id: id.clone(),
parent_id: None,
kind: ActivityKind::Assistant,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new("assistant"),
});
state.apply_activity_event(ActivityEvent::FinalPreview {
id,
preview: "preview must be omitted".to_string(),
metadata: None,
status: Some(ActivityStatus::Success),
});
let backend = TestBackend::new(20, 4);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal
.draw(|frame| super::super::activity::draw_tree(frame, Rect::new(0, 0, 20, 4), &state))
.unwrap();
let rendered = rendered_text_in_area(terminal.backend().buffer(), Rect::new(0, 0, 20, 4));
assert!(!rendered.contains("preview must be omitted"), "{rendered}");
}