use axum::{body::Body, http::{header, Request, StatusCode}}; use oauth2::{basic::BasicClient, AuthUrl, ClientId, ClientSecret, TokenUrl}; use sqlx::SqlitePool; use tower::ServiceExt; use weight_tracker::{create_app, AppState}; async fn make_app() -> axum::Router { let pool = SqlitePool::connect("sqlite::memory:").await.unwrap(); sqlx::query(include_str!("../migrations/20260408203423_create_weights_table.sql")) .execute(&pool) .await .unwrap(); let oidc_client = BasicClient::new( ClientId::new("test-client".into()), Some(ClientSecret::new("test-secret".into())), AuthUrl::new("http://localhost/auth".into()).unwrap(), Some(TokenUrl::new("http://localhost/token".into()).unwrap()), ); let state = AppState { pool: pool.clone(), oidc_client }; create_app(state, b"01234567890123456789012345678901".to_vec(), pool).await } #[tokio::test] async fn index_returns_ok() { let app = make_app().await; let response = app .oneshot(Request::builder().uri("/").body(Body::empty()).unwrap()) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); } #[tokio::test] async fn auth_login_redirects_and_sets_cookie() { let app = make_app().await; let response = app .oneshot(Request::builder().uri("/auth/login").body(Body::empty()).unwrap()) .await .unwrap(); assert_eq!(response.status(), StatusCode::FOUND); assert!(response.headers().get(header::LOCATION).is_some()); assert!(response.headers().get(header::SET_COOKIE).is_some()); } #[tokio::test] async fn input_post_requires_authentication() { let app = make_app().await; let response = app .oneshot( Request::builder() .method("POST") .uri("/input") .header(header::CONTENT_TYPE, "application/x-www-form-urlencoded") .body(Body::from("date=2026-04-10&weight=80")) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::FOUND); assert_eq!(response.headers().get(header::LOCATION).unwrap(), "/auth/login"); } #[tokio::test] async fn authenticated_input_post_stores_weight() { let app = make_app().await; let app_clone = app.clone(); let auth_response = app_clone .oneshot(Request::builder().uri("/test/login").body(Body::empty()).unwrap()) .await .unwrap(); assert_eq!(auth_response.status(), StatusCode::FOUND); let cookie = auth_response .headers() .get(header::SET_COOKIE) .unwrap() .to_str() .unwrap(); let response = app .oneshot( Request::builder() .method("POST") .uri("/input") .header(header::CONTENT_TYPE, "application/x-www-form-urlencoded") .header(header::COOKIE, cookie) .body(Body::from("date=2026-04-10&weight=80")) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let body_bytes = hyper::body::to_bytes(response.into_body()).await.unwrap(); let body_text = std::str::from_utf8(&body_bytes).unwrap(); assert!(body_text.contains("80 kg")); assert!(body_text.contains("test-user")); }