yufmath 0.1.1

A Rust CAS Lib.
Documentation
//! # GUI 测试模块
//!
//! 测试笔记本图形用户界面的功能。

#[cfg(test)]
mod tests {
    use super::super::*;
    use crate::notebook::{NotebookGUI, CellEditor, NotebookCell, CellType, Notebook};
    use fltk::prelude::*;
    
    /// 测试单元格编辑器的基本功能
    #[test]
    fn test_cell_editor_basic_functionality() {
        // 创建测试单元格
        let cell = NotebookCell::new_code("x + y".to_string());
        let original_id = cell.id;
        
        // 创建单元格编辑器
        let editor = CellEditor::new(0, 0, 400, 200, &cell);
        
        // 验证基本属性
        assert_eq!(editor.cell_id(), original_id);
        assert_eq!(editor.cell_type(), &CellType::Code);
        assert_eq!(editor.get_input_text(), "x + y");
        assert!(!editor.is_selected());
    }
    
    /// 测试单元格编辑器的选中状态
    #[test]
    fn test_cell_editor_selection() {
        let cell = NotebookCell::new_code("test".to_string());
        let mut editor = CellEditor::new(0, 0, 400, 200, &cell);
        
        // 初始状态应该是未选中
        assert!(!editor.is_selected());
        
        // 设置为选中
        editor.set_selected(true);
        assert!(editor.is_selected());
        
        // 设置为未选中
        editor.set_selected(false);
        assert!(!editor.is_selected());
    }
    
    /// 测试单元格类型转换
    #[test]
    fn test_cell_editor_type_conversion() {
        let cell = NotebookCell::new_code("# 标题".to_string());
        let mut editor = CellEditor::new(0, 0, 400, 200, &cell);
        
        // 初始类型应该是代码
        assert_eq!(editor.cell_type(), &CellType::Code);
        
        // 转换为 Markdown
        editor.set_cell_type(CellType::Markdown);
        assert_eq!(editor.cell_type(), &CellType::Markdown);
        
        // 转换为文本
        editor.set_cell_type(CellType::Text);
        assert_eq!(editor.cell_type(), &CellType::Text);
    }
    
    /// 测试单元格编辑器的文本操作
    #[test]
    fn test_cell_editor_text_operations() {
        let cell = NotebookCell::new_code("original text".to_string());
        let mut editor = CellEditor::new(0, 0, 400, 200, &cell);
        
        // 验证初始文本
        assert_eq!(editor.get_input_text(), "original text");
        
        // 设置新文本
        editor.set_input_text("new text");
        assert_eq!(editor.get_input_text(), "new text");
        
        // 设置输出文本
        editor.set_output_text("output result");
        // 注意:由于 FLTK 的限制,我们无法直接测试输出文本的获取
    }
    
    /// 测试笔记本 GUI 的创建
    #[test]
    fn test_notebook_gui_creation() {
        // 注意:这个测试需要在有图形环境的情况下运行
        // 在没有图形环境的 CI 中会跳过
        if std::env::var("DISPLAY").is_err() && std::env::var("WAYLAND_DISPLAY").is_err() {
            println!("跳过 GUI 测试:没有图形环境");
            return;
        }
        
        // 尝试创建 GUI(可能会失败如果没有图形环境)
        match std::panic::catch_unwind(|| {
            let gui = NotebookGUI::new();
            assert!(gui.get_notebook().is_none());
        }) {
            Ok(_) => println!("GUI 创建测试通过"),
            Err(_) => println!("GUI 创建测试跳过:无法初始化图形环境"),
        }
    }
    
    /// 测试笔记本设置功能
    #[test]
    fn test_notebook_gui_set_notebook() {
        // 跳过需要图形环境的测试
        if std::env::var("DISPLAY").is_err() && std::env::var("WAYLAND_DISPLAY").is_err() {
            println!("跳过 GUI 测试:没有图形环境");
            return;
        }
        
        // 创建测试笔记本
        let mut notebook = Notebook::with_title("测试笔记本".to_string());
        notebook.add_cell(NotebookCell::new_code("x = 1".to_string()));
        notebook.add_cell(NotebookCell::new_markdown("# 标题".to_string()));
        
        // 尝试设置笔记本
        match std::panic::catch_unwind(|| {
            let mut gui = NotebookGUI::new();
            let result = gui.set_notebook(notebook);
            assert!(result.is_ok());
        }) {
            Ok(_) => println!("笔记本设置测试通过"),
            Err(_) => println!("笔记本设置测试跳过:无法初始化图形环境"),
        }
    }
    
    /// 测试快捷键功能(模拟)
    #[test]
    fn test_shortcut_functionality() {
        // 这是一个概念性测试,验证快捷键映射的逻辑
        
        // 模拟 Ctrl+N (新建代码单元格)
        let ctrl_n_shortcut = fltk::enums::Shortcut::Ctrl | 'n';
        assert_eq!(ctrl_n_shortcut.bits(), (fltk::enums::Shortcut::Ctrl | 'n').bits());
        
        // 模拟 Ctrl+M (新建文档单元格)
        let ctrl_m_shortcut = fltk::enums::Shortcut::Ctrl | 'm';
        assert_eq!(ctrl_m_shortcut.bits(), (fltk::enums::Shortcut::Ctrl | 'm').bits());
        
        // 模拟 Ctrl+Enter (执行单元格)
        let ctrl_enter_shortcut = fltk::enums::Shortcut::Ctrl | fltk::enums::Shortcut::from_key(fltk::enums::Key::Enter);
        assert!(ctrl_enter_shortcut.bits() != 0);
        
        // 模拟 Shift+Enter (执行并新建单元格)
        let shift_enter_shortcut = fltk::enums::Shortcut::Shift | fltk::enums::Shortcut::from_key(fltk::enums::Key::Enter);
        assert!(shift_enter_shortcut.bits() != 0);
    }
    
    /// 测试语法高亮设置
    #[test]
    fn test_syntax_highlighting_setup() {
        let code_cell = NotebookCell::new_code("fn main() {}".to_string());
        let mut code_editor = CellEditor::new(0, 0, 400, 200, &code_cell);
        
        // 验证代码单元格的类型
        assert_eq!(code_editor.cell_type(), &CellType::Code);
        
        let markdown_cell = NotebookCell::new_markdown("# 标题\n\n内容".to_string());
        let mut markdown_editor = CellEditor::new(0, 0, 400, 200, &markdown_cell);
        
        // 验证 Markdown 单元格的类型
        assert_eq!(markdown_editor.cell_type(), &CellType::Markdown);
        
        // 测试类型转换
        code_editor.set_cell_type(CellType::Markdown);
        assert_eq!(code_editor.cell_type(), &CellType::Markdown);
        
        markdown_editor.set_cell_type(CellType::Code);
        assert_eq!(markdown_editor.cell_type(), &CellType::Code);
    }
    
    /// 测试单元格容器功能
    #[test]
    fn test_cell_container_functionality() {
        let cell = NotebookCell::new_code("test".to_string());
        let editor = CellEditor::new(10, 20, 400, 200, &cell);
        
        // 验证容器存在
        let container = editor.container();
        assert!(container.x() == 10);
        assert!(container.y() == 20);
        assert!(container.width() == 400);
        assert!(container.height() == 200);
    }
    
    /// 集成测试:模拟完整的用户交互流程
    #[test]
    fn test_user_interaction_flow() {
        // 跳过需要图形环境的测试
        if std::env::var("DISPLAY").is_err() && std::env::var("WAYLAND_DISPLAY").is_err() {
            println!("跳过集成测试:没有图形环境");
            return;
        }
        
        // 模拟用户交互流程
        match std::panic::catch_unwind(|| {
            // 1. 创建笔记本
            let mut notebook = Notebook::with_title("集成测试笔记本".to_string());
            
            // 2. 添加一些单元格
            notebook.add_cell(NotebookCell::new_code("x = 2 + 3".to_string()));
            notebook.add_cell(NotebookCell::new_markdown("## 计算结果".to_string()));
            notebook.add_cell(NotebookCell::new_code("y = x * 2".to_string()));
            
            // 3. 创建 GUI(如果可能)
            let mut gui = NotebookGUI::new();
            
            // 4. 设置笔记本
            let result = gui.set_notebook(notebook);
            assert!(result.is_ok());
            
            // 5. 验证笔记本已设置
            assert!(gui.get_notebook().is_some());
            
            println!("集成测试完成");
        }) {
            Ok(_) => println!("集成测试通过"),
            Err(_) => println!("集成测试跳过:无法初始化图形环境"),
        }
    }
}

/// 性能测试模块
#[cfg(test)]
mod performance_tests {
    use super::super::*;
    use std::time::Instant;
    
    /// 测试大量单元格的创建性能
    #[test]
    fn test_large_notebook_performance() {
        let start = Instant::now();
        
        // 创建包含大量单元格的笔记本
        let mut notebook = Notebook::with_title("性能测试笔记本".to_string());
        
        for i in 0..100 {
            notebook.add_cell(NotebookCell::new_code(format!("x{} = {}", i, i)));
        }
        
        let creation_time = start.elapsed();
        println!("创建 100 个单元格耗时: {:?}", creation_time);
        
        // 验证创建成功
        assert_eq!(notebook.cell_count(), 100);
        
        // 性能要求:创建 100 个单元格应该在 10ms 内完成
        assert!(creation_time.as_millis() < 10, "单元格创建性能不达标");
    }
    
    /// 测试单元格编辑器创建性能
    #[test]
    fn test_cell_editor_creation_performance() {
        let start = Instant::now();
        
        let mut editors = Vec::new();
        
        for i in 0..50 {
            let cell = NotebookCell::new_code(format!("test_{}", i));
            let editor = CellEditor::new(0, i * 160, 400, 150, &cell);
            editors.push(editor);
        }
        
        let creation_time = start.elapsed();
        println!("创建 50 个单元格编辑器耗时: {:?}", creation_time);
        
        // 验证创建成功
        assert_eq!(editors.len(), 50);
        
        // 性能要求:创建 50 个编辑器应该在 100ms 内完成
        assert!(creation_time.as_millis() < 100, "单元格编辑器创建性能不达标");
    }
}

/// 错误处理测试模块
#[cfg(test)]
mod error_handling_tests {
    use super::super::*;
    
    /// 测试无效单元格类型转换
    #[test]
    fn test_invalid_cell_type_conversion() {
        let cell = NotebookCell::new_code("test".to_string());
        let mut editor = CellEditor::new(0, 0, 400, 200, &cell);
        
        // 所有有效的单元格类型转换都应该成功
        editor.set_cell_type(CellType::Markdown);
        assert_eq!(editor.cell_type(), &CellType::Markdown);
        
        editor.set_cell_type(CellType::Text);
        assert_eq!(editor.cell_type(), &CellType::Text);
        
        editor.set_cell_type(CellType::Code);
        assert_eq!(editor.cell_type(), &CellType::Code);
        
        // 输出类型的转换也应该被允许(虽然不常用)
        editor.set_cell_type(CellType::Output);
        assert_eq!(editor.cell_type(), &CellType::Output);
    }
    
    /// 测试空文本处理
    #[test]
    fn test_empty_text_handling() {
        let cell = NotebookCell::new_code("".to_string());
        let mut editor = CellEditor::new(0, 0, 400, 200, &cell);
        
        // 空文本应该被正确处理
        assert_eq!(editor.get_input_text(), "");
        
        // 设置空文本应该成功
        editor.set_input_text("");
        assert_eq!(editor.get_input_text(), "");
        
        // 设置非空文本然后再设置为空
        editor.set_input_text("some text");
        assert_eq!(editor.get_input_text(), "some text");
        
        editor.set_input_text("");
        assert_eq!(editor.get_input_text(), "");
    }
    
    /// 测试长文本处理
    #[test]
    fn test_long_text_handling() {
        // 创建一个很长的文本
        let long_text = "x = ".repeat(1000) + "1";
        let cell = NotebookCell::new_code(long_text.clone());
        let mut editor = CellEditor::new(0, 0, 400, 200, &cell);
        
        // 长文本应该被正确处理
        assert_eq!(editor.get_input_text(), long_text);
        
        // 设置另一个长文本
        let another_long_text = "y = ".repeat(500) + "2";
        editor.set_input_text(&another_long_text);
        assert_eq!(editor.get_input_text(), another_long_text);
    }
}