fix(attendance): correct course_id column in slot queries, add patch_json helper

This commit is contained in:
2026-04-28 03:29:13 +02:00
parent 797ccacbb2
commit e75a2bccb8
2 changed files with 34 additions and 19 deletions

View File

@@ -4,6 +4,7 @@ use axum::{
routing::{delete, get, patch, post},
Json, Router,
};
use rand::Rng;
use serde::Deserialize;
use serde_json::{json, Value};
use sqlx::SqlitePool;
@@ -16,7 +17,6 @@ use crate::{
fn generate_code() -> String {
const CHARS: &[u8] = b"ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
use rand::Rng;
let mut rng = rand::rng();
(0..8)
.map(|_| CHARS[rng.random_range(0..CHARS.len())] as char)
@@ -132,7 +132,7 @@ async fn create_slot(
.fetch_optional(&pool)
.await?;
if room.is_none() {
return Err(AppError::NotFound);
return Err(AppError::BadRequest("room_id does not exist".into()));
}
}
@@ -174,7 +174,7 @@ async fn update_slot_status(
// Fetch the slot + its session's course_id for access check
let row: Option<(i64, Option<String>)> = sqlx::query_as(
"SELECT s.id, sl.code
"SELECT s.course_id, sl.code
FROM slots sl
JOIN sessions s ON s.id = sl.session_id
WHERE sl.id = ?",
@@ -284,7 +284,7 @@ pub fn router() -> Router<SqlitePool> {
#[cfg(test)]
mod tests {
use super::*;
use crate::test_helpers::{build_test_app, delete, get, post_json};
use crate::test_helpers::{build_test_app, delete, get, patch_json, post_json};
use axum::http::StatusCode;
use serde_json::{json, Value};
use std::collections::HashSet;
@@ -413,21 +413,13 @@ mod tests {
.unwrap();
// Open the slot
use axum::http::Request;
use http_body_util::BodyExt;
use tower::ServiceExt;
let req = Request::builder()
.method("PATCH")
.uri(format!("/api/admin/slots/{slot_id}/status"))
.header("Content-Type", "application/json")
.header("Authorization", &auth)
.body(axum::body::Body::from(
json!({"status": "open"}).to_string(),
))
.unwrap();
let res = app.clone().oneshot(req).await.unwrap();
assert_eq!(res.status(), StatusCode::OK);
let body = res.into_body().collect().await.unwrap().to_bytes();
let (status, body) = patch_json(
app.clone(),
&format!("/api/admin/slots/{slot_id}/status"),
&auth,
json!({"status": "open"}),
).await;
assert_eq!(status, StatusCode::OK);
let slot = serde_json::from_slice::<Value>(&body).unwrap();
assert_eq!(slot["status"], "open");
let code = slot["code"].as_str().unwrap();

View File

@@ -64,6 +64,29 @@ pub async fn put_json(app: Router, uri: &str, auth: &str, body: serde_json::Valu
(status, body)
}
/// PATCH JSON body to the app (one-shot), returns (StatusCode, response body bytes).
pub async fn patch_json(
app: Router,
uri: &str,
auth: &str,
body: serde_json::Value,
) -> (StatusCode, bytes::Bytes) {
let mut req = Request::builder()
.method("PATCH")
.uri(uri)
.header("Content-Type", "application/json");
if !auth.is_empty() {
req = req.header("Authorization", auth);
}
let req = req
.body(axum::body::Body::from(body.to_string()))
.unwrap();
let res = app.oneshot(req).await.unwrap();
let status = res.status();
let body = res.into_body().collect().await.unwrap().to_bytes();
(status, body)
}
/// GET from the app (one-shot), returns (StatusCode, response body bytes).
pub async fn get(app: Router, path: &str, auth: &str) -> (StatusCode, bytes::Bytes) {
let mut builder = Request::builder()