Something went wrong. Try again.
A simple to-do app focused on tasks that can be completed within a specific time span. taskline.tobinio.dev
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283#![allow(unused)]#![allow(clippy::unwrap_used)]use std::sync::OnceLock;
use api::app;use axum_test::{TestRequest, TestResponse, TestServer};use chrono::NaiveDate;use serde::de::DeserializeOwned;use serde_json::json;use services::User;use tracing::Level;use types::{ organization::Organization, tag::{Category, Tag}, todo::Todo,};use uuid::Uuid;
pub struct Client<'a> { uuid: Option<Uuid>, org: Option<Uuid>, server: &'a TestServer,}
impl<'a> Client<'a> { pub fn new(server: &'a TestServer) -> Client<'a> { let uuid = Uuid::new_v4();
Client { uuid: Some(uuid), org: None, server, } }
pub fn new_no_user(server: &'a TestServer) -> Client<'a> { Client { uuid: None, org: None, server, } }
pub fn new_with_org(server: &'a TestServer, org: Uuid) -> Client<'a> { let uuid = Uuid::new_v4();
Client { uuid: Some(uuid), org: Some(org), server, } }
pub fn set_org(&mut self, org: Uuid) { self.org = Some(org) }
pub fn uuid(&self) -> Option<Uuid> { self.uuid.clone() }}
impl<'a> Client<'a> { fn add_header(&self, mut request: TestRequest) -> TestRequest { if let Some(uuid) = self.uuid { request = request.add_header("x-user-id", uuid.to_string()); };
if let Some(uuid) = self.org { request = request.add_header("x-org-id", uuid.to_string()); };
request }
async fn get(&self, path: &str) -> TestResponse { self.add_header(self.server.get(&format!("/api/{path}"))) .await }
async fn post(&self, path: &str) -> TestResponse { self.add_header(self.server.post(&format!("/api/{path}"))) .await }
async fn post_json(&self, path: &str, body: serde_json::Value) -> TestResponse { self.add_header(self.server.post(&format!("/api/{path}")).json(&body)) .await }
async fn put_json(&self, path: &str, body: serde_json::Value) -> TestResponse { self.add_header(self.server.put(&format!("/api/{path}")).json(&body)) .await }
async fn delete(&self, path: &str) -> TestResponse { self.add_header(self.server.delete(&format!("/api/{path}"))) .await }
fn json<T: DeserializeOwned>(response: &TestResponse) -> T { response.assert_status_success(); response.json() }}
impl<'a> Client<'a> { pub async fn get_todos(&self) -> TestResponse { self.get("todos").await }
pub async fn get_todos_json(&self) -> Vec<Todo> { Self::json(&self.get_todos().await) }
pub async fn get_deleted_todos(&self) -> TestResponse { self.get("todos?deleted=true").await }
pub async fn get_deleted_todos_json(&self) -> Vec<Todo> { Self::json(&self.get_deleted_todos().await) }
pub async fn add_todo(&self, todo: serde_json::Value) -> TestResponse { self.post_json("todos", todo).await }
pub async fn add_todo_json(&self, todo: serde_json::Value) -> Todo { Self::json(&self.add_todo(todo).await) }
pub async fn update_todo(&self, todo: serde_json::Value) -> TestResponse { self.put_json("todos", todo).await }
pub async fn update_todo_json(&self, todo: serde_json::Value) -> Todo { Self::json(&self.update_todo(todo).await) }
pub async fn reactivate_todo(&self, todo_uuid: Uuid) -> TestResponse { self.post(&format!("todos/reactivate/{todo_uuid}")).await }
pub async fn delete_todo(&self, todo_uuid: Uuid) -> TestResponse { self.delete(&format!("todos/{todo_uuid}")).await }
pub async fn delete_todo_json(&self, todo_uuid: Uuid) -> Todo { Self::json(&self.delete_todo(todo_uuid).await) }
pub async fn check_todo_with_date(&self, todo_uuid: Uuid, date: NaiveDate) -> TestResponse { self.post_json(&format!("todos/check/{todo_uuid}"), json!({ "date": date })) .await }
pub async fn check_todo(&self, todo_uuid: Uuid) -> TestResponse { self.post(&format!("todos/check/{todo_uuid}")).await }
pub async fn remove_check_todo(&self, todo_uuid: Uuid) -> TestResponse { self.delete(&format!("todos/check/{todo_uuid}")).await }
pub async fn add_organization(&self, organization: serde_json::Value) -> TestResponse { self.post_json("organization", organization).await }
pub async fn add_organization_json(&self, organization: serde_json::Value) -> Organization { Self::json(&self.add_organization(organization).await) }
pub async fn leave_organization(&self, organization: serde_json::Value) -> TestResponse { self.post_json("organization/leave", organization).await }
pub async fn join_organization(&self, organization: serde_json::Value) -> TestResponse { self.post_json("organization/join", organization).await }
pub async fn get_organizations(&self) -> TestResponse { self.get("organization").await }
pub async fn get_organizations_json(&self) -> Vec<Organization> { Self::json(&self.get_organizations().await) }
pub async fn get_tags(&self) -> TestResponse { self.get("tags").await }
pub async fn get_tags_json(&self) -> Vec<Tag> { Self::json(&self.get_tags().await) }
pub async fn add_tag(&self, tag: serde_json::Value) -> TestResponse { self.post_json("tags", tag).await }
pub async fn add_tag_json(&self, tag: serde_json::Value) -> Tag { Self::json(&self.add_tag(tag).await) }
pub async fn update_tag(&self, tag: serde_json::Value) -> TestResponse { self.put_json("tags", tag).await }
pub async fn update_tag_json(&self, tag: serde_json::Value) -> Tag { Self::json(&self.update_tag(tag).await) }
pub async fn delete_tag(&self, tag_uuid: Uuid) -> TestResponse { self.delete(&format!("tags/{tag_uuid}")).await }
pub async fn delete_tag_json(&self, tag_uuid: Uuid) -> Tag { Self::json(&self.delete_tag(tag_uuid).await) }
pub async fn get_categories(&self) -> TestResponse { self.get("categories").await }
pub async fn get_categories_json(&self) -> Vec<Category> { Self::json(&self.get_categories().await) }
pub async fn add_category(&self, category: serde_json::Value) -> TestResponse { self.post_json("categories", category).await }
pub async fn add_category_json(&self, category: serde_json::Value) -> Category { Self::json(&self.add_category(category).await) }
pub async fn update_category(&self, category: serde_json::Value) -> TestResponse { self.put_json("categories", category).await }
pub async fn update_category_json(&self, category: serde_json::Value) -> Category { Self::json(&self.update_category(category).await) }
pub async fn delete_category(&self, category_uuid: Uuid) -> TestResponse { self.delete(&format!("categories/{category_uuid}")).await }
pub async fn delete_category_json(&self, category_uuid: Uuid) -> Category { Self::json(&self.delete_category(category_uuid).await) }
pub async fn move_todo(&self, value: serde_json::Value) -> TestResponse { self.post_json("todos/move", value).await }
pub async fn add_web_push_subscription(&self, subscription: serde_json::Value) -> TestResponse { self.post_json("subscription", subscription).await }}
static TRACING: OnceLock<()> = OnceLock::new();
pub async fn get_server() -> TestServer { TRACING.get_or_init(|| { tracing_subscriber::fmt().with_max_level(Level::WARN).init(); });
let app = app( "sqlite::memory:", true, None, "http://localhost:3000".to_string(), "http://localhost:8080".to_string(), ) .await .unwrap();
let mut test_server = TestServer::builder().http_transport().build(app);
test_server}