diff options
| -rw-r--r-- | src/handlers.rs | 4 | ||||
| -rw-r--r-- | src/models.rs | 1 | ||||
| -rw-r--r-- | src/tests.rs | 45 |
3 files changed, 49 insertions, 1 deletions
diff --git a/src/handlers.rs b/src/handlers.rs index 3c38724..5d31600 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -41,6 +41,7 @@ pub async fn list_measurements( SELECT id, measured_at, metric_type, value, unit FROM measurement WHERE ($1::timestamptz IS NULL OR measured_at >= $1) AND ($2::timestamptz IS NULL OR measured_at < $2) + AND ($5::metric_type IS NULL OR metric_type = $5) ORDER BY CASE WHEN $4 THEN measured_at END DESC, measured_at ASC LIMIT $3 @@ -48,7 +49,8 @@ pub async fn list_measurements( query.from, query.to, limit, - matches!(query.order, Order::Desc) + matches!(query.order, Order::Desc), + query.metric_type ) .fetch_all(&pool) .await?; diff --git a/src/models.rs b/src/models.rs index 102860b..15da87b 100644 --- a/src/models.rs +++ b/src/models.rs @@ -95,6 +95,7 @@ pub enum Order { pub struct ListQuery { pub from: Option<DateTime<Utc>>, pub to: Option<DateTime<Utc>>, + pub metric_type: Option<MetricType>, pub limit: Option<i64>, #[serde(default)] pub order: Order, diff --git a/src/tests.rs b/src/tests.rs index d2ee143..1f539bd 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -274,12 +274,57 @@ async fn list_combines_filters_with_order_and_limit(pool: PgPool) { } #[sqlx::test] +async fn list_filters_by_metric_type(pool: PgPool) { + let app = router(pool); + let rows = [ + ("2026-10-14T12:00:00Z", "BodyWeight", 70.0, "Kilogram"), + ("2026-10-15T12:00:00Z", "Waist", 80.0, "Centimeter"), + ("2026-10-16T12:00:00Z", "BodyWeight", 71.0, "Kilogram"), + ("2026-10-17T12:00:00Z", "Hip", 95.0, "Centimeter"), + ("2026-10-18T12:00:00Z", "BodyWeight", 72.0, "Kilogram"), + ]; + for (measured_at, metric_type, value, unit) in rows { + let body = measurement(measured_at, metric_type, value, unit); + let (status, _, _) = send(&app, Method::POST, "/measurements", Some(body)).await; + assert_eq!(status, StatusCode::CREATED); + } + let cases = [ + ("/measurements", vec![70.0, 80.0, 71.0, 95.0, 72.0]), + ( + "/measurements?metric_type=BodyWeight", + vec![70.0, 71.0, 72.0], + ), + ("/measurements?metric_type=Waist", vec![80.0]), + ("/measurements?metric_type=Hip", vec![95.0]), + ( + "/measurements?metric_type=BodyWeight&order=desc&limit=2", + vec![72.0, 71.0], + ), + ( + "/measurements?metric_type=BodyWeight&from=2026-10-15T00:00:00Z&to=2026-10-18T00:00:00Z", + vec![71.0], + ), + ( + "/measurements?metric_type=Hip&to=2026-10-17T00:00:00Z", + vec![], + ), + ]; + for (uri, expected) in cases { + let (status, rows) = get_json(&app, uri).await; + assert_eq!(status, StatusCode::OK, "{uri}"); + assert_eq!(values(&rows), expected, "{uri}"); + } +} + +#[sqlx::test] async fn list_rejects_bad_queries(pool: PgPool) { let app = router(pool); let uris = [ "/measurements?limit=0", "/measurements?limit=-1", "/measurements?order=sideways", + "/measurements?metric_type=Nope", + "/measurements?metric_type=bodyweight", "/measurements?from=bad", "/measurements?from=2026-10-15", "/measurements?to=2026-10-15T00:00:00", |
