use backstage_client::{entities::Entity, BackstageClient, ClientError};
use std::collections::HashMap;
#[tokio::test]
async fn test_client_creation_with_valid_url() {
let client = BackstageClient::new("https://demo.backstage.io", "test-token");
assert!(client.is_ok());
}
#[tokio::test]
async fn test_client_creation_with_invalid_url() {
let client = BackstageClient::new("not-a-valid-url", "test-token");
assert!(client.is_err());
if let Err(ClientError::InvalidUrl(_)) = client {
} else {
panic!("Expected InvalidUrl error");
}
}
#[tokio::test]
async fn test_client_creation_with_empty_token() {
let client = BackstageClient::new("https://demo.backstage.io", "");
assert!(client.is_err());
if let Err(ClientError::Authentication(_)) = client {
} else {
panic!("Expected Authentication error");
}
}
#[tokio::test]
async fn test_client_creation_with_whitespace_token() {
let client = BackstageClient::new("https://demo.backstage.io", " ");
assert!(client.is_err());
if let Err(ClientError::Authentication(_)) = client {
} else {
panic!("Expected Authentication error");
}
}
#[tokio::test]
async fn test_filters_validation() {
let client = BackstageClient::new("https://demo.backstage.io", "test-token").unwrap();
let mut invalid_filters = HashMap::new();
invalid_filters.insert("".to_string(), "Component".to_string());
let result = client.fetch_entities::<Entity>(Some(invalid_filters)).await;
assert!(result.is_err());
if let Err(ClientError::InvalidFilter(_)) = result {
} else {
panic!("Expected InvalidFilter error");
}
}
#[tokio::test]
async fn test_filters_validation_empty_value() {
let client = BackstageClient::new("https://demo.backstage.io", "test-token").unwrap();
let mut invalid_filters = HashMap::new();
invalid_filters.insert("kind".to_string(), "".to_string());
let result = client.fetch_entities::<Entity>(Some(invalid_filters)).await;
assert!(result.is_err());
if let Err(ClientError::InvalidFilter(_)) = result {
} else {
panic!("Expected InvalidFilter error");
}
}
#[test]
fn test_entity_methods() {
}
#[test]
fn test_url_normalization() {
let _client1 = BackstageClient::new("https://demo.backstage.io/", "test-token").unwrap();
let _client2 = BackstageClient::new("https://demo.backstage.io", "test-token").unwrap();
}
#[cfg(feature = "integration-tests")]
mod mock_tests {
use super::*;
use mockito::Matcher;
#[tokio::test]
async fn test_fetch_entities_success() {
let mut server = mockito::Server::new_async().await;
let mock_response = r#"[
{
"apiVersion": "backstage.io/v1alpha1",
"kind": "Component",
"metadata": {
"name": "test-component",
"namespace": "default"
},
"spec": {
"type": "service",
"owner": "team-a",
"lifecycle": "production"
}
}
]"#;
let _m = server
.mock("GET", "/api/catalog/entities")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(mock_response)
.create_async()
.await;
let client = BackstageClient::new(&server.url(), "test-token").unwrap();
let result = client.fetch_entities::<Entity>(None).await;
assert!(result.is_ok());
let entities = result.unwrap();
assert_eq!(entities.len(), 1);
}
#[tokio::test]
async fn test_fetch_entities_unauthorized() {
let mut server = mockito::Server::new_async().await;
let _m = server
.mock("GET", "/api/catalog/entities")
.with_status(401)
.with_header("content-type", "application/json")
.with_body(r#"{"error": "Unauthorized"}"#)
.create_async()
.await;
let client = BackstageClient::new(&server.url(), "invalid-token").unwrap();
let result = client.fetch_entities::<Entity>(None).await;
assert!(result.is_err());
if let Err(ClientError::Authentication(_)) = result {
} else {
panic!("Expected Authentication error");
}
}
#[tokio::test]
async fn test_fetch_entities_with_filters() {
let mut server = mockito::Server::new_async().await;
let _m = server
.mock(
"GET",
Matcher::Regex(r"^/api/catalog/entities\?filter=.*".to_string()),
)
.with_status(200)
.with_header("content-type", "application/json")
.with_body("[]")
.create_async()
.await;
let client = BackstageClient::new(&server.url(), "test-token").unwrap();
let mut filters = HashMap::new();
filters.insert("kind".to_string(), "Component".to_string());
let result = client.fetch_entities::<Entity>(Some(filters)).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_get_entity_success() {
let mut server = mockito::Server::new_async().await;
let mock_response = r#"{
"apiVersion": "backstage.io/v1alpha1",
"kind": "Component",
"metadata": {
"name": "test-component",
"namespace": "default"
},
"spec": {
"type": "service",
"owner": "team-a",
"lifecycle": "production"
}
}"#;
let _m = server
.mock(
"GET",
"/api/catalog/entities/by-name/component%3Adefault%2Ftest-component",
)
.with_status(200)
.with_header("content-type", "application/json")
.with_body(mock_response)
.create_async()
.await;
let client = BackstageClient::new(&server.url(), "test-token").unwrap();
let result = client
.get_entity::<Entity>("Component", None, "test-component")
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_get_entity_not_found() {
let mut server = mockito::Server::new_async().await;
let _m = server
.mock(
"GET",
"/api/catalog/entities/by-name/component%3Adefault%2Fnonexistent",
)
.with_status(404)
.with_header("content-type", "application/json")
.with_body(r#"{"error": "Entity not found"}"#)
.create_async()
.await;
let client = BackstageClient::new(&server.url(), "test-token").unwrap();
let result = client
.get_entity::<Entity>("Component", None, "nonexistent")
.await;
assert!(result.is_err());
if let Err(ClientError::ApiError { status: 404, .. }) = result {
} else {
panic!("Expected 404 API error");
}
}
}