From b49bb08c7a77fe4b29cf4ed0504c2f1c32a025e3 Mon Sep 17 00:00:00 2001 From: batsumaru <> Date: Fri, 16 Oct 2026 15:17:17 +0900 Subject: Update error responses --- src/tests.rs | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 5 deletions(-) (limited to 'src/tests.rs') diff --git a/src/tests.rs b/src/tests.rs index 586f35a..5b21352 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -116,7 +116,10 @@ async fn create_returns_the_measurement_and_location(pool: PgPool) { async fn create_rejects_bad_bodies(pool: PgPool) { let app = router(pool); let cases = [ - (json!({"metric_type": "Hip"}).to_string(), StatusCode::UNPROCESSABLE_ENTITY), + ( + json!({"metric_type": "Hip"}).to_string(), + StatusCode::UNPROCESSABLE_ENTITY, + ), ( measurement("2026-10-14T12:00:00Z", "Nope", 1.0, "Kilogram"), StatusCode::UNPROCESSABLE_ENTITY, @@ -219,8 +222,14 @@ async fn list_ranges_are_inclusive_of_both_days(pool: PgPool) { let cases = [ ("/measurements?from=2026-10-15", vec![2.0, 3.0, 4.0]), ("/measurements?to=2026-10-14", vec![1.0]), - ("/measurements?from=2026-10-14&to=2026-10-15", vec![1.0, 2.0, 3.0]), - ("/measurements?from=2026-10-15&to=2026-10-15", vec![2.0, 3.0]), + ( + "/measurements?from=2026-10-14&to=2026-10-15", + vec![1.0, 2.0, 3.0], + ), + ( + "/measurements?from=2026-10-15&to=2026-10-15", + vec![2.0, 3.0], + ), ("/measurements?from=2030-01-01", vec![]), ]; for (uri, expected) in cases { @@ -236,7 +245,10 @@ async fn list_combines_filters_with_order_and_limit(pool: PgPool) { seed(&app).await; let cases = [ ("/measurements?from=2026-10-15&limit=1", vec![2.0]), - ("/measurements?from=2026-10-15&order=desc&limit=2", vec![4.0, 3.0]), + ( + "/measurements?from=2026-10-15&order=desc&limit=2", + vec![4.0, 3.0], + ), ("/measurements?date=2026-10-15&order=desc", vec![3.0, 2.0]), ]; for (uri, expected) in cases { @@ -350,8 +362,101 @@ async fn delete_is_idempotent(pool: PgPool) { #[sqlx::test] async fn old_paths_are_gone(pool: PgPool) { let app = router(pool); - for uri in ["/", "/all", "/search?from=2026-10-14", "/units", "/metric_types"] { + for uri in [ + "/", + "/all", + "/search?from=2026-10-14", + "/units", + "/metric_types", + ] { let (status, _) = get_json(&app, uri).await; assert_eq!(status, StatusCode::NOT_FOUND, "{uri}"); } } + +#[sqlx::test] +async fn errors_have_a_json_body(pool: PgPool) { + let app = router(pool); + let missing = format!("/measurements/{}", Uuid::now_v7()); + let valid = measurement("2026-10-14T12:00:00Z", "Waist", 80.0, "Centimeter"); + let invalid_pair = measurement("2026-10-14T12:00:00Z", "Waist", 80.0, "Kilogram"); + let cases = [ + ( + Method::GET, + "/measurements?limit=0".to_owned(), + None, + StatusCode::BAD_REQUEST, + ), + ( + Method::GET, + "/measurements?order=sideways".to_owned(), + None, + StatusCode::BAD_REQUEST, + ), + ( + Method::GET, + "/measurements?date=bad".to_owned(), + None, + StatusCode::BAD_REQUEST, + ), + ( + Method::GET, + "/measurements/not-a-uuid".to_owned(), + None, + StatusCode::BAD_REQUEST, + ), + (Method::GET, missing.clone(), None, StatusCode::NOT_FOUND), + (Method::PUT, missing, Some(valid), StatusCode::NOT_FOUND), + ( + Method::POST, + "/measurements".to_owned(), + Some("not json".to_owned()), + StatusCode::BAD_REQUEST, + ), + ( + Method::POST, + "/measurements".to_owned(), + Some(invalid_pair), + StatusCode::UNPROCESSABLE_ENTITY, + ), + (Method::GET, "/nope".to_owned(), None, StatusCode::NOT_FOUND), + ( + Method::PATCH, + "/measurements".to_owned(), + None, + StatusCode::METHOD_NOT_ALLOWED, + ), + ]; + for (method, uri, body, expected) in cases { + let (status, _, body) = send(&app, method.clone(), &uri, body).await; + assert_eq!(status, expected, "{method} {uri}"); + assert!(body["error"].is_string(), "{method} {uri}: {body}"); + } +} + +#[sqlx::test] +async fn error_messages_explain_the_problem(pool: PgPool) { + let app = router(pool); + let cases = [ + ("/measurements?limit=0", "limit must be positive"), + ( + "/measurements?date=2026-10-15&from=2026-10-14", + "date can't be combined with from or to", + ), + ( + "/measurements?from=2026-10-16&to=2026-10-14", + "from must not be after to", + ), + ]; + for (uri, message) in cases { + let (_, body) = get_json(&app, uri).await; + assert_eq!(body["error"], message, "{uri}"); + } + let body = measurement("2026-10-14T12:00:00Z", "Waist", 80.0, "Kilogram"); + let (_, _, body) = send(&app, Method::POST, "/measurements", Some(body)).await; + let message = body["error"].as_str().unwrap(); + assert!( + message.contains("Invalid pair Waist, Kilogram"), + "{message}" + ); +} -- cgit v1.3