Files
kakeibo/backend/tests/common/mod.rs
T
suphicakir e188922c0f feat(kayıt): yeni hane kaydı yalnızca davetle (REGISTRATION=invite_only)
- REGISTRATION ortam değişkeni: invite_only (varsayılan) | open
- invite_only: ilk hane serbest, sonrasında yalnızca davet koduyla katılım
- Backend'de zorunlu: 403 registration_closed; GET /api/auth/registration
- Kayıt ekranı: kayıt kapalıyken yalnızca davet kodu ve açıklama
- Entegrasyon testleri: kayıt politikası (2)
- Prettier ayarı eklendi (proje stiliyle uyumlu), kaynaklar biçimlendirildi

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 01:04:48 +03:00

160 lines
5.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Entegrasyon testleri için yardımcılar.
//!
//! Her test kendi geçici veritabanını (`kakeibo_test_<uuid>`) kullanır ve sonunda siler.
//! Gereken: yerel MongoDB çalışıyor olmalı (`npm run db:up`), `.env` içinde `MONGODB_URI`.
#![allow(dead_code)] // her test dosyası tüm yardımcıları kullanmaz
use axum::{
Router,
body::Body,
http::{Method, Request, StatusCode, header},
};
use http_body_util::BodyExt;
use kakeibo::{
config::{Config, RegistrationMode},
db, routes,
state::AppState,
};
use mongodb::Database;
use serde_json::{Value, json};
use tower::ServiceExt;
pub struct TestApp {
router: Router,
pub db: Database,
}
/// Oturum açmış bir test kullanıcısı
#[derive(Clone)]
pub struct Session {
pub cookie: String,
pub household_id: String,
}
impl TestApp {
/// Kayıt açık (birden fazla hane gerektiren testler için).
pub async fn new() -> Self {
Self::with_registration(RegistrationMode::Open).await
}
pub async fn with_registration(registration: RegistrationMode) -> Self {
dotenvy::dotenv().ok();
let uri = std::env::var("MONGODB_URI")
.expect("MONGODB_URI tanımlı değil (.env dosyasını kontrol edin)");
let base = db::connect(&uri)
.await
.expect("MongoDB'ye bağlanılamadı — `npm run db:up` çalıştırın");
let name = format!("kakeibo_test_{}", uuid::Uuid::new_v4().simple());
let db = base.client().database(&name);
db::prepare(&db).await.expect("test DB hazırlanamadı");
let config = Config {
mongodb_uri: uri,
jwt_secret: "test-jwt-secret-en-az-32-karakter-olmali!!".into(),
app_url: "http://localhost".into(),
port: 0,
registration,
};
let router = routes::router(AppState::new(db.clone(), config));
Self { router, db }
}
/// Test sonunda geçici veritabanını siler.
pub async fn cleanup(self) {
self.db.drop().await.ok();
}
/// İstek gönderir; (durum kodu, JSON gövde, set-cookie) döner.
pub async fn send(
&self,
method: Method,
path: &str,
cookie: Option<&str>,
body: Option<Value>,
) -> (StatusCode, Value, Option<String>) {
let mut req = Request::builder().method(method).uri(format!("/api{path}"));
if let Some(c) = cookie {
req = req.header(header::COOKIE, c);
}
let req = match body {
Some(b) => req
.header(header::CONTENT_TYPE, "application/json")
.body(Body::from(b.to_string())),
None => req.body(Body::empty()),
}
.unwrap();
let res = self.router.clone().oneshot(req).await.unwrap();
let status = res.status();
let set_cookie = res
.headers()
.get(header::SET_COOKIE)
.and_then(|v| v.to_str().ok())
.and_then(|v| v.split(';').next())
.map(String::from);
let bytes = res.into_body().collect().await.unwrap().to_bytes();
let json = serde_json::from_slice(&bytes).unwrap_or(Value::Null);
(status, json, set_cookie)
}
pub async fn get(&self, path: &str, s: &Session) -> (StatusCode, Value) {
let (st, v, _) = self.send(Method::GET, path, Some(&s.cookie), None).await;
(st, v)
}
pub async fn post(&self, path: &str, s: &Session, body: Value) -> (StatusCode, Value) {
let (st, v, _) = self
.send(Method::POST, path, Some(&s.cookie), Some(body))
.await;
(st, v)
}
pub async fn patch(&self, path: &str, s: &Session, body: Value) -> (StatusCode, Value) {
let (st, v, _) = self
.send(Method::PATCH, path, Some(&s.cookie), Some(body))
.await;
(st, v)
}
pub async fn put(&self, path: &str, s: &Session, body: Value) -> (StatusCode, Value) {
let (st, v, _) = self
.send(Method::PUT, path, Some(&s.cookie), Some(body))
.await;
(st, v)
}
pub async fn delete(&self, path: &str, s: &Session) -> (StatusCode, Value) {
let (st, v, _) = self.send(Method::DELETE, path, Some(&s.cookie), None).await;
(st, v)
}
/// Yeni kullanıcı kaydeder (davet koduyla veya yeni hane olarak) ve oturumunu döner.
pub async fn register(&self, name: &str, invite_code: Option<&str>) -> Session {
let email = format!(
"{}-{}@test.com",
name.to_lowercase(),
uuid::Uuid::new_v4().simple()
);
let (status, body, cookie) = self
.send(
Method::POST,
"/auth/register",
None,
Some(json!({
"name": name,
"email": email,
"password": "test-sifre-123",
"invite_code": invite_code,
})),
)
.await;
assert_eq!(status, StatusCode::CREATED, "kayıt başarısız: {body}");
Session {
cookie: cookie.expect("kayıtta cookie dönmedi"),
household_id: body["household"]["id"].as_str().unwrap().to_string(),
}
}
}