Files
agentic-studio/kipina-codebench/golden-examples/todo-rs/tests/api_test.rs

263 lines
6.6 KiB
Rust

//! Integraatiotestit — muistinvarainen SQLite, uniikki data per testi.
use axum::http::StatusCode;
use reqwest::Client;
use sqlx::sqlite::SqlitePoolOptions;
use todo_rs::{app, init_db};
/// Käynnistä testipalvelin satunnaisessa portissa.
async fn spawn_server() -> (Client, String) {
let pool = SqlitePoolOptions::new()
.max_connections(1)
.connect("sqlite::memory:")
.await
.expect("Testitietokanta epäonnistui");
init_db(&pool).await;
let listener = tokio::net::TcpListener::bind("127.0.0.1:0")
.await
.expect("Testiportin kuuntelu epäonnistui");
let addr = listener.local_addr().unwrap();
let base_url = format!("http://{addr}");
let router = app(pool);
tokio::spawn(async move {
axum::serve(listener, router).await.unwrap();
});
(Client::new(), base_url)
}
#[tokio::test]
async fn test_create_todo() {
let (client, url) = spawn_server().await;
let res = client
.post(format!("{url}/todos"))
.json(&serde_json::json!({"title": "Osta maitoa", "priority": 2}))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::CREATED);
let body: serde_json::Value = res.json().await.unwrap();
assert_eq!(body["title"], "Osta maitoa");
assert_eq!(body["priority"], 2);
assert!(body["id"].is_number());
}
#[tokio::test]
async fn test_create_todo_defaults() {
let (client, url) = spawn_server().await;
let res = client
.post(format!("{url}/todos"))
.json(&serde_json::json!({"title": "Oletusarvotesti"}))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::CREATED);
let body: serde_json::Value = res.json().await.unwrap();
assert_eq!(body["priority"], 1);
assert_eq!(body["status"], "pending");
assert!(body["description"].is_null());
}
#[tokio::test]
async fn test_list_todos() {
let (client, url) = spawn_server().await;
client
.post(format!("{url}/todos"))
.json(&serde_json::json!({"title": "Listattava tehtävä"}))
.send()
.await
.unwrap();
let res = client.get(format!("{url}/todos")).send().await.unwrap();
assert_eq!(res.status(), StatusCode::OK);
let body: Vec<serde_json::Value> = res.json().await.unwrap();
assert!(body.len() >= 1);
}
#[tokio::test]
async fn test_get_todo_by_id() {
let (client, url) = spawn_server().await;
let created: serde_json::Value = client
.post(format!("{url}/todos"))
.json(&serde_json::json!({"title": "Haettava tehtävä"}))
.send()
.await
.unwrap()
.json()
.await
.unwrap();
let id = created["id"].as_i64().unwrap();
let res = client
.get(format!("{url}/todos/{id}"))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::OK);
let body: serde_json::Value = res.json().await.unwrap();
assert_eq!(body["id"], id);
assert_eq!(body["title"], "Haettava tehtävä");
}
#[tokio::test]
async fn test_get_todo_not_found() {
let (client, url) = spawn_server().await;
let res = client
.get(format!("{url}/todos/99999"))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::NOT_FOUND);
}
#[tokio::test]
async fn test_update_todo() {
let (client, url) = spawn_server().await;
let created: serde_json::Value = client
.post(format!("{url}/todos"))
.json(&serde_json::json!({"title": "Vanha otsikko"}))
.send()
.await
.unwrap()
.json()
.await
.unwrap();
let id = created["id"].as_i64().unwrap();
let res = client
.put(format!("{url}/todos/{id}"))
.json(&serde_json::json!({"title": "Uusi otsikko"}))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::OK);
let body: serde_json::Value = res.json().await.unwrap();
assert_eq!(body["title"], "Uusi otsikko");
}
#[tokio::test]
async fn test_update_todo_not_found() {
let (client, url) = spawn_server().await;
let res = client
.put(format!("{url}/todos/99999"))
.json(&serde_json::json!({"title": "Ei löydy"}))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::NOT_FOUND);
}
#[tokio::test]
async fn test_delete_todo() {
let (client, url) = spawn_server().await;
let created: serde_json::Value = client
.post(format!("{url}/todos"))
.json(&serde_json::json!({"title": "Poistettava"}))
.send()
.await
.unwrap()
.json()
.await
.unwrap();
let id = created["id"].as_i64().unwrap();
let res = client
.delete(format!("{url}/todos/{id}"))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::NO_CONTENT);
let res = client
.get(format!("{url}/todos/{id}"))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::NOT_FOUND);
}
#[tokio::test]
async fn test_delete_todo_not_found() {
let (client, url) = spawn_server().await;
let res = client
.delete(format!("{url}/todos/99999"))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::NOT_FOUND);
}
#[tokio::test]
async fn test_full_lifecycle() {
let (client, url) = spawn_server().await;
// Luo
let created: serde_json::Value = client
.post(format!("{url}/todos"))
.json(&serde_json::json!({
"title": "Elinkaaritesti",
"description": "Testataan koko CRUD-kierto",
"due_date": "2026-12-31",
"priority": 3,
"status": "in_progress"
}))
.send()
.await
.unwrap()
.json()
.await
.unwrap();
let id = created["id"].as_i64().unwrap();
assert_eq!(created["title"], "Elinkaaritesti");
assert_eq!(created["description"], "Testataan koko CRUD-kierto");
assert_eq!(created["due_date"], "2026-12-31");
assert_eq!(created["priority"], 3);
assert_eq!(created["status"], "in_progress");
// Päivitä
let updated: serde_json::Value = client
.put(format!("{url}/todos/{id}"))
.json(&serde_json::json!({"status": "done"}))
.send()
.await
.unwrap()
.json()
.await
.unwrap();
assert_eq!(updated["status"], "done");
assert_eq!(updated["title"], "Elinkaaritesti");
// Poista
let res = client
.delete(format!("{url}/todos/{id}"))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::NO_CONTENT);
}