#![allow(
clippy::absolute_paths,
clippy::assertions_on_result_states,
clippy::expect_used,
clippy::panic_in_result_fn,
clippy::single_call_fn,
clippy::tests_outside_test_module,
clippy::unwrap_used,
reason = "integration tests use assertions, unwrap, and expect freely"
)]
use horizon_sdk::HorizonSdk;
use horizon_sdk::types::config::{CoverageConfig, IcebergConfig, PostgresConfig, SdkConfig};
use horizon_sdk::types::error::HorizonError;
#[tokio::test]
async fn builder_fails_without_postgres() {
let result = HorizonSdk::builder().build().await;
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(err.contains("Postgres configuration is required"));
}
#[tokio::test]
async fn builder_with_invalid_postgres_url_fails() {
let result = HorizonSdk::builder()
.with_postgres_url("not-a-url")
.build()
.await;
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(err.contains("invalid Postgres URL"));
}
#[tokio::test]
async fn builder_iceberg_without_kafka_fails() {
let config = SdkConfig {
horizon_api: None,
coverage: None,
iceberg: Some(IcebergConfig {
catalog_uri: "http://localhost:8181".to_owned(),
catalog_warehouse: None,
data_row_table: "horizon.data_row".to_owned(),
metadata_row_table: "horizon.metadata_row".to_owned(),
credential: None,
oauth2_server_uri: None,
scope: None,
}),
kafka: None,
postgres: test_postgres_config(),
};
let result = HorizonSdk::builder().with_config(config).build().await;
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("Kafka"),
"error should mention Kafka subsystem: {err}"
);
assert!(
err.contains("Iceberg"),
"error should mention Iceberg dependency: {err}"
);
}
#[test]
fn load_config_fails_for_missing_file() {
let result = horizon_sdk::load_config(Some("/nonexistent/config.toml"));
assert!(result.is_err());
}
#[tokio::test]
#[ignore = "requires live Postgres"]
async fn build_with_postgres_only() -> std::result::Result<(), HorizonError> {
let sdk = HorizonSdk::builder()
.with_postgres_config(live_postgres_config())
.build()
.await?;
assert!(!sdk.has_iceberg());
assert!(sdk.coverage().is_none());
let debug = format!("{sdk:?}");
assert!(debug.contains("HorizonSdk"));
assert!(debug.contains("iceberg_enabled: false"));
Ok(())
}
#[tokio::test]
#[ignore = "requires live Postgres"]
async fn build_with_postgres_and_coverage() -> std::result::Result<(), HorizonError> {
let sdk = HorizonSdk::builder()
.with_postgres_config(live_postgres_config())
.with_coverage(CoverageConfig {
api_key: None,
base_url: "http://localhost:9999".to_owned(),
timeout_secs: 5,
})
.build()
.await?;
assert!(sdk.coverage().is_some());
assert_eq!(sdk.coverage().unwrap().base_url(), "http://localhost:9999");
Ok(())
}
#[tokio::test]
#[ignore = "requires live Postgres"]
async fn build_with_postgres_url() -> std::result::Result<(), HorizonError> {
let url = std::env::var("DATABASE_URL").unwrap_or_else(|_| {
"postgresql://horizon_owner:insecure_password@localhost:5432/horizon?sslmode=disable"
.to_owned()
});
let sdk = HorizonSdk::builder()
.with_postgres_url(&url)
.build()
.await?;
assert!(!sdk.has_iceberg());
Ok(())
}
#[tokio::test]
#[ignore = "requires live Postgres"]
async fn facade_delegates_to_postgres_repo() -> std::result::Result<(), HorizonError> {
let sdk = HorizonSdk::builder()
.with_postgres_config(live_postgres_config())
.build()
.await?;
let _platforms = sdk.postgres().list_platforms().await?;
Ok(())
}
#[tokio::test]
#[ignore = "requires live Postgres"]
async fn build_with_organization_id() -> std::result::Result<(), HorizonError> {
let org_id = uuid::Uuid::new_v4();
let sdk = HorizonSdk::builder()
.with_postgres_config(live_postgres_config())
.with_organization_id(org_id)
.build()
.await?;
assert!(!sdk.has_iceberg());
Ok(())
}
fn test_postgres_config() -> PostgresConfig {
PostgresConfig {
database: "horizon".to_owned(),
host: "localhost".to_owned(),
password: "test".to_owned(),
port: 5432,
possible_organization_id: None,
role: None,
sslmode: "disable".to_owned(),
user: "test".to_owned(),
}
}
fn live_postgres_config() -> PostgresConfig {
let url = std::env::var("DATABASE_URL").unwrap_or_else(|_| {
"postgresql://horizon_owner:insecure_password@localhost:5432/horizon?sslmode=disable"
.to_owned()
});
let parsed = url::Url::parse(&url).expect("valid DATABASE_URL");
PostgresConfig {
database: parsed.path().trim_start_matches('/').to_owned(),
host: parsed.host_str().unwrap_or("localhost").to_owned(),
password: parsed.password().unwrap_or("insecure_password").to_owned(),
port: parsed.port().unwrap_or(5432),
possible_organization_id: None,
role: None,
sslmode: "disable".to_owned(),
user: if parsed.username().is_empty() {
"horizon_owner".to_owned()
} else {
parsed.username().to_owned()
},
}
}