-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathe2e_api_tests.rs
More file actions
225 lines (191 loc) · 7.5 KB
/
e2e_api_tests.rs
File metadata and controls
225 lines (191 loc) · 7.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
use axum_test::TestServer;
use serde_json::json;
const SESSION_TOKEN: &str = "sess_e7ce7abb623a46f68db69a12e995af21";
async fn create_test_server() -> TestServer {
use api::{create_router, AppState};
use std::sync::Arc;
// Load .env file
dotenvy::dotenv().ok();
// Load configuration
let config = config::Config::from_env();
// Create database connection
let db = database::Database::from_config(&config.database)
.await
.expect("Failed to connect to database");
// Run migrations
db.run_migrations().await.expect("Failed to run migrations");
// Get repositories
let user_repo = db.user_repository();
let session_repo = db.session_repository();
let oauth_repo = db.oauth_repository();
let conversation_repo = db.conversation_repository();
// Create services
let oauth_service = Arc::new(services::auth::OAuthServiceImpl::new(
oauth_repo.clone(),
session_repo.clone(),
user_repo.clone(),
config.oauth.google_client_id.clone(),
config.oauth.google_client_secret.clone(),
config.oauth.github_client_id.clone(),
config.oauth.github_client_secret.clone(),
config.oauth.redirect_uri.clone(),
));
let user_service = Arc::new(services::user::UserServiceImpl::new(user_repo));
// Initialize OpenAI proxy service
let mut proxy_service =
services::response::service::OpenAIProxy::new(config.openai.api_key.clone());
if let Some(base_url) = config.openai.base_url.clone() {
proxy_service = proxy_service.with_base_url(base_url);
}
let proxy_service = Arc::new(proxy_service);
// Initialize conversation service
let conversation_service =
Arc::new(services::conversation::service::ConversationServiceImpl::new(conversation_repo));
// Create application state
let app_state = AppState {
oauth_service: oauth_service as Arc<dyn services::auth::ports::OAuthService>,
user_service: user_service as Arc<dyn services::user::ports::UserService>,
session_repository: session_repo,
proxy_service: proxy_service as Arc<dyn services::response::ports::OpenAIProxyService>,
conversation_service: conversation_service
as Arc<dyn services::conversation::ports::ConversationService>,
redirect_uri: config.oauth.redirect_uri.clone(),
};
// Create router
let app = create_router(app_state);
// Create test server
TestServer::new(app).expect("Failed to create test server")
}
#[tokio::test]
#[ignore] // This makes real OpenAI API calls - run with: cargo test -- --ignored --nocapture
async fn test_conversation_workflow() {
let server = create_test_server().await;
println!("\n=== Test: Conversation Workflow ===");
// Step 1: Create a conversation using OpenAI's API
println!("1. Creating a conversation via OpenAI...");
let create_conv_body = json!({
"metadata": {"test": "e2e"}
});
let response = server
.post("/v1/conversations")
.add_header(
http::HeaderName::from_static("authorization"),
http::HeaderValue::from_str(&format!("Bearer {SESSION_TOKEN}")).unwrap(),
)
.json(&create_conv_body)
.await;
let status = response.status_code();
println!(" Status: {status}");
let conversation_id = if status.is_success() {
let body: serde_json::Value = response.json();
println!(" ✓ Conversation created successfully");
let conv_id = body
.get("id")
.and_then(|v| v.as_str())
.map(|s| s.to_string())
.expect("Conversation should have an ID");
println!(" Conversation ID: {conv_id}");
conv_id
} else {
let error_text = response.text();
println!(" ✗ Failed: {error_text}");
panic!("Failed to create conversation");
};
// Step 2: Add first response to the conversation
println!("\n2. Adding first response to the conversation...");
let request_body = json!({
"conversation": conversation_id,
"model": "gpt-4o",
"input": [
{
"type": "message",
"role": "user",
"content": "Say hello!"
}
]
});
let response = server
.post("/v1/responses")
.add_header(
http::HeaderName::from_static("authorization"),
http::HeaderValue::from_str(&format!("Bearer {SESSION_TOKEN}")).unwrap(),
)
.json(&request_body)
.await;
let status = response.status_code();
println!(" Status: {status}");
if status.is_success() {
let body: serde_json::Value = response.json();
println!(" ✓ First response created successfully");
println!(
" Response ID: {}",
body.get("id").unwrap_or(&json!("N/A"))
);
} else {
let error_text = response.text();
println!(" ✗ Failed: {error_text}");
panic!("Failed to create first response");
};
// Step 3: Add second response to the same conversation
println!("\n3. Adding second response to the conversation...");
let request_body = json!({
"conversation": conversation_id,
"model": "gpt-4o",
"input": [
{
"type": "message",
"role": "user",
"content": "Tell me a joke!"
}
]
});
let response = server
.post("/v1/responses")
.add_header(
http::HeaderName::from_static("authorization"),
http::HeaderValue::from_str(&format!("Bearer {SESSION_TOKEN}")).unwrap(),
)
.json(&request_body)
.await;
let status = response.status_code();
println!(" Status: {status}");
if status.is_success() {
let body: serde_json::Value = response.json();
println!(" ✓ Second response created successfully");
println!(
" Response ID: {}",
body.get("id").unwrap_or(&json!("N/A"))
);
} else {
let error_text = response.text();
println!(" ✗ Failed: {error_text}");
panic!("Failed to create second response");
};
// Step 4: List conversations (from our database)
println!("\n4. Listing conversations from database...");
let response = server
.get("/v1/conversations")
.add_header(
http::HeaderName::from_static("authorization"),
http::HeaderValue::from_str(&format!("Bearer {SESSION_TOKEN}")).unwrap(),
)
.await;
assert_eq!(response.status_code(), 200, "Should list conversations");
let conversations: Vec<serde_json::Value> = response.json();
println!("{conversations:?}");
println!(" Found {} total conversations", conversations.len());
// Find our conversation
let our_conv = conversations.iter().find(|c| c["id"] == conversation_id);
if let Some(conv) = our_conv {
println!(" ✓ Found our conversation in the list!");
println!(" ID: {}", conv["id"]);
println!(" Title: {:?}", conv["title"]);
println!(" Created: {}", conv["created_at"]);
println!(" Updated: {}", conv["updated_at"]);
} else {
println!(" ⚠ Our conversation not found in list");
println!(" This means conversation tracking may not be working properly");
}
println!("\n=== Test Complete ===");
println!("✅ Test passed: Created conversation, added response, and listed conversations successfully\n");
}