#[cfg(test)]
mod tests {
use crate::model::common::SocketFunction;
use crate::tests::test_utils::*;
use crate::thread_manager::Message;
use std::sync::mpsc;
#[test]
fn test_complete_app_lifecycle() {
let mut app = TestDataFactory::create_test_app();
app.validate();
assert!(TestAssertions::assert_app_active_layout(
&app,
"test_layout"
));
assert_eq!(app.layouts.len(), 1);
assert_eq!(app.layouts[0].children.as_ref().unwrap().len(), 1);
let mut multi_app = TestDataFactory::create_multi_layout_app();
multi_app.validate();
assert!(TestAssertions::assert_app_active_layout(
&multi_app, "layout1"
));
assert_eq!(multi_app.layouts.len(), 3);
}
#[test]
fn test_socket_to_message_workflow() {
let socket_function = TestDataFactory::create_socket_function_replace_content(
"test_muxbox",
"Updated via socket",
true,
);
let result = IntegrationTestUtils::simulate_socket_to_app_workflow(socket_function);
assert!(result.is_ok());
let message = result.unwrap();
assert!(TestAssertions::assert_message_type(
&message,
"StreamUpdate"
));
if let Message::StreamUpdateMessage(stream_update) = message {
let box_id = &stream_update.target_box_id;
let success = matches!(
stream_update.source_state,
crate::model::common::SourceState::Batch(crate::model::common::BatchSourceState {
status: crate::model::common::BatchStatus::Completed,
..
})
);
let content = stream_update.content_update;
assert_eq!(box_id, "test_muxbox");
assert_eq!(success, true);
assert_eq!(content, "Updated via socket");
}
}
#[test]
fn test_script_replacement_workflow() {
let script_commands = MockUtils::create_test_script_commands();
let socket_function = TestDataFactory::create_socket_function_replace_script(
"script_muxbox",
script_commands.clone(),
);
let result = IntegrationTestUtils::simulate_socket_to_app_workflow(socket_function);
assert!(result.is_ok());
let message = result.unwrap();
assert!(TestAssertions::assert_message_type(
&message,
"MuxBoxScriptUpdate"
));
if let Message::MuxBoxScriptUpdate(box_id, script) = message {
assert_eq!(box_id, "script_muxbox");
assert_eq!(script, script_commands);
}
}
#[test]
fn test_socket_function_handling() {
let socket_function = SocketFunction::ReplaceBoxContent {
box_id: "test_muxbox".to_string(),
success: true,
content: "test content".to_string(),
};
let result = crate::model::common::run_socket_function(
socket_function,
&TestDataFactory::create_test_app_context(),
);
assert!(result.is_ok());
let (_, messages) = result.unwrap();
assert_eq!(messages.len(), 1);
match &messages[0] {
Message::StreamUpdateMessage(stream_update) => {
let box_id = &stream_update.target_box_id;
let success = matches!(
stream_update.source_state,
crate::model::common::SourceState::Batch(
crate::model::common::BatchSourceState {
status: crate::model::common::BatchStatus::Completed,
..
}
)
);
let content = &stream_update.content_update;
assert_eq!(box_id, "test_muxbox");
assert_eq!(success, true);
assert_eq!(content, "test content");
}
_ => panic!("Expected StreamUpdate message"),
}
}
#[test]
fn test_large_configuration_performance() {
PerformanceTestUtils::assert_performance(
|| {
let _large_layout = PerformanceTestUtils::create_large_layout(100);
},
100,
std::time::Duration::from_millis(500),
"Large layout creation",
);
}
#[test]
fn test_concurrent_socket_operations() {
let (tx, rx) = mpsc::channel::<(uuid::Uuid, Message)>();
let test_uuid = MockUtils::create_test_uuid();
let functions = vec![
TestDataFactory::create_socket_function_replace_content("muxbox1", "content1", true),
TestDataFactory::create_socket_function_replace_content("muxbox2", "content2", true),
TestDataFactory::create_socket_function_replace_content("muxbox3", "content3", true),
];
for socket_function in functions {
let message = match socket_function {
SocketFunction::ReplaceBoxContent {
box_id,
success,
content,
} => {
use crate::model::common::{
BatchSourceState, ExecutionMode, SourceState, StreamUpdate,
};
let stream_update = StreamUpdate {
stream_id: format!("{}_default", box_id),
target_box_id: box_id.clone(),
content_update: content,
source_state: SourceState::Batch(BatchSourceState {
task_id: "test_task".to_string(),
queue_wait_time: std::time::Duration::from_millis(0),
execution_time: std::time::Duration::from_millis(100),
exit_code: if success { Some(0) } else { Some(1) },
status: if success {
crate::model::common::BatchStatus::Completed
} else {
crate::model::common::BatchStatus::Failed("Test error".to_string())
},
}),
execution_mode: ExecutionMode::Thread,
};
Message::StreamUpdateMessage(stream_update)
}
_ => panic!("Unexpected socket function type"),
};
tx.send((test_uuid, message))
.expect("Failed to send message");
}
let mut message_count = 0;
while let Ok(_) = rx.try_recv() {
message_count += 1;
}
assert_eq!(message_count, 3);
}
#[test]
fn test_bounds_calculation_integration() {
use crate::utils::input_bounds_to_bounds;
let parent_bounds = TestDataFactory::create_bounds(0, 0, 100, 50);
let input_bounds = TestDataFactory::create_input_bounds("10%", "20%", "90%", "80%");
let result_bounds = input_bounds_to_bounds(&input_bounds, &parent_bounds);
assert_eq!(result_bounds.x1, 10); assert_eq!(result_bounds.y1, 10); assert_eq!(result_bounds.x2, 90); assert_eq!(result_bounds.y2, 40);
let input_bounds = TestDataFactory::create_input_bounds("5", "10", "95", "45");
let result_bounds = input_bounds_to_bounds(&input_bounds, &parent_bounds);
assert_eq!(result_bounds.x1, 5);
assert_eq!(result_bounds.y1, 10);
assert_eq!(result_bounds.x2, 95);
assert_eq!(result_bounds.y2, 45);
}
#[test]
fn test_key_mapping_integration() {
use crate::utils::handle_keypress;
let key_mappings = MockUtils::create_test_key_mappings();
let test_cases = vec![
("ctrl+c", Some(vec!["exit".to_string()])),
("CTRL+C", Some(vec!["exit".to_string()])),
("enter", Some(vec!["confirm".to_string()])),
("ENTER", Some(vec!["confirm".to_string()])),
("tab", Some(vec!["next_muxbox".to_string()])),
("unknown_key", None),
];
for (key, expected) in test_cases {
let result = handle_keypress(key, &key_mappings);
assert_eq!(result, expected, "Failed for key: {}", key);
}
}
#[test]
fn test_script_execution_integration() {
use crate::utils::run_script;
let result = run_script(None, &vec!["echo test".to_string()]);
assert!(result.is_ok());
let output = result.unwrap();
assert!(output.contains("test"));
let lib_paths = Some(vec!["/usr/bin".to_string()]);
let result = run_script(lib_paths, &vec!["echo integration_test".to_string()]);
assert!(result.is_ok());
}
#[test]
fn test_ansi_handling_integration() {
use crate::utils::strip_ansi_codes;
let test_cases = vec![
("Plain text", "Plain text"),
("\x1b[31mRed text\x1b[0m", "Red text"),
("\x1b[1;32mBold green\x1b[0m normal", "Bold green normal"),
(
"\x1b[2J\x1b[H\x1b[31mRed after clear\x1b[0m",
"Red after clear",
),
];
for (input, expected) in test_cases {
let result = strip_ansi_codes(input);
assert_eq!(result, expected, "Failed for input: {}", input);
}
}
#[test]
fn test_muxbox_lifecycle_integration() {
let mut app = TestDataFactory::create_test_app();
let original_muxbox_count = app.layouts[0].children.as_ref().unwrap().len();
let new_muxbox = TestDataFactory::create_custom_muxbox("new_muxbox", "New muxbox content");
let add_function = SocketFunction::AddBox {
layout_id: "test_layout".to_string(),
muxbox: new_muxbox.clone(),
};
let message = IntegrationTestUtils::simulate_socket_to_app_workflow(add_function).unwrap();
assert!(TestAssertions::assert_message_type(&message, "AddBox"));
let updated_muxbox = TestDataFactory::create_custom_muxbox("new_muxbox", "Updated content");
let replace_function = SocketFunction::ReplaceBox {
box_id: "new_muxbox".to_string(),
new_box: updated_muxbox,
};
let message =
IntegrationTestUtils::simulate_socket_to_app_workflow(replace_function).unwrap();
assert!(TestAssertions::assert_message_type(
&message,
"ReplaceMuxBox"
));
let remove_function = SocketFunction::RemoveBox {
box_id: "new_muxbox".to_string(),
};
let message =
IntegrationTestUtils::simulate_socket_to_app_workflow(remove_function).unwrap();
assert!(TestAssertions::assert_message_type(&message, "RemoveBox"));
}
#[test]
fn test_error_recovery_scenarios() {
let mut invalid_app = TestDataFactory::create_test_app();
let existing_id = invalid_app.layouts[0].children.as_ref().unwrap()[0].id.clone();
assert_eq!(
existing_id, "default_muxbox",
"test relies on the seeded muxbox id; update if the factory changes"
);
let duplicate_muxbox = TestDataFactory::create_test_muxbox(&existing_id);
invalid_app.layouts[0]
.children
.as_mut()
.unwrap()
.push(duplicate_muxbox);
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
invalid_app.validate();
}));
assert!(result.is_err());
let mut multi_root_app = TestDataFactory::create_multi_layout_app();
multi_root_app.layouts[1].root = Some(true);
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
multi_root_app.validate();
}));
assert!(result.is_err());
}
#[test]
fn test_memory_usage_patterns() {
let start_time = std::time::Instant::now();
for _ in 0..1000 {
let _app = TestDataFactory::create_multi_layout_app();
let _large_layout = PerformanceTestUtils::create_large_layout(50);
}
let duration = start_time.elapsed();
println!("Memory stress test (1000 iterations): {:?}", duration);
assert!(
duration.as_secs() < 10,
"Memory stress test took too long: {:?}",
duration
);
}
}