fix(attendance): correct course_id column in slot queries, add patch_json helper
This commit is contained in:
@@ -4,6 +4,7 @@ use axum::{
|
|||||||
routing::{delete, get, patch, post},
|
routing::{delete, get, patch, post},
|
||||||
Json, Router,
|
Json, Router,
|
||||||
};
|
};
|
||||||
|
use rand::Rng;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
@@ -16,7 +17,6 @@ use crate::{
|
|||||||
|
|
||||||
fn generate_code() -> String {
|
fn generate_code() -> String {
|
||||||
const CHARS: &[u8] = b"ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
const CHARS: &[u8] = b"ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
||||||
use rand::Rng;
|
|
||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
(0..8)
|
(0..8)
|
||||||
.map(|_| CHARS[rng.random_range(0..CHARS.len())] as char)
|
.map(|_| CHARS[rng.random_range(0..CHARS.len())] as char)
|
||||||
@@ -132,7 +132,7 @@ async fn create_slot(
|
|||||||
.fetch_optional(&pool)
|
.fetch_optional(&pool)
|
||||||
.await?;
|
.await?;
|
||||||
if room.is_none() {
|
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
|
// Fetch the slot + its session's course_id for access check
|
||||||
let row: Option<(i64, Option<String>)> = sqlx::query_as(
|
let row: Option<(i64, Option<String>)> = sqlx::query_as(
|
||||||
"SELECT s.id, sl.code
|
"SELECT s.course_id, sl.code
|
||||||
FROM slots sl
|
FROM slots sl
|
||||||
JOIN sessions s ON s.id = sl.session_id
|
JOIN sessions s ON s.id = sl.session_id
|
||||||
WHERE sl.id = ?",
|
WHERE sl.id = ?",
|
||||||
@@ -284,7 +284,7 @@ pub fn router() -> Router<SqlitePool> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
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 axum::http::StatusCode;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
@@ -413,21 +413,13 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Open the slot
|
// Open the slot
|
||||||
use axum::http::Request;
|
let (status, body) = patch_json(
|
||||||
use http_body_util::BodyExt;
|
app.clone(),
|
||||||
use tower::ServiceExt;
|
&format!("/api/admin/slots/{slot_id}/status"),
|
||||||
let req = Request::builder()
|
&auth,
|
||||||
.method("PATCH")
|
json!({"status": "open"}),
|
||||||
.uri(format!("/api/admin/slots/{slot_id}/status"))
|
).await;
|
||||||
.header("Content-Type", "application/json")
|
assert_eq!(status, StatusCode::OK);
|
||||||
.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 slot = serde_json::from_slice::<Value>(&body).unwrap();
|
let slot = serde_json::from_slice::<Value>(&body).unwrap();
|
||||||
assert_eq!(slot["status"], "open");
|
assert_eq!(slot["status"], "open");
|
||||||
let code = slot["code"].as_str().unwrap();
|
let code = slot["code"].as_str().unwrap();
|
||||||
|
|||||||
@@ -64,6 +64,29 @@ pub async fn put_json(app: Router, uri: &str, auth: &str, body: serde_json::Valu
|
|||||||
(status, body)
|
(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).
|
/// GET from the app (one-shot), returns (StatusCode, response body bytes).
|
||||||
pub async fn get(app: Router, path: &str, auth: &str) -> (StatusCode, bytes::Bytes) {
|
pub async fn get(app: Router, path: &str, auth: &str) -> (StatusCode, bytes::Bytes) {
|
||||||
let mut builder = Request::builder()
|
let mut builder = Request::builder()
|
||||||
|
|||||||
Reference in New Issue
Block a user