Lines
97.28 %
Functions
100 %
Branches
use axum::{
Router,
body::Body,
http::{Request, StatusCode},
routing::{get, post},
};
use tower::ServiceExt;
use crate::common::{create_mock_jwt_auth, create_mock_user, create_test_app_state};
fn make_convert_app(
app_state: std::sync::Arc<web::AppState>,
jwt_auth: web::jwt_auth::JWTAuthMiddleware,
) -> Router {
Router::new()
.route(
"/commodity/convert/submit",
post(web::pages::commodity::convert::submit::commodity_convert_submit),
)
.layer(axum::middleware::from_fn_with_state(
app_state.clone(),
move |mut req: axum::http::Request<Body>, next: axum::middleware::Next| {
let jwt_auth = jwt_auth.clone();
async move {
req.extensions_mut().insert(jwt_auth);
next.run(req).await
}
},
))
.with_state(app_state)
#[tokio::test]
async fn test_commodity_convert_without_auth() {
let app_state = create_test_app_state().await;
let app = Router::new()
.with_state(app_state);
let response = app
.oneshot(
Request::builder()
.method("POST")
.uri("/commodity/convert/submit")
.header("content-type", "application/x-www-form-urlencoded")
.body(Body::from(
"amount=100&source_commodity_id=00000000-0000-0000-0000-000000000001\
&target_commodity_id=00000000-0000-0000-0000-000000000002",
.unwrap(),
.await
.unwrap();
assert!(response.status().is_client_error() || response.status().is_server_error());
async fn test_commodity_convert_invalid_amount() {
let mock_user = create_mock_user();
let jwt_auth = create_mock_jwt_auth(mock_user);
let app = make_convert_app(app_state, jwt_auth);
"amount=not-a-number\
&source_commodity_id=00000000-0000-0000-0000-000000000001\
// Invalid amount → error fragment returned with 200 (HTMX pattern)
assert!(
response.status().is_success() || response.status() == StatusCode::BAD_REQUEST,
"Expected success or 400 for invalid amount, got: {}",
response.status()
);
if response.status().is_success() {
let body = axum::body::to_bytes(response.into_body(), usize::MAX)
let body_str = String::from_utf8(body.to_vec()).unwrap();
body_str.contains("error") || body_str.contains("Invalid"),
"Expected error content in response for invalid amount, got: {body_str}"
async fn test_commodity_convert_invalid_uuid() {
"amount=100&source_commodity_id=not-a-uuid\
// Invalid UUID → error fragment returned with 200 (HTMX pattern)
response.status().is_success(),
"Expected success (HTMX error fragment) for invalid UUID, got: {}",
"Expected error content for invalid UUID, got: {body_str}"
async fn test_commodity_convert_no_price_row() {
// Valid UUIDs but no price row exists between them in test DB
"amount=100\
// Either an HTMX error fragment (200) or a server error is acceptable
response.status().is_success() || response.status().is_server_error(),
"Expected success or server error, got: {}",
// Should contain an error message about missing price row
body_str.contains("error") || body_str.contains("exchange") || body_str.contains("No"),
"Expected error fragment for missing price row, got: {body_str}"
async fn test_commodity_convert_page_with_auth() {
"/commodity/convert",
get(web::pages::commodity::convert::submit::commodity_convert_page),
.method("GET")
.uri("/commodity/convert")
.body(Body::empty())
"Expected success or server error for convert page, got: {}",
body_str.contains("convert") || body_str.contains("Convert"),
"Expected convert page content, got: {body_str}"