use akribes_sdk::AkribesClient;
use akribes_sdk::models::McpOrigin;
use mockito::Server;
fn make_client(server: &Server) -> AkribesClient {
AkribesClient::builder(server.url())
.project_id(1)
.name("test-app")
.id("test-id")
.build()
}
#[tokio::test]
async fn test_list_servers() {
let mut server = Server::new_async().await;
let body = r#"[
{"alias":"github","url":"https://api.githubcopilot.com/mcp/","origin":"env","is_registry":false,"status":"connected","tool_count":12},
{"alias":"context7","url":"https://mcp.context7.com/mcp","origin":"db","is_registry":true,"status":"degraded","tool_count":0}
]"#;
let _m = server
.mock("GET", "/projects/1/mcp/servers")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(body)
.create_async()
.await;
let client = make_client(&server);
let servers = client.project(1).mcp().list_servers().await.unwrap();
assert_eq!(servers.len(), 2);
assert_eq!(servers[0].alias, "github");
assert!(matches!(servers[0].origin, McpOrigin::Env));
assert_eq!(servers[0].tool_count, 12);
assert!(matches!(servers[1].origin, McpOrigin::Db));
assert!(servers[1].is_registry);
}
#[tokio::test]
async fn test_list_tools() {
let mut server = Server::new_async().await;
let body = r#"[
{"qualified_name":"github.create_issue","server_alias":"github","description":"Create an issue","input_schema":{"type":"object","properties":{}}},
{"qualified_name":"ctx.search","server_alias":"context7","input_schema":{"type":"object"}}
]"#;
let _m = server
.mock("GET", "/projects/1/mcp/tools")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(body)
.create_async()
.await;
let client = make_client(&server);
let tools = client.project(1).mcp().list_tools().await.unwrap();
assert_eq!(tools.len(), 2);
assert_eq!(tools[0].qualified_name, "github.create_issue");
assert_eq!(tools[0].description.as_deref(), Some("Create an issue"));
assert!(tools[1].description.is_none());
}
#[tokio::test]
async fn test_health() {
let mut server = Server::new_async().await;
let body = r#"{"status":"connected","last_error":null,"last_check_at":"2024-01-01T00:00:00Z"}"#;
let _m = server
.mock("GET", "/projects/1/mcp/servers/github/health")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(body)
.create_async()
.await;
let client = make_client(&server);
let health = client.project(1).mcp().health("github").await.unwrap();
assert_eq!(health.status, "connected");
assert_eq!(
health.last_check_at.as_deref(),
Some("2024-01-01T00:00:00Z")
);
assert!(health.last_error.is_none());
}
#[tokio::test]
async fn test_refresh_404_surfaces_http_status() {
let mut server = Server::new_async().await;
let _m = server
.mock("POST", "/projects/1/mcp/servers/nope/refresh")
.with_status(404)
.with_body("server not found")
.create_async()
.await;
let client = make_client(&server);
let err = client.project(1).mcp().refresh("nope").await.unwrap_err();
match err {
akribes_sdk::AkribesError::HttpStatus { status, .. } => assert_eq!(status, 404),
other => panic!("expected HttpStatus, got {:?}", other),
}
}
#[tokio::test]
async fn test_refresh() {
let mut server = Server::new_async().await;
let body = r#"{"refreshed":true,"alias":"github","tool_count":12}"#;
let _m = server
.mock("POST", "/projects/1/mcp/servers/github/refresh")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(body)
.create_async()
.await;
let client = make_client(&server);
let result = client.project(1).mcp().refresh("github").await.unwrap();
assert!(result.refreshed);
assert_eq!(result.alias, "github");
assert_eq!(result.tool_count, 12);
}
#[tokio::test]
async fn test_drift() {
let mut server = Server::new_async().await;
let body = r#"{"drifted":true,"added":["new_tool"],"removed":["old_tool"]}"#;
let _m = server
.mock("GET", "/projects/1/mcp/servers/github/drift")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(body)
.create_async()
.await;
let client = make_client(&server);
let drift = client.project(1).mcp().drift("github").await.unwrap();
assert!(drift.drifted);
assert_eq!(drift.added, vec!["new_tool"]);
assert_eq!(drift.removed, vec!["old_tool"]);
}
#[tokio::test]
async fn test_drift_not_pinned() {
let mut server = Server::new_async().await;
let body = r#"{"drifted":false,"added":[],"removed":[],"reason":"not_pinned"}"#;
let _m = server
.mock("GET", "/projects/1/mcp/servers/github/drift")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(body)
.create_async()
.await;
let client = make_client(&server);
let drift = client.project(1).mcp().drift("github").await.unwrap();
assert!(!drift.drifted);
assert_eq!(drift.reason.as_deref(), Some("not_pinned"));
}
#[tokio::test]
async fn test_health_encodes_alias() {
let mut server = Server::new_async().await;
let body = r#"{"status":"offline"}"#;
let _m = server
.mock("GET", "/projects/1/mcp/servers/weird%2Falias/health")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(body)
.create_async()
.await;
let client = make_client(&server);
let health = client.project(1).mcp().health("weird/alias").await.unwrap();
assert_eq!(health.status, "offline");
}