//! Copy/cut route rich tables to the host without a later egui text write replacing them. use std::cell::RefCell; use std::rc::Rc; use egui::{Event, OutputCommand}; use gridcraft_engine::Session; use gridcraft_ui_egui::{Services, SheetApp}; use serde_json::json; fn harness(services: Services) -> egui_kittest::Harness<'static, SheetApp> { let mut session = Session::new(); session.new_workbook(); session.execute("range.setValues", json!({"range": "A1", "values": [["Name", "Score"], ["Ada", 42]]})).unwrap(); session.execute("selection.set", json!({"range": "A1:B2"})).unwrap(); let mut h = egui_kittest::Harness::builder().with_size(egui::vec2(1200.0, 800.0)).build_ui_state( |ui, app: &mut SheetApp| { let ctx = ui.ctx().clone(); app.logic(&ctx); app.ui(ui); }, SheetApp::new(session, services), ); h.run_steps(4); h } #[test] fn copy_and_cut_publish_html_and_text_without_overwriting_rich_clipboard() { for event in [Event::Copy, Event::Cut] { let calls = Rc::new(RefCell::new(Vec::new())); let received = calls.clone(); let mut h = harness(Services { copy_html: Some(Box::new(move |html, text| { received.borrow_mut().push((html.to_string(), text.to_string())); Ok(()) })), ..Default::default() }); h.input_mut().events.push(event.clone()); h.step(); let calls = calls.borrow(); assert_eq!(calls.len(), 1); assert!(calls[0].0.contains("Rp10,000.00"#.to_string()))), ..Default::default() }); h.state_mut().run("selection.set", json!({"cell": "D5"})).unwrap(); h.input_mut().events.push(Event::Paste("Rp10,000.00".into())); h.run_steps(2); let value = h.state().session.active().and_then(|d| d.wb.active().map(|s| s.value(gridcraft_engine::core::CellRef::new(4, 3)))); assert_eq!(value, Some(gridcraft_engine::core::Value::number(10000.0))); } #[test] fn copying_multiple_areas_copies_lined_up_areas_and_explains_the_rest() { // Issue #348: lined-up areas copy as one block; others get Excel's message instead of nothing. let mut h = harness(Services::default()); h.state_mut().session.execute("selection.set", json!({"range": "B1:B2,A1:A2"})).unwrap(); h.input_mut().events.push(Event::Copy); h.step(); assert!(h.output().platform_output.commands.iter().any(|c| matches!(c, OutputCommand::CopyText(text) if text == "Name\tScore\nAda\t42\n"))); assert!(h.state().message.is_none()); assert_eq!(h.state().session.clipboard.as_ref().map(|c| c.areas.len()), Some(2)); h.state_mut().session.execute("selection.set", json!({"range": "A1,B2"})).unwrap(); h.input_mut().events.push(Event::Copy); h.step(); assert!(!h.output().platform_output.commands.iter().any(|c| matches!(c, OutputCommand::CopyText(_)))); assert_eq!(h.state().message.as_ref().map(|(_, text)| text.as_str()), Some("This action won't work on multiple selections.")); assert_eq!(h.state().session.clipboard.as_ref().map(|c| c.areas.len()), Some(2), "the earlier copy stays"); }