use backbone_core::http::*;
use backbone_core::entity::*;
use serde::{Serialize, Deserialize};
use uuid::Uuid;
// Test entity for integration testing
#[derive(Debug, Clone, Serialize, Deserialize)]
struct TestEntity {
id: Uuid,
name: String,
created_at: chrono::DateTime<chrono::Utc>,
updated_at: chrono::DateTime<chrono::Utc>,
deleted_at: Option<chrono::DateTime<chrono::Utc>>,
}
impl Entity for TestEntity {
fn id(&self) -> &Uuid {
&self.id
}
fn created_at(&self) -> chrono::DateTime<chrono::Utc> {
self.created_at
}
fn updated_at(&self) -> chrono::DateTime<chrono::Utc> {
self.updated_at
}
fn deleted_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
self.deleted_at
}
}
// Mock HTTP handler for testing
struct MockHttpHandler;
impl BackboneHttpHandler<TestEntity> for MockHttpHandler {
fn list(&self, _request: ListRequest) -> Result<ApiResponse<Vec<TestEntity>>> {
Ok(ApiResponse::success(vec![], Some("List successful".to_string())))
}
fn create(&self, _request: TestEntity) -> Result<ApiResponse<TestEntity>> {
let entity = TestEntity {
id: Uuid::new_v4(),
name: "Test Entity".to_string(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
};
Ok(ApiResponse::success(entity, Some("Entity created".to_string())))
}
fn get_by_id(&self, _id: &Uuid) -> Result<ApiResponse<TestEntity>> {
Ok(ApiResponse::success(TestEntity {
id: *_id,
name: "Test Entity".to_string(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
}, Some("Entity retrieved".to_string())))
}
fn update(&self, _id: &Uuid, _request: TestEntity) -> Result<ApiResponse<TestEntity>> {
Ok(ApiResponse::success(TestEntity {
id: *_id,
name: "Updated Entity".to_string(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
}, Some("Entity updated".to_string())))
}
fn partial_update(&self, _id: &Uuid, _request: std::collections::HashMap<String, String>) -> Result<ApiResponse<TestEntity>> {
Ok(ApiResponse::success(TestEntity {
id: *_id,
name: "Partially Updated".to_string(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
}, Some("Entity partially updated".to_string())))
}
fn soft_delete(&self, _id: &Uuid) -> Result<ApiResponse<()>> {
Ok(ApiResponse::success((), Some("Entity deleted".to_string())))
}
fn bulk_create(&self, _request: BulkCreateRequest<TestEntity>) -> Result<ApiResponse<BulkResponse<TestEntity>>> {
Ok(ApiResponse::success(BulkResponse {
items: vec![],
total: 0,
failed: 0,
errors: vec![],
}, Some("Bulk create successful".to_string())))
}
fn upsert(&self, _request: UpsertRequest<TestEntity>) -> Result<ApiResponse<TestEntity>> {
Ok(ApiResponse::success(TestEntity {
id: Uuid::new_v4(),
name: "Upserted Entity".to_string(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
}, Some("Entity upserted".to_string())))
}
fn list_deleted(&self, _request: ListRequest) -> Result<ApiResponse<Vec<TestEntity>>> {
Ok(ApiResponse::success(vec![], Some("List deleted successful".to_string())))
}
fn restore(&self, _id: &Uuid) -> Result<ApiResponse<TestEntity>> {
Ok(ApiResponse::success(TestEntity {
id: *_id,
name: "Restored Entity".to_string(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
}, Some("Entity restored".to_string())))
}
fn empty_trash(&self) -> Result<ApiResponse<()>> {
Ok(ApiResponse::success((), Some("Trash emptied".to_string())))
}
}
#[test]
fn test_api_response_success() {
let data = "test data";
let response = ApiResponse::success(data, Some("Success".to_string()));
assert_eq!(response.success, true);
assert_eq!(response.data, Some("test data"));
assert_eq!(response.message, Some("Success".to_string()));
assert_eq!(response.error, None);
}
#[test]
fn test_api_response_error() {
let response = ApiResponse::<String>::error("Error message".to_string());
assert_eq!(response.success, false);
assert_eq!(response.data, None);
assert_eq!(response.message, None);
assert_eq!(response.error, Some("Error message".to_string()));
}
#[test]
fn test_pagination_response() {
let response = PaginationResponse::new(100, 2, 20);
assert_eq!(response.total, 100);
assert_eq!(response.page, 2);
assert_eq!(response.limit, 20);
assert_eq!(response.total_pages, 5); // 100 / 20 = 5
}
#[test]
fn test_sort_order_default() {
let default_order = SortOrder::default();
match default_order {
SortOrder::Asc => assert!(true),
SortOrder::Desc => assert!(false),
}
}
#[test]
fn test_list_request_default() {
let request = ListRequest::default();
assert_eq!(request.page, Some(1));
assert_eq!(request.limit, Some(20));
assert_eq!(request.sort_by, None);
assert_eq!(request.filters, None);
}
#[tokio::test]
async fn test_mock_http_handler_all_endpoints() {
let handler = MockHttpHandler;
let test_id = Uuid::new_v4();
// Test all 11 endpoints
let list_result = handler.list(ListRequest::default());
assert!(list_result.is_ok());
let create_result = handler.create(TestEntity {
id: Uuid::new_v4(),
name: "Test".to_string(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
});
assert!(create_result.is_ok());
let get_result = handler.get_by_id(&test_id);
assert!(get_result.is_ok());
let update_result = handler.update(&test_id, TestEntity {
id: test_id,
name: "Updated".to_string(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
});
assert!(update_result.is_ok());
let partial_update_result = handler.partial_update(&test_id, std::collections::HashMap::new());
assert!(partial_update_result.is_ok());
let delete_result = handler.soft_delete(&test_id);
assert!(delete_result.is_ok());
let bulk_result = handler.bulk_create(BulkCreateRequest { items: vec![] });
assert!(bulk_result.is_ok());
let upsert_result = handler.upsert(UpsertRequest {
entity: TestEntity {
id: Uuid::new_v4(),
name: "Test".to_string(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
},
create_if_not_exists: true,
});
assert!(upsert_result.is_ok());
let list_deleted_result = handler.list_deleted(ListRequest::default());
assert!(list_deleted_result.is_ok());
let restore_result = handler.restore(&test_id);
assert!(restore_result.is_ok());
let empty_trash_result = handler.empty_trash();
assert!(empty_trash_result.is_ok());
}