use elif_http::{routing::router::Router, *};
use elif_testing::prelude::*;
use serde::{Deserialize, Serialize};
use serde_json::json;
use tokio::time::Duration;
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct User {
id: u32,
name: String,
email: String,
}
#[derive(Deserialize)]
struct CreateUserRequest {
name: String,
email: String,
}
#[derive(Deserialize)]
struct UserQuery {
limit: Option<u32>,
offset: Option<u32>,
}
async fn get_users(request: ElifRequest) -> HttpResult<ElifResponse> {
let query: UserQuery = request.query().unwrap_or(UserQuery {
limit: Some(10),
offset: Some(0),
});
let users = vec![
User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
},
User {
id: 2,
name: "Bob".to_string(),
email: "bob@example.com".to_string(),
},
];
let limited_users: Vec<User> = users
.into_iter()
.skip(query.offset.unwrap_or(0) as usize)
.take(query.limit.unwrap_or(10) as usize)
.collect();
ElifResponse::ok().json(&json!({
"users": limited_users,
"total": 2,
"limit": query.limit,
"offset": query.offset
}))
}
async fn create_user(request: ElifRequest) -> HttpResult<ElifResponse> {
let create_req: CreateUserRequest = request.json()?;
let user = User {
id: 42,
name: create_req.name,
email: create_req.email,
};
ElifResponse::created().json(&json!({
"user": user,
"message": "User created successfully"
}))
}
async fn health_check(_request: ElifRequest) -> HttpResult<ElifResponse> {
ElifResponse::ok().json(&json!({
"status": "healthy",
"framework": "Elif.rs",
"version": env!("CARGO_PKG_VERSION"),
"timestamp": chrono::Utc::now().timestamp()
}))
}
fn create_test_router() -> Router {
Router::new()
.get("/health", health_check)
.get("/users", get_users)
.post("/users", create_user)
}
#[tokio::test]
#[ignore] async fn test_health_endpoint() {
let _router = create_test_router();
let response = TestClient::with_base_url("http://localhost:3001")
.get("/health")
.send()
.await
.expect("Health check should succeed")
.assert_success()
.assert_header_exists("content-type");
let health_data = response.json().expect("Should parse JSON");
assert_eq!(health_data["status"], "healthy");
assert_eq!(health_data["framework"], "Elif.rs");
}
#[tokio::test]
#[ignore] async fn test_users_with_query_params() {
let response = TestClient::with_base_url("http://localhost:3001")
.get("/users")
.query("limit", "5")
.query("offset", "10")
.header("authorization", "Bearer test-token")
.send()
.await
.expect("Users request should succeed")
.assert_success();
response
.assert_json_contains(json!({
"limit": 5,
"offset": 10
}))
.expect("Should contain query params");
}
#[tokio::test]
#[ignore] async fn test_create_user() {
let user_data = json!({
"name": "Charlie",
"email": "charlie@example.com"
});
let response = TestClient::with_base_url("http://localhost:3001")
.post("/users")
.json(&user_data)
.header("authorization", "Bearer admin-token")
.send()
.await
.expect("Create user should succeed")
.assert_status(201);
response
.assert_json_contains(json!({
"user": {
"name": "Charlie",
"email": "charlie@example.com"
},
"message": "User created successfully"
}))
.expect("Should contain user data");
}
#[tokio::test]
#[ignore] async fn test_validation_error() {
let invalid_data = json!({
"name": "", "email": "invalid-email" });
TestClient::with_base_url("http://localhost:3001")
.post("/users")
.json(&invalid_data)
.send()
.await
.expect("Request should complete")
.assert_status(422) .assert_validation_error("name", "required")
.expect("Should have name validation error");
}
#[tokio::test]
#[ignore] async fn test_authenticated_request() {
TestClient::with_base_url("http://localhost:3001")
.authenticated_with_token("valid-jwt-token")
.get("/users")
.send()
.await
.expect("Authenticated request should succeed")
.assert_success()
.assert_header_exists("authorization");
}
#[tokio::test]
#[ignore] async fn test_cors_headers() {
TestClient::with_base_url("http://localhost:3001")
.get("/health")
.header("Origin", "https://example.com")
.send()
.await
.expect("CORS request should succeed")
.assert_success()
.assert_header("Access-Control-Allow-Origin", "*");
}
#[tokio::test]
#[ignore] async fn test_response_time() {
use std::time::Instant;
let start = Instant::now();
TestClient::with_base_url("http://localhost:3001")
.get("/health")
.send()
.await
.expect("Performance test should succeed")
.assert_success();
let duration = start.elapsed();
assert!(
duration < Duration::from_millis(100),
"Response should be fast"
);
}
#[tokio::test]
#[ignore] async fn test_multiple_requests() {
let client =
TestClient::with_base_url("http://localhost:3001").authenticated_with_token("test-token");
for i in 1..=5 {
let response = client
.clone()
.get("/users")
.query("page", &i.to_string())
.send()
.await
.expect("Batch request should succeed")
.assert_success();
let data = response.json().expect("Should parse JSON");
println!(
"Request {}: got {} users",
i,
data["users"].as_array().unwrap().len()
);
}
}
#[tokio::test]
#[ignore] async fn test_with_database() {
let response = TestClient::with_base_url("http://localhost:3001")
.get("/users")
.send()
.await
.expect("DB test should succeed")
.assert_success();
assert!(response.json().is_ok());
}