From e56a04b88dfb8c141310a71d1a9c6b4be2fc9203 Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Tue, 7 May 2024 16:56:48 -0500 Subject: feat(api): impl tests for tasks module --- src/api/tasks.rs | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 1 deletion(-) (limited to 'src/api') diff --git a/src/api/tasks.rs b/src/api/tasks.rs index 9a3e1ab..b8acd91 100644 --- a/src/api/tasks.rs +++ b/src/api/tasks.rs @@ -47,7 +47,7 @@ pub fn router() -> Resource { pub async fn create( State(pool): State, - _: AccessClaims, + AccessClaims { sub, .. }: AccessClaims, Json(CreateTaskSchema { user_id, title, @@ -58,6 +58,10 @@ pub async fn create( end_at, }): Json, ) -> Result<(StatusCode, Json), Error> { + if sub != user_id { + return Err(Error::InvalidToken); + } + let task = sqlx::query_as!(Task, "INSERT INTO task (user_id, title, description, remote, location, start_at, end_at) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *", user_id, @@ -102,3 +106,157 @@ pub async fn destroy( .ok_or_else(|| Error::TaskNotFound) .map(Json) } + +#[cfg(test)] +mod tests { + use super::*; + + use axum::{ + body::Body, + http::{ + header::{CONTENT_TYPE, COOKIE}, + Request, StatusCode, + }, + Router, + }; + + use http_body_util::BodyExt; + use time::macros::datetime; + use tower::ServiceExt; + + use crate::{ + auth::AccessClaims, + tests::{setup_test_env, TestResult}, + }; + + const TASK_ID: Uuid = uuid::uuid!("d5d31b54-0fc4-432c-9212-25175749c7f4"); + const TASK_USER_ID: Uuid = uuid::uuid!("4c14f795-86f0-4361-a02f-0edb966fb145"); + const TASK_TITLE: &str = "Unload Cargo"; + const TASK_DESCRIPTION: &str = r#"I've got some cargo I need unloading."#; + const TASK_REMOTE: bool = false; + const TASK_LOCATION: &str = "Astroid Gamma 2b, Madranite Mining Belt, 42d5b4, Orion Beta"; + const TASK_START_AT: OffsetDateTime = datetime!(2042-05-13 12:00:00 -5); + const TASK_END_AT: OffsetDateTime = datetime!(2042-05-13 15:00:00 -5); + + #[sqlx::test(fixtures(path = "../../fixtures", scripts("users")))] + async fn test_tasks_post_created(pool: PgPool) -> TestResult { + setup_test_env(); + + let router = Router::new().merge(router()).with_state(AppState { pool }); + + let task = serde_json::json!( { + "user_id": TASK_USER_ID, + "title": TASK_TITLE, + "description": TASK_DESCRIPTION, + "remote": TASK_REMOTE, + "location": TASK_LOCATION, + "start_at": TASK_START_AT, + "end_at": TASK_END_AT, + }); + + let request = Request::builder() + .method("POST") + .uri("/tasks") + .header( + COOKIE, + AccessClaims::issue(TASK_USER_ID).as_cookie()?.to_string(), + ) + .header(CONTENT_TYPE, mime::APPLICATION_JSON.as_ref()) + .body(Body::from(serde_json::to_vec(&task)?))?; + + let response = router.oneshot(request).await?; + + assert_eq!( + StatusCode::CREATED, + response.status(), + "{}", + std::str::from_utf8(&response.into_body().collect().await?.to_bytes())? + ); + + let body_bytes = response.into_body().collect().await?.to_bytes(); + let Task { + user_id, + title, + description, + remote, + location, + start_at, + end_at, + .. + } = serde_json::from_slice(&body_bytes)?; + + assert_eq!(Some(TASK_USER_ID), user_id); + assert_eq!(TASK_TITLE, title); + assert_eq!(Some(TASK_DESCRIPTION), description.as_deref()); + assert_eq!(TASK_REMOTE, remote); + assert_eq!(Some(TASK_LOCATION), location.as_deref()); + assert_eq!(Some(TASK_START_AT), start_at); + assert_eq!(Some(TASK_END_AT), end_at); + + Ok(()) + } + + #[sqlx::test(fixtures(path = "../../fixtures", scripts("users", "tasks")))] + async fn test_tasks_get_ok(pool: PgPool) -> TestResult { + setup_test_env(); + + let router = Router::new().merge(router()).with_state(AppState { pool }); + + let request = Request::builder() + .uri(format!("/tasks/{}", TASK_ID)) + .header( + COOKIE, + AccessClaims::issue(TASK_USER_ID).as_cookie()?.to_string(), + ) + .body(Body::empty())?; + + let response = router.oneshot(request).await?; + + assert_eq!(StatusCode::OK, response.status()); + + let body_bytes = response.into_body().collect().await?.to_bytes(); + let Task { + id, + user_id, + title, + description, + remote, + location, + start_at, + end_at, + .. + } = serde_json::from_slice(&body_bytes)?; + + assert_eq!(TASK_ID, id); + assert_eq!(Some(TASK_USER_ID), user_id); + assert_eq!(TASK_TITLE, title); + assert_eq!(Some(TASK_DESCRIPTION), description.as_deref()); + assert_eq!(TASK_REMOTE, remote); + assert_eq!(Some(TASK_LOCATION), location.as_deref()); + assert_eq!(Some(TASK_START_AT), start_at); + assert_eq!(Some(TASK_END_AT), end_at); + + Ok(()) + } + + #[sqlx::test] + async fn test_tasks_get_not_found(pool: PgPool) -> TestResult { + setup_test_env(); + + let router = Router::new().merge(router()).with_state(AppState { pool }); + + let request = Request::builder() + .uri(format!("/tasks/{}", TASK_ID)) + .header( + COOKIE, + AccessClaims::issue(TASK_USER_ID).as_cookie()?.to_string(), + ) + .body(Body::empty())?; + + let response = router.oneshot(request).await?; + + assert_eq!(StatusCode::NOT_FOUND, response.status()); + + Ok(()) + } +} -- cgit v1.2.3-70-g09d2