use super::*;
#[test]
fn sdk_migrate_report_aggregates_failure_groups_and_rollback_suggestions() {
let root = temp_dir("sdk-migrate-report-root").expect("create temp sdk report root");
let report = temp_path("sdk-migrate-report", "json");
let init = run_cli(&[
"sdk",
"init",
"demo_sdk_report_ok",
"--template",
"action",
"--output",
root.to_str().expect("utf-8 path"),
]);
assert!(init.status.success(), "stderr: {}", init.stderr);
let ok_dir = root.join("demo_sdk_report_ok");
let bad_dir = root.join("demo_sdk_report_missing");
let projects_arg = format!(
"{},{}",
ok_dir.to_str().expect("utf-8 path"),
bad_dir.to_str().expect("utf-8 path")
);
let batch = run_cli(&[
"sdk",
"migrate-batch",
"--projects",
projects_arg.as_str(),
"--target-schema",
"4",
"--output",
report.to_str().expect("utf-8 path"),
"--json",
]);
assert!(!batch.status.success(), "batch should contain one failure");
let summary = run_cli(&[
"sdk",
"migrate-report",
"--batch-report",
report.to_str().expect("utf-8 path"),
"--json",
]);
assert!(summary.status.success(), "stderr: {}", summary.stderr);
let payload: Value = serde_json::from_str(&summary.stdout).expect("parse migrate-report json");
assert_eq!(
payload.get("api_version").and_then(Value::as_str),
Some("robotrt.sdk.migrate-report.v1")
);
assert!(
!payload["result"]["failure_groups"]
.as_object()
.expect("failure_groups object")
.is_empty()
);
assert!(
payload["result"]["failure_code_distribution"]
.as_object()
.expect("failure code distribution object")
.contains_key("E_PROJECT_NOT_FOUND")
);
assert_eq!(
payload["result"]["failure_severity_distribution"]["critical"].as_u64(),
Some(1)
);
assert!(
!payload["result"]["rollback_suggestions"]
.as_array()
.expect("rollback suggestions array")
.is_empty()
);
}
#[test]
fn sdk_migrate_report_maps_warn_and_info_severity_buckets() {
let report = temp_path("sdk-migrate-report-severity", "json");
let report_payload = serde_json::json!({
"api_version": "robotrt.sdk.migrate-batch.v1",
"kind": "sdk_migrate_batch",
"result": {
"projects": [
{
"project_dir": "/tmp/demo_warn",
"status": "error",
"error": "unsupported target schema 99 (latest supported: 4)",
"to_schema_version": 99
},
{
"project_dir": "/tmp/demo_info",
"status": "error",
"error": "custom pipeline timeout",
"to_schema_version": 4
},
{
"project_dir": "/tmp/demo_ok",
"status": "ok",
"backup_path": "/tmp/demo_ok/robotrt.toml.bak",
"to_schema_version": 4
}
]
}
});
fs::write(
&report,
serde_json::to_string_pretty(&report_payload).expect("serialize migrate report fixture"),
)
.expect("write migrate report fixture");
let summary = run_cli(&[
"sdk",
"migrate-report",
"--batch-report",
report.to_str().expect("utf-8 path"),
"--json",
]);
assert!(summary.status.success(), "stderr: {}", summary.stderr);
let payload: Value = serde_json::from_str(&summary.stdout).expect("parse migrate-report json");
assert_eq!(
payload["result"]["failure_code_distribution"]["E_UNSUPPORTED_TARGET_SCHEMA"].as_u64(),
Some(1)
);
assert_eq!(
payload["result"]["failure_code_distribution"]["E_UNKNOWN"].as_u64(),
Some(1)
);
assert_eq!(
payload["result"]["failure_severity_distribution"]["warn"].as_u64(),
Some(1)
);
assert_eq!(
payload["result"]["failure_severity_distribution"]["info"].as_u64(),
Some(1)
);
}
#[test]
fn sdk_migrate_report_supports_severity_map_override() {
let report = temp_path("sdk-migrate-report-severity-override", "json");
let severity_map = temp_path("sdk-migrate-report-severity-map", "json");
let report_payload = serde_json::json!({
"api_version": "robotrt.sdk.migrate-batch.v1",
"kind": "sdk_migrate_batch",
"result": {
"projects": [
{
"project_dir": "/tmp/demo_override",
"status": "error",
"error": "project dir not found: /tmp/demo_override",
"to_schema_version": 4
}
]
}
});
fs::write(
&report,
serde_json::to_string_pretty(&report_payload).expect("serialize migrate report fixture"),
)
.expect("write migrate report fixture");
let severity_payload = serde_json::json!({
"code_to_severity": {
"E_PROJECT_NOT_FOUND": "info"
}
});
fs::write(
&severity_map,
serde_json::to_string_pretty(&severity_payload).expect("serialize severity map fixture"),
)
.expect("write severity map fixture");
let summary = run_cli(&[
"sdk",
"migrate-report",
"--batch-report",
report.to_str().expect("utf-8 path"),
"--severity-map",
severity_map.to_str().expect("utf-8 path"),
"--json",
]);
assert!(summary.status.success(), "stderr: {}", summary.stderr);
let payload: Value =
serde_json::from_str(&summary.stdout).expect("parse migrate-report severity override json");
assert_eq!(
payload["query"]["severity_map"].as_str(),
severity_map.to_str()
);
assert_eq!(
payload["result"]["failure_severity_distribution"]["info"].as_u64(),
Some(1)
);
}
#[test]
fn sdk_retry_failed_requires_batch_report_argument() {
let output = run_cli(&["sdk", "retry-failed", "--json"]);
assert!(!output.status.success(), "stdout: {}", output.stdout);
assert!(
output
.stderr
.contains("missing --batch-report for sdk retry-failed"),
"stderr: {}",
output.stderr
);
}
#[test]
fn sdk_retry_failed_rejects_report_without_failed_projects() {
let root = temp_dir("sdk-retry-no-failure-root").expect("create retry no-failure root");
let report = temp_path("sdk-retry-no-failure-report", "json");
let init = run_cli(&[
"sdk",
"init",
"demo_sdk_retry_clean",
"--template",
"local",
"--output",
root.to_str().expect("utf-8 path"),
]);
assert!(init.status.success(), "stderr: {}", init.stderr);
let batch = run_cli(&[
"sdk",
"migrate-batch",
"--projects",
root.join("demo_sdk_retry_clean")
.to_str()
.expect("utf-8 path"),
"--target-schema",
"4",
"--output",
report.to_str().expect("utf-8 path"),
"--json",
]);
assert!(batch.status.success(), "stderr: {}", batch.stderr);
let retry = run_cli(&[
"sdk",
"retry-failed",
"--batch-report",
report.to_str().expect("utf-8 path"),
"--json",
]);
assert!(!retry.status.success(), "stdout: {}", retry.stdout);
assert!(
retry
.stderr
.contains("no failed projects found in batch report"),
"stderr: {}",
retry.stderr
);
}
#[test]
fn sdk_migrate_report_rejects_invalid_report_shape() {
let bad_report = temp_path("sdk-migrate-report-invalid-shape", "json");
fs::write(
&bad_report,
serde_json::json!({"api_version": "x", "result": {"oops": []}}).to_string(),
)
.expect("write invalid shape report");
let output = run_cli(&[
"sdk",
"migrate-report",
"--batch-report",
bad_report.to_str().expect("utf-8 path"),
"--json",
]);
assert!(!output.status.success(), "stdout: {}", output.stdout);
assert!(
output.stderr.contains("missing result.projects array"),
"stderr: {}",
output.stderr
);
}
#[test]
fn sdk_rollback_batch_rejects_invalid_report_json() {
let bad_report = temp_path("sdk-rollback-batch-invalid-json", "json");
fs::write(&bad_report, "{ this is not valid json").expect("write invalid json report");
let output = run_cli(&[
"sdk",
"rollback-batch",
"--batch-report",
bad_report.to_str().expect("utf-8 path"),
"--json",
]);
assert!(!output.status.success(), "stdout: {}", output.stdout);
assert!(
output.stderr.contains("parse") && output.stderr.contains("failed"),
"stderr: {}",
output.stderr
);
}