121 lines
3.9 KiB
Rust
121 lines
3.9 KiB
Rust
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use serde_json::json;
|
|
use sgclaw::compat::report_artifact::interpret_report_artifact_and_postprocess;
|
|
use sgclaw::scene_contract::PostprocessSection;
|
|
use uuid::Uuid;
|
|
|
|
fn temp_workspace(prefix: &str) -> PathBuf {
|
|
let root = std::env::temp_dir().join(format!("{prefix}-{}", Uuid::new_v4()));
|
|
fs::create_dir_all(&root).unwrap();
|
|
root
|
|
}
|
|
|
|
fn report_postprocess_xlsx() -> PostprocessSection {
|
|
PostprocessSection {
|
|
exporter: "xlsx_report".to_string(),
|
|
auto_open: None,
|
|
}
|
|
}
|
|
|
|
fn exported_xlsx_files(workspace_root: &Path) -> Vec<PathBuf> {
|
|
let out_dir = workspace_root.join("out");
|
|
if !out_dir.exists() {
|
|
return Vec::new();
|
|
}
|
|
|
|
fs::read_dir(out_dir)
|
|
.unwrap()
|
|
.filter_map(Result::ok)
|
|
.map(|entry| entry.path())
|
|
.filter(|path| path.extension().and_then(|ext| ext.to_str()) == Some("xlsx"))
|
|
.collect()
|
|
}
|
|
|
|
#[test]
|
|
fn report_artifact_postprocess_exports_xlsx_for_ok_or_partial_scene() {
|
|
let workspace_root = temp_workspace("sgclaw-report-artifact-export");
|
|
let artifact = json!({
|
|
"type": "report-artifact",
|
|
"report_name": "tq-lineloss-report",
|
|
"status": "partial",
|
|
"columns": ["ORG_NAME", "LINE_LOSS_RATE"],
|
|
"column_defs": [["ORG_NAME", "供电单位"], ["LINE_LOSS_RATE", "综合线损率(%)"]],
|
|
"rows": [{"ORG_NAME": "国网兰州供电公司", "LINE_LOSS_RATE": "1.23"}],
|
|
"counts": {"rows": 1},
|
|
"partial_reasons": ["report_log_failed"]
|
|
});
|
|
|
|
let outcome = interpret_report_artifact_and_postprocess(
|
|
&artifact,
|
|
Some(&report_postprocess_xlsx()),
|
|
&workspace_root,
|
|
)
|
|
.unwrap();
|
|
|
|
assert!(outcome.success);
|
|
assert!(outcome.summary.contains("tq-lineloss-report"));
|
|
assert!(outcome.summary.contains("status=partial"));
|
|
assert!(outcome.summary.contains("detail_rows=1"));
|
|
assert!(outcome
|
|
.summary
|
|
.contains("partial_reasons=report_log_failed"));
|
|
assert!(outcome.summary.contains("export_path="));
|
|
assert_eq!(exported_xlsx_files(&workspace_root).len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn report_artifact_postprocess_skips_export_for_blocked_or_error_scene() {
|
|
for status in ["blocked", "error"] {
|
|
let workspace_root = temp_workspace(&format!("sgclaw-report-artifact-{status}"));
|
|
let artifact = json!({
|
|
"type": "report-artifact",
|
|
"report_name": "generic-report",
|
|
"status": status,
|
|
"columns": ["ORG_NAME"],
|
|
"rows": [{"ORG_NAME": "国网兰州供电公司"}],
|
|
"counts": {"rows": 1},
|
|
"reasons": ["login_required"]
|
|
});
|
|
|
|
let outcome = interpret_report_artifact_and_postprocess(
|
|
&artifact,
|
|
Some(&report_postprocess_xlsx()),
|
|
&workspace_root,
|
|
)
|
|
.unwrap();
|
|
|
|
assert!(!outcome.success, "{status} should fail");
|
|
assert!(outcome.summary.contains(&format!("status={status}")));
|
|
assert!(!outcome.summary.contains("export_path="));
|
|
assert!(exported_xlsx_files(&workspace_root).is_empty());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn report_artifact_postprocess_exports_with_columns_when_column_defs_are_absent() {
|
|
let workspace_root = temp_workspace("sgclaw-report-artifact-columns-fallback");
|
|
let artifact = json!({
|
|
"type": "report-artifact",
|
|
"report_name": "generic-report",
|
|
"status": "ok",
|
|
"columns": ["ORG_NAME", "VALUE"],
|
|
"rows": [{"ORG_NAME": "国网兰州供电公司", "VALUE": "42"}],
|
|
"counts": {"rows": 1}
|
|
});
|
|
|
|
let outcome = interpret_report_artifact_and_postprocess(
|
|
&artifact,
|
|
Some(&report_postprocess_xlsx()),
|
|
&workspace_root,
|
|
)
|
|
.unwrap();
|
|
|
|
assert!(outcome.success);
|
|
assert!(outcome.summary.contains("generic-report"));
|
|
assert!(outcome.summary.contains("detail_rows=1"));
|
|
assert!(outcome.summary.contains("export_path="));
|
|
assert_eq!(exported_xlsx_files(&workspace_root).len(), 1);
|
|
}
|