diff --git a/api-requests/posts.http b/api-requests/posts.http new file mode 100644 index 0000000..aa421c4 --- /dev/null +++ b/api-requests/posts.http @@ -0,0 +1,96 @@ +@host=https://dummyjson.com/posts + +### +# @name GetAllPosts +GET {{host}} +Accept: application/json +Content-Type: application/json + +### +# @name GetPostById +@id=1 +GET {{host}}/{{id}} +Accept: application/json +Content-Type: application/json + + +### +# @name SearchPosts +@search=love +GET {{host}}/search?q={{search}} +Accept: application/json +Content-Type: application/json + + +### +# @name LimitAndSkipPosts +GET {{host}}?limit=10&skip=10&select=title,reactions,userId +Accept: application/json +Content-Type: application/json + +### +# @name SortPosts +GET {{host}}?sortBy=title&order=desc +Accept: application/json +Content-Type: application/json + + +### +# @name GetAllPostsTags +GET {{host}}/tags +Accept: application/json +Content-Type: application/json + +### +# @name GetPostsByTags +@tags=nature +GET {{host}}/tag/{{tags}} +Accept: application/json +Content-Type: application/json + +### +# @name GetPostsByUserId +@userId=1 +GET {{host}}/user/{{userId}} +Accept: application/json +Content-Type: application/json + +### +# @name GetPostComments +@id=1 +GET {{host}}/{{id}}/comments +Accept: application/json +Content-Type: application/json + + +### +# @name AddPost +POST {{host}}/add +Accept: application/json +Content-Type: application/json + +{ + "title": "test title", + "body": "test body", + "userId": 1, + "tags": ["nature", "photography"] +} + +### +# @name UpdatePost +@id=1 +PUT {{host}}/{{id}} +Accept: application/json +Content-Type: application/json + +{ + "title": "updated title", + "body": "updated body" +} + +### +# @name DeletePost +@id=1 +DELETE {{host}}/{{id}} +Accept: application/json +Content-Type: application/json diff --git a/src/auth.rs b/src/auth.rs index 1120b12..6823e11 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -99,14 +99,14 @@ impl DummyJsonClient { expires_in_mins, }; - let url = format!("{}/login", *AUTH_BASE_URL); + let url = format!("{}/login", AUTH_BASE_URL.as_str()); let response = self.client.post(url).json(&payload).send().await?; response.json().await } /// Get the current user pub async fn get_user(&self, access_token: &str) -> Result { - let url = format!("{}/me", *AUTH_BASE_URL); + let url = format!("{}/me", AUTH_BASE_URL.as_str()); let response = self .client .get(url) @@ -127,7 +127,7 @@ impl DummyJsonClient { "expiresInMins": expires_in_mins, }); - let url = format!("{}/refresh", *AUTH_BASE_URL); + let url = format!("{}/refresh", AUTH_BASE_URL.as_str()); let response = self.client.post(url).json(&payload).send().await?; response.json().await } diff --git a/src/carts.rs b/src/carts.rs index 4791759..d3315ee 100644 --- a/src/carts.rs +++ b/src/carts.rs @@ -69,13 +69,13 @@ pub struct DeleteCartResponse { impl DummyJsonClient { /// Get all carts pub async fn get_all_carts(&self) -> Result { - let url = &*CARTS_BASE_URL; + let url = CARTS_BASE_URL.as_str(); self.client.get(url).send().await?.json::().await } /// Get cart by id pub async fn get_cart_by_id(&self, id: u32) -> Result { - let url = format!("{}/{}", &*CARTS_BASE_URL, id); + let url = format!("{}/{}", CARTS_BASE_URL.as_str(), id); self.client.get(url).send().await?.json::().await } @@ -84,13 +84,13 @@ impl DummyJsonClient { &self, user_id: u32, ) -> Result { - let url = format!("{}/user/{}", &*CARTS_BASE_URL, user_id); + let url = format!("{}/user/{}", CARTS_BASE_URL.as_str(), user_id); self.client.get(url).send().await?.json::().await } /// Add cart pub async fn add_cart(&self, payload: AddCartPayload) -> Result { - let url = format!("{}/add", &*CARTS_BASE_URL); + let url = format!("{}/add", CARTS_BASE_URL.as_str()); self.client.post(url).json(&payload).send().await?.json::().await } @@ -100,13 +100,13 @@ impl DummyJsonClient { id: u32, payload: UpdateCartPayload, ) -> Result { - let url = format!("{}/{}", &*CARTS_BASE_URL, id); + let url = format!("{}/{}", CARTS_BASE_URL.as_str(), id); self.client.put(url).json(&payload).send().await?.json::().await } /// Delete cart pub async fn delete_cart(&self, cart_id: u32) -> Result { - let url = format!("{}/{}", &*CARTS_BASE_URL, cart_id); + let url = format!("{}/{}", CARTS_BASE_URL.as_str(), cart_id); self.client.delete(url).send().await?.json::().await } } diff --git a/src/lib.rs b/src/lib.rs index d100838..7f46007 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,13 @@ mod auth; mod carts; +mod posts; mod products; mod recipes; mod todos; pub use auth::*; pub use carts::*; +pub use posts::*; pub use products::*; pub use recipes::*; use reqwest::Client; diff --git a/src/posts.rs b/src/posts.rs new file mode 100644 index 0000000..e7a47fb --- /dev/null +++ b/src/posts.rs @@ -0,0 +1,203 @@ +use crate::{DummyJsonClient, ProductCategory, API_BASE_URL}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +static POSTS_BASE_URL: Lazy = Lazy::new(|| format!("{}/posts", API_BASE_URL)); + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct Post { + pub id: u32, + #[serde(flatten)] + pub other_fields: AddPost, +} + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct AddPost { + pub title: Option, + pub body: Option, + pub tags: Option>, + pub reactions: Option, + pub views: Option, + #[serde(rename = "userId")] + pub user_id: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Reaction { + pub likes: u32, + pub dislikes: u32, +} + +#[derive(Deserialize, Debug)] +pub struct GetAllPosts { + pub posts: Vec, + pub total: u32, + pub skip: u32, + pub limit: u32, +} + +#[derive(Deserialize, Debug)] +pub struct PostComment { + pub id: u32, + pub body: String, + #[serde(rename = "postId")] + pub post_id: u32, + pub likes: u32, + pub user: UserProfile, +} + +#[derive(Deserialize, Debug)] +pub struct UserProfile { + pub id: u32, + pub username: String, + #[serde(rename = "fullName")] + pub full_name: String, +} + +#[derive(Deserialize, Debug)] +pub struct PostCommentsResponse { + pub comments: Vec, + pub total: u32, + pub skip: u32, + pub limit: u32, +} + +impl DummyJsonClient { + /// Get all posts + pub async fn get_all_posts(&self) -> Result { + self.client + .get(POSTS_BASE_URL.as_str()) + .send() + .await? + .json::() + .await + } + + /// Get post by id + pub async fn get_post_by_id(&self, id: u32) -> Result { + self.client + .get(format!("{}/{}", POSTS_BASE_URL.as_str(), id)) + .send() + .await? + .json::() + .await + } + + /// Search posts + pub async fn search_posts(&self, query: &str) -> Result { + self.client + .get(format!("{}/search?q={}", POSTS_BASE_URL.as_str(), query)) + .send() + .await? + .json::() + .await + } + + /// Limit and skip posts + pub async fn limit_and_skip_posts( + &self, + limit: u32, + skip: u32, + selects: &str, + ) -> Result { + self.client + .get(format!( + "{}/?limit={}&skip={}&select={}", + POSTS_BASE_URL.as_str(), + limit, + skip, + selects + )) + .send() + .await? + .json::() + .await + } + + /// Sort posts + pub async fn sort_posts( + &self, + sort_by: &str, + // TODO: Change to enum + order: &str, + ) -> Result { + self.client + .get(format!("{}/?sortBy={}&order={}", POSTS_BASE_URL.as_str(), sort_by, order)) + .send() + .await? + .json::() + .await + } + + /// Get all posts tags + pub async fn get_all_posts_tags(&self) -> Result, reqwest::Error> { + self.client + .get(format!("{}/tags", POSTS_BASE_URL.as_str())) + .send() + .await? + .json::>() + .await + } + + /// Get posts by tags + pub async fn get_posts_by_tags(&self, tag: &str) -> Result { + self.client + .get(format!("{}/tag/{}", POSTS_BASE_URL.as_str(), tag)) + .send() + .await? + .json::() + .await + } + + /// Get posts by user id + pub async fn get_posts_by_user_id(&self, user_id: u32) -> Result { + self.client + .get(format!("{}/user/{}", POSTS_BASE_URL.as_str(), user_id)) + .send() + .await? + .json::() + .await + } + + /// Get post comments + pub async fn get_post_comments(&self, id: u32) -> Result { + self.client + .get(format!("{}/{}/comments", POSTS_BASE_URL.as_str(), id)) + .send() + .await? + .json::() + .await + } + + /// Add post + pub async fn add_post(&self, post: &AddPost) -> Result { + self.client + .post(format!("{}/add", POSTS_BASE_URL.as_str())) + .json(post) + .send() + .await? + .json::() + .await + } + + /// Update post + pub async fn update_post(&self, id: u32, post: &AddPost) -> Result { + self.client + .put(format!("{}/{}", POSTS_BASE_URL.as_str(), id)) + .json(post) + .send() + .await? + .json::() + .await + } + + /// Delete post + pub async fn delete_post(&self, id: u32) -> Result { + self.client + .delete(format!("{}/{}", POSTS_BASE_URL.as_str(), id)) + .send() + .await? + .json::() + .await + } +} diff --git a/src/products.rs b/src/products.rs index d45d47b..fef9e83 100644 --- a/src/products.rs +++ b/src/products.rs @@ -100,13 +100,13 @@ pub struct DeleteProductResponse { impl DummyJsonClient { /// Get all products pub async fn get_all_products(&self) -> Result { - let response = self.client.get(&*PRODUCTS_BASE_URL).send().await?; + let response = self.client.get(PRODUCTS_BASE_URL.as_str()).send().await?; response.json::().await } /// Get product by id pub async fn get_product_by_id(&self, id: u32) -> Result { - let url = &format!("{}/{}", &*PRODUCTS_BASE_URL, id); + let url = &format!("{}/{}", PRODUCTS_BASE_URL.as_str(), id); let response = self.client.get(url).send().await?; response.json::().await } @@ -116,7 +116,7 @@ impl DummyJsonClient { &self, query: &str, ) -> Result { - let url = &format!("{}/search?q={}", &*PRODUCTS_BASE_URL, query); + let url = &format!("{}/search?q={}", PRODUCTS_BASE_URL.as_str(), query); let response = self.client.get(url).send().await?; response.json::().await } @@ -128,8 +128,13 @@ impl DummyJsonClient { skip: u32, selects: &str, ) -> Result { - let url = - &format!("{}/?limit={}&skip={}&select={}", &*PRODUCTS_BASE_URL, limit, skip, selects); + let url = &format!( + "{}/?limit={}&skip={}&select={}", + PRODUCTS_BASE_URL.as_str(), + limit, + skip, + selects + ); let response = self.client.get(url).send().await?; response.json::().await } @@ -140,21 +145,21 @@ impl DummyJsonClient { field: &str, order: &str, ) -> Result { - let url = &format!("{}/?sortBy={}&order={}", &*PRODUCTS_BASE_URL, field, order); + let url = &format!("{}/?sortBy={}&order={}", PRODUCTS_BASE_URL.as_str(), field, order); let response = self.client.get(url).send().await?; response.json::().await } /// Get product categories pub async fn get_product_categories(&self) -> Result, reqwest::Error> { - let url = &format!("{}/categories", &*PRODUCTS_BASE_URL); + let url = &format!("{}/categories", PRODUCTS_BASE_URL.as_str()); let response = self.client.get(url).send().await?; response.json::>().await } /// Get product categories list pub async fn get_product_categories_list(&self) -> Result, reqwest::Error> { - let url = &format!("{}/category-list", &*PRODUCTS_BASE_URL); + let url = &format!("{}/category-list", PRODUCTS_BASE_URL.as_str()); let response = self.client.get(url).send().await?; response.json::>().await } @@ -164,14 +169,14 @@ impl DummyJsonClient { &self, category: &str, ) -> Result { - let url = &format!("{}/category/{}", &*PRODUCTS_BASE_URL, category); + let url = &format!("{}/category/{}", PRODUCTS_BASE_URL.as_str(), category); let response = self.client.get(url).send().await?; response.json::().await } /// Add product pub async fn add_product(&self, product: &AddProduct) -> Result { - let url = &format!("{}/add", &*PRODUCTS_BASE_URL); + let url = &format!("{}/add", PRODUCTS_BASE_URL.as_str()); let response = self.client.post(url).json(product).send().await?; response.json::().await } @@ -182,14 +187,14 @@ impl DummyJsonClient { id: u32, product: &AddProduct, ) -> Result { - let url = &format!("{}/{}", &*PRODUCTS_BASE_URL, id); + let url = &format!("{}/{}", PRODUCTS_BASE_URL.as_str(), id); let response = self.client.put(url).json(product).send().await?; response.json::().await } /// Delete product pub async fn delete_product(&self, id: u32) -> Result { - let url = &format!("{}/{}", &*PRODUCTS_BASE_URL, id); + let url = &format!("{}/{}", PRODUCTS_BASE_URL.as_str(), id); let response = self.client.delete(url).send().await?; response.json::().await } diff --git a/src/recipes.rs b/src/recipes.rs index 7e51290..c79818d 100644 --- a/src/recipes.rs +++ b/src/recipes.rs @@ -53,7 +53,7 @@ impl DummyJsonClient { /// Get recipe by id pub async fn get_recipe_by_id(&self, id: u32) -> Result { self.client - .get(format!("{}/{}", &*RECIPES_BASE_URL, id)) + .get(format!("{}/{}", RECIPES_BASE_URL.as_str(), id)) .send() .await? .json::() @@ -66,7 +66,7 @@ impl DummyJsonClient { query: &str, ) -> Result { self.client - .get(format!("{}/search?q={}", &*RECIPES_BASE_URL, query)) + .get(format!("{}/search?q={}", RECIPES_BASE_URL.as_str(), query)) .send() .await? .json::() @@ -83,7 +83,10 @@ impl DummyJsonClient { self.client .get(format!( "{}/?limit={}&skip={}&select={}", - &*RECIPES_BASE_URL, limit, skip, selects + RECIPES_BASE_URL.as_str(), + limit, + skip, + selects )) .send() .await? @@ -99,7 +102,7 @@ impl DummyJsonClient { order: &str, ) -> Result { self.client - .get(format!("{}/?sortBy={}&order={}", &*RECIPES_BASE_URL, sort_by, order)) + .get(format!("{}/?sortBy={}&order={}", RECIPES_BASE_URL.as_str(), sort_by, order)) .send() .await? .json::() @@ -109,7 +112,7 @@ impl DummyJsonClient { /// Get recipes tags pub async fn get_recipes_tags(&self) -> Result, reqwest::Error> { self.client - .get(format!("{}/tags", &*RECIPES_BASE_URL)) + .get(format!("{}/tags", RECIPES_BASE_URL.as_str())) .send() .await? .json::>() @@ -122,7 +125,7 @@ impl DummyJsonClient { tags: &str, ) -> Result { self.client - .get(format!("{}/tag/{}", &*RECIPES_BASE_URL, tags)) + .get(format!("{}/tag/{}", RECIPES_BASE_URL.as_str(), tags)) .send() .await? .json::() @@ -135,7 +138,7 @@ impl DummyJsonClient { meal_type: &str, ) -> Result { self.client - .get(format!("{}/meal-type/{}", &*RECIPES_BASE_URL, meal_type)) + .get(format!("{}/meal-type/{}", RECIPES_BASE_URL.as_str(), meal_type)) .send() .await? .json::() diff --git a/src/todos.rs b/src/todos.rs index 569233a..60b2eeb 100644 --- a/src/todos.rs +++ b/src/todos.rs @@ -42,57 +42,57 @@ pub struct DeleteTodoResponse { impl DummyJsonClient { /// Get all todos pub async fn get_all_todos(&self) -> Result { - let url = &*TODOS_BASE_URL; + let url = TODOS_BASE_URL.as_str(); self.client.get(url).send().await?.json().await } /// Get todo by id pub async fn get_todo_by_id(&self, id: u32) -> Result { - let url = format!("{}/{}", *TODOS_BASE_URL, id); + let url = format!("{}/{}", TODOS_BASE_URL.as_str(), id); self.client.get(url).send().await?.json().await } /// Get random todo pub async fn get_random_todo(&self) -> Result { - let url = format!("{}/random", *TODOS_BASE_URL); + let url = format!("{}/random", TODOS_BASE_URL.as_str()); self.client.get(url).send().await?.json().await } /// Get random todos pub async fn get_random_todos(&self, count: u32) -> Result, Error> { - let url = format!("{}/random/{}", *TODOS_BASE_URL, count); + let url = format!("{}/random/{}", TODOS_BASE_URL.as_str(), count); self.client.get(url).send().await?.json().await } /// Limit and skip todos pub async fn limit_skip_todos(&self, limit: u32, skip: u32) -> Result { - let url = format!("{}/?limit={}&skip={}", *TODOS_BASE_URL, limit, skip); + let url = format!("{}/?limit={}&skip={}", TODOS_BASE_URL.as_str(), limit, skip); self.client.get(url).send().await?.json().await } /// Get all todos of user pub async fn get_all_todos_of_user(&self, user_id: u32) -> Result { - let url = format!("{}/user/{}", *TODOS_BASE_URL, user_id); + let url = format!("{}/user/{}", TODOS_BASE_URL.as_str(), user_id); self.client.get(url).send().await?.json().await } /// Add todo pub async fn add_todo(&self, todo: &str, completed: bool, user_id: u32) -> Result { - let url = format!("{}/add", *TODOS_BASE_URL); + let url = format!("{}/add", TODOS_BASE_URL.as_str()); let payload = json!({ "todo": todo, "completed": completed, "userId": user_id }); self.client.post(url).json(&payload).send().await?.json().await } /// Update todo pub async fn update_todo(&self, id: u32, completed: bool) -> Result { - let url = format!("{}/{}", *TODOS_BASE_URL, id); + let url = format!("{}/{}", TODOS_BASE_URL.as_str(), id); let payload = json!({ "completed": completed }); self.client.put(url).json(&payload).send().await?.json().await } /// Delete todo pub async fn delete_todo(&self, id: u32) -> Result { - let url = format!("{}/{}", *TODOS_BASE_URL, id); + let url = format!("{}/{}", TODOS_BASE_URL.as_str(), id); self.client.delete(url).send().await?.json().await } } diff --git a/tests/posts.rs b/tests/posts.rs new file mode 100644 index 0000000..20a7a2f --- /dev/null +++ b/tests/posts.rs @@ -0,0 +1,112 @@ +#[cfg(test)] +mod posts { + use dummy_json_rs::{AddPost, DummyJsonClient}; + + #[tokio::test] + async fn get_all_posts() { + let client = DummyJsonClient::default(); + let response = client.get_all_posts().await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn get_post_by_id() { + let client = DummyJsonClient::default(); + let response = client.get_post_by_id(1).await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn search_posts() { + let client = DummyJsonClient::default(); + let response = client.search_posts("love").await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn limit_and_skip_posts() { + let client = DummyJsonClient::default(); + let response = client.limit_and_skip_posts(10, 10, "title,reactions,userId").await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn sort_posts() { + let client = DummyJsonClient::default(); + let response = client.sort_posts("title", "desc").await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn get_all_posts_tags() { + let client = DummyJsonClient::default(); + let response = client.get_all_posts_tags().await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn get_posts_by_tags() { + let client = DummyJsonClient::default(); + let response = client.get_posts_by_tags("nature").await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn get_posts_by_user_id() { + let client = DummyJsonClient::default(); + let response = client.get_posts_by_user_id(1).await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn get_post_comments() { + let client = DummyJsonClient::default(); + let response = client.get_post_comments(1).await; + // assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn add_post() { + let client = DummyJsonClient::default(); + let post = AddPost { + title: Some("test title".to_string()), + body: Some("test body".to_string()), + user_id: Some(1), + tags: Some(vec!["nature".to_string(), "photography".to_string()]), + ..Default::default() + }; + let response = client.add_post(&post).await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn update_post() { + let client = DummyJsonClient::default(); + let updated_post = AddPost { + title: Some("updated title".to_string()), + body: Some("updated body".to_string()), + ..Default::default() + }; + let response = client.update_post(1, &updated_post).await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } + + #[tokio::test] + async fn delete_post() { + let client = DummyJsonClient::default(); + let response = client.delete_post(1).await; + assert!(response.is_ok()); + println!("{:#?}", response.unwrap()); + } +}