c62d8daea8
Move all 29 workspace members from packages/<name>/ to crates/<name>/. Updates: workspace Cargo.toml (members + path deps), justfile, root CLAUDE.md, scripts/build/CARGO_INSTALL.md, docs/architecture/crates.md (renamed from packages.md), structural references in docs/architecture and docs/configuration, per-crate CLAUDE.md self-references. Historical plans, reports, and building/ docs are left untouched. No behavior change; just check-all stays green and fermata tests pass.
160 lines
5.3 KiB
Rust
160 lines
5.3 KiB
Rust
//! Integration tests for the ACP JSON-RPC server.
|
|
//!
|
|
//! These tests verify that the server correctly handles JSON-RPC requests
|
|
//! over HTTP and returns proper responses.
|
|
|
|
use dirigate::acp::model::{JsonRpcError, JsonRpcRequest, JsonRpcResponse};
|
|
use dirigate::acp::server::AcpServer;
|
|
use dirigate::fixture::types::*;
|
|
use dirigate::{MockerConfig, MockerState};
|
|
use std::collections::HashMap;
|
|
use std::sync::Arc;
|
|
|
|
/// Helper to create a minimal test fixture with a template session.
|
|
fn create_test_fixture_with_template() -> Fixture {
|
|
Fixture {
|
|
version: "0.1".to_string(),
|
|
sessions: vec![Session {
|
|
id: "test-template".to_string(),
|
|
title: "Test Template Session".to_string(),
|
|
created_at: "2025-01-01T00:00:00Z".to_string(),
|
|
participants: vec![
|
|
Participant {
|
|
id: "user-1".to_string(),
|
|
kind: ParticipantKind::User,
|
|
display_name: Some("Test User".to_string()),
|
|
},
|
|
Participant {
|
|
id: "assistant-1".to_string(),
|
|
kind: ParticipantKind::Assistant,
|
|
display_name: Some("Test Assistant".to_string()),
|
|
},
|
|
],
|
|
messages: vec![],
|
|
behavior: None,
|
|
}],
|
|
responders: Responders {
|
|
keyword_map: HashMap::new(),
|
|
default_strategy: ResponderStrategy::Echo,
|
|
random: None,
|
|
},
|
|
streaming: Streaming {
|
|
enabled: true,
|
|
tokens_per_chunk: 5,
|
|
chunk_interval_ms: 100,
|
|
jitter_ms: Some(10),
|
|
},
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_server_initialize_request() {
|
|
// Create state
|
|
let config = MockerConfig::default();
|
|
let fixtures = create_test_fixture_with_template();
|
|
let state = Arc::new(MockerState::new(config, fixtures));
|
|
|
|
// Create server on a random port
|
|
let server = AcpServer::new(state.clone(), 0);
|
|
|
|
// Start server in background
|
|
tokio::spawn(async move {
|
|
let _ = server.serve().await;
|
|
});
|
|
|
|
// Give server time to start
|
|
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
|
|
|
|
// Note: We can't actually test the HTTP endpoint without binding to a known port
|
|
// This test verifies the server compiles and runs without panicking
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_jsonrpc_initialize_response_format() {
|
|
// Create a mock initialize request
|
|
let request = JsonRpcRequest::new(
|
|
"initialize",
|
|
Some(serde_json::json!({
|
|
"protocol_version": "0.1",
|
|
"client_capabilities": {}
|
|
})),
|
|
1,
|
|
);
|
|
|
|
// Verify request serialization
|
|
let json = serde_json::to_string(&request).unwrap();
|
|
assert!(json.contains("\"jsonrpc\":\"2.0\""));
|
|
assert!(json.contains("\"method\":\"initialize\""));
|
|
assert!(json.contains("\"id\":1"));
|
|
|
|
// Parse it back
|
|
let parsed: JsonRpcRequest = serde_json::from_str(&json).unwrap();
|
|
assert_eq!(parsed.method, "initialize");
|
|
assert_eq!(parsed.jsonrpc, "2.0");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_jsonrpc_session_new_response_format() {
|
|
// Create a mock session/new request
|
|
let request = JsonRpcRequest::new(
|
|
"session/new",
|
|
Some(serde_json::json!({
|
|
"template_id": "test-template"
|
|
})),
|
|
2,
|
|
);
|
|
|
|
// Verify request serialization
|
|
let json = serde_json::to_string(&request).unwrap();
|
|
assert!(json.contains("\"jsonrpc\":\"2.0\""));
|
|
assert!(json.contains("\"method\":\"session/new\""));
|
|
assert!(json.contains("\"template_id\":\"test-template\""));
|
|
assert!(json.contains("\"id\":2"));
|
|
|
|
// Parse it back
|
|
let parsed: JsonRpcRequest = serde_json::from_str(&json).unwrap();
|
|
assert_eq!(parsed.method, "session/new");
|
|
assert_eq!(parsed.jsonrpc, "2.0");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_jsonrpc_error_response_format() {
|
|
// Create an error response
|
|
let error = JsonRpcError::method_not_found("unknown_method");
|
|
let response = JsonRpcResponse::error(error, Some(serde_json::json!(1)));
|
|
|
|
// Verify response serialization
|
|
let json = serde_json::to_string(&response).unwrap();
|
|
assert!(json.contains("\"jsonrpc\":\"2.0\""));
|
|
assert!(json.contains("\"error\""));
|
|
assert!(json.contains("-32601")); // Method not found code
|
|
assert!(!json.contains("\"result\"")); // Should not have result field
|
|
|
|
// Parse it back
|
|
let parsed: JsonRpcResponse = serde_json::from_str(&json).unwrap();
|
|
assert!(parsed.error.is_some());
|
|
assert!(parsed.result.is_none());
|
|
assert_eq!(parsed.error.unwrap().code, -32601);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_jsonrpc_success_response_format() {
|
|
// Create a success response
|
|
let result = serde_json::json!({
|
|
"session_id": "test-session-123"
|
|
});
|
|
let response = JsonRpcResponse::success(result, Some(serde_json::json!(1)));
|
|
|
|
// Verify response serialization
|
|
let json = serde_json::to_string(&response).unwrap();
|
|
assert!(json.contains("\"jsonrpc\":\"2.0\""));
|
|
assert!(json.contains("\"result\""));
|
|
assert!(json.contains("\"session_id\":\"test-session-123\""));
|
|
assert!(!json.contains("\"error\"")); // Should not have error field
|
|
|
|
// Parse it back
|
|
let parsed: JsonRpcResponse = serde_json::from_str(&json).unwrap();
|
|
assert!(parsed.result.is_some());
|
|
assert!(parsed.error.is_none());
|
|
}
|