use std::path::PathBuf;
use greentic_ext_runtime::{DiscoveryPaths, ExtensionRuntime, RuntimeConfig};
fn load_rt_from_pack() -> Option<(tempfile::TempDir, ExtensionRuntime, String)> {
let raw = std::env::var("GTDX_TEST_DEPLOY_GTXPACK").ok()?;
let pack = PathBuf::from(&raw);
if !pack.exists() {
eprintln!(
"skipping: GTDX_TEST_DEPLOY_GTXPACK points to non-existent file: {}",
pack.display()
);
return None;
}
let tmp = tempfile::TempDir::new().unwrap();
let ext_dir = tmp.path().join("ext");
greentic_extension_sdk_testing::unpack_to_dir(&pack, &ext_dir).unwrap();
let config = RuntimeConfig::from_paths(DiscoveryPaths::new(tmp.path().to_path_buf()));
let mut rt = ExtensionRuntime::new(config).unwrap();
rt.register_loaded_from_dir(&ext_dir).unwrap();
let id = rt
.loaded()
.keys()
.next()
.map(|k| k.as_str().to_string())
.expect("at least one extension loaded");
Some((tmp, rt, id))
}
#[test]
fn list_targets_returns_non_empty_for_deploy_extension() {
let Some((_tmp, rt, id)) = load_rt_from_pack() else {
eprintln!("skipping: GTDX_TEST_DEPLOY_GTXPACK not set.");
return;
};
let targets = rt.list_targets(&id).expect("list_targets should succeed");
assert!(!targets.is_empty(), "expected at least one target");
let first = &targets[0];
assert!(!first.id.is_empty());
assert!(!first.display_name.is_empty());
}
#[test]
fn credential_schema_returns_valid_json_schema() {
let Some((_tmp, rt, id)) = load_rt_from_pack() else {
eprintln!("skipping: GTDX_TEST_DEPLOY_GTXPACK not set.");
return;
};
let targets = rt.list_targets(&id).unwrap();
let target_id = &targets[0].id;
let schema = rt
.credential_schema(&id, target_id)
.expect("credential_schema should succeed");
let parsed: serde_json::Value =
serde_json::from_str(&schema).expect("schema should be valid JSON");
assert_eq!(
parsed.get("type").and_then(|v| v.as_str()),
Some("object"),
"credential schema top-level type should be 'object', got: {schema}"
);
}
#[test]
fn validate_credentials_returns_diagnostics_slice() {
let Some((_tmp, rt, id)) = load_rt_from_pack() else {
eprintln!("skipping: GTDX_TEST_DEPLOY_GTXPACK not set.");
return;
};
let targets = rt.list_targets(&id).unwrap();
let target_id = &targets[0].id;
let result = rt
.validate_credentials(&id, target_id, r"{}")
.expect("validate_credentials should succeed");
for d in &result {
assert!(
!d.message.is_empty(),
"diagnostic message should be non-empty"
);
}
}
#[test]
fn deploy_on_mode_a_extension_surfaces_typed_internal_error() {
let Some((_tmp, rt, id)) = load_rt_from_pack() else {
eprintln!("skipping: GTDX_TEST_DEPLOY_GTXPACK not set.");
return;
};
let req = greentic_ext_runtime::DeployRequest {
target_id: "anything".into(),
artifact_bytes: vec![],
credentials_json: "{}".into(),
config_json: "{}".into(),
deployment_name: "smoke".into(),
};
match rt.deploy(&id, req) {
Err(greentic_ext_runtime::RuntimeError::Deploy(
greentic_ext_runtime::DeployExtensionError::Internal(msg),
)) => assert!(!msg.is_empty(), "Mode A stub should carry a message"),
other => panic!("expected Deploy(Internal), got {other:?}"),
}
}