use std::path::PathBuf; use serde_json::{json, Value}; use sgclaw::compat::screen_html_export_tool::ScreenHtmlExportTool; use uuid::Uuid; use zeroclaw::tools::Tool; fn temp_workspace_root() -> PathBuf { let root = std::env::temp_dir().join(format!("sgclaw-screen-html-{}", Uuid::new_v4())); std::fs::create_dir_all(&root).unwrap(); root } #[tokio::test] async fn screen_html_export_tool_renders_dashboard_html_with_presentation_contract() { let workspace_root = temp_workspace_root(); let output_path = workspace_root.join("out/zhihu-hotlist-screen.html"); let tool = ScreenHtmlExportTool::new(workspace_root.clone()); let result = tool .execute(json!({ "snapshot_id": "snapshot-20260329", "generated_at_ms": 1774713600000u64, "rows": [ [1, "问题一", "344万"], [2, "问题二", "266万"] ], "output_path": output_path })) .await .unwrap(); assert!(result.success, "{result:?}"); assert!(output_path.exists()); let payload: Value = serde_json::from_str(&result.output).unwrap(); let html = std::fs::read_to_string(&output_path).unwrap(); assert_eq!(payload["output_path"], json!(output_path)); assert_eq!(payload["presentation"]["mode"], json!("new_tab")); assert_eq!(payload["renderer"], json!("screen_html_export")); assert!(payload["presentation"]["url"] .as_str() .unwrap() .starts_with("file://")); assert!(html.contains("snapshot-20260329")); assert!(html.contains("问题一")); assert!(html.contains("344万")); assert!(html.contains("const defaultPayload =")); assert!(html.contains("汇报摘要")); assert!(html.contains("fitScreenToViewport")); assert!(html.contains("dashboard-canvas")); assert!(html.contains("themeSwitcher")); assert!(html.contains("gov_blue_gold")); assert!(html.contains("tech_cyan_blue")); assert!(html.contains("industry_ink_green")); assert!(html.contains("meeting_red_gold")); assert!(html.contains("localStorage.setItem(\"zhihu-hotlist-theme\"")); }