f7a720204a
- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用 - 添加所有子项目的完整源代码 - 保留原始 .git 为 .git.bak 备份
167 lines
5.7 KiB
Rust
167 lines
5.7 KiB
Rust
//! E2E integration tests for ACP management routes.
|
|
//!
|
|
//! Tests cover: agents list, agents/refresh, agents/test, health-check,
|
|
//! and session-bound routes (mode/model).
|
|
|
|
mod common;
|
|
|
|
use axum::http::StatusCode;
|
|
use serde_json::json;
|
|
use tower::ServiceExt;
|
|
|
|
use common::{body_json, build_app, get_with_token, json_with_token, setup_and_login};
|
|
|
|
// ── Global ACP routes ────────────────────────────────────────────
|
|
|
|
#[tokio::test]
|
|
async fn list_agents_returns_array() {
|
|
let (mut app, services) = build_app().await;
|
|
let (token, _csrf) = setup_and_login(&mut app, &services, "user1", "pass123").await;
|
|
|
|
let req = get_with_token("/api/agents", &token);
|
|
let resp = app.oneshot(req).await.unwrap();
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
|
|
|
let body = body_json(resp).await;
|
|
assert_eq!(body["success"], true);
|
|
assert!(body["data"].is_array());
|
|
let agents = body["data"].as_array().unwrap();
|
|
assert!(agents.iter().any(|a| a["agent_type"] == "nomi"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn refresh_agents_returns_array() {
|
|
let (mut app, services) = build_app().await;
|
|
let (token, csrf) = setup_and_login(&mut app, &services, "user1", "pass123").await;
|
|
|
|
let req = json_with_token("POST", "/api/agents/refresh", json!({}), &token, &csrf);
|
|
let resp = app.oneshot(req).await.unwrap();
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
|
|
|
let body = body_json(resp).await;
|
|
assert_eq!(body["success"], true);
|
|
assert!(body["data"].is_array());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_custom_agent_nonexistent_command() {
|
|
let (mut app, services) = build_app().await;
|
|
let (token, csrf) = setup_and_login(&mut app, &services, "user1", "pass123").await;
|
|
|
|
// Endpoint was renamed from /api/agents/test to /api/agents/custom/try-connect
|
|
// when the custom-agent CRUD routes were introduced. The new endpoint always
|
|
// returns HTTP 200 and encodes failure in the JSON body (step = "fail_cli" or
|
|
// "fail_acp"), so we assert on the body rather than the HTTP status.
|
|
let req = json_with_token(
|
|
"POST",
|
|
"/api/agents/custom/try-connect",
|
|
json!({ "command": "/nonexistent/path/to/agent" }),
|
|
&token,
|
|
&csrf,
|
|
);
|
|
let resp = app.oneshot(req).await.unwrap();
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
|
let json = common::body_json(resp).await;
|
|
assert_eq!(json["success"], true);
|
|
assert_eq!(json["data"]["step"], "fail_cli");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn health_check_returns_status() {
|
|
let (mut app, services) = build_app().await;
|
|
let (token, csrf) = setup_and_login(&mut app, &services, "user1", "pass123").await;
|
|
|
|
let req = json_with_token(
|
|
"POST",
|
|
"/api/agents/health-check",
|
|
json!({ "backend": "claude" }),
|
|
&token,
|
|
&csrf,
|
|
);
|
|
let resp = app.oneshot(req).await.unwrap();
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
|
|
|
let body = body_json(resp).await;
|
|
assert_eq!(body["success"], true);
|
|
// available is a boolean
|
|
assert!(body["data"]["available"].is_boolean());
|
|
// latency should be present
|
|
assert!(body["data"]["latency"].is_number());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn health_check_unknown_backend_reports_unavailable() {
|
|
let (mut app, services) = build_app().await;
|
|
let (token, csrf) = setup_and_login(&mut app, &services, "user1", "pass123").await;
|
|
|
|
// Same rationale as `detect_cli_unknown_backend_returns_null_path`:
|
|
// unknown backends are valid at the request layer and surface as
|
|
// `available: false` with an error string.
|
|
let req = json_with_token(
|
|
"POST",
|
|
"/api/agents/health-check",
|
|
json!({ "backend": "iFlow" }),
|
|
&token,
|
|
&csrf,
|
|
);
|
|
let resp = app.oneshot(req).await.unwrap();
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
|
let body = body_json(resp).await;
|
|
assert_eq!(body["success"], true);
|
|
assert_eq!(body["data"]["available"], false);
|
|
}
|
|
|
|
// ── Session-bound ACP routes (no active task → 404) ──────────────
|
|
|
|
#[tokio::test]
|
|
async fn get_mode_no_active_task() {
|
|
let (mut app, services) = build_app().await;
|
|
let (token, _csrf) = setup_and_login(&mut app, &services, "user1", "pass123").await;
|
|
|
|
let req = get_with_token("/api/conversations/nonexistent/mode", &token);
|
|
let resp = app.oneshot(req).await.unwrap();
|
|
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn set_mode_no_active_task() {
|
|
let (mut app, services) = build_app().await;
|
|
let (token, csrf) = setup_and_login(&mut app, &services, "user1", "pass123").await;
|
|
|
|
let req = json_with_token(
|
|
"PUT",
|
|
"/api/conversations/nonexistent/mode",
|
|
json!({ "mode": "code" }),
|
|
&token,
|
|
&csrf,
|
|
);
|
|
let resp = app.oneshot(req).await.unwrap();
|
|
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn get_model_no_active_task() {
|
|
let (mut app, services) = build_app().await;
|
|
let (token, _csrf) = setup_and_login(&mut app, &services, "user1", "pass123").await;
|
|
|
|
let req = get_with_token("/api/conversations/nonexistent/model", &token);
|
|
let resp = app.oneshot(req).await.unwrap();
|
|
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn set_model_no_active_task() {
|
|
let (mut app, services) = build_app().await;
|
|
let (token, csrf) = setup_and_login(&mut app, &services, "user1", "pass123").await;
|
|
|
|
let req = json_with_token(
|
|
"PUT",
|
|
"/api/conversations/nonexistent/model",
|
|
json!({ "model_id": "claude-sonnet-4" }),
|
|
&token,
|
|
&csrf,
|
|
);
|
|
let resp = app.oneshot(req).await.unwrap();
|
|
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
|
}
|