tmdb_api/movie/
reviews.rs1use crate::common::PaginatedResult;
2
3pub type Params<'a> = crate::common::LanguagePageParams<'a>;
4
5#[derive(Debug, Deserialize, Serialize)]
6pub struct AuthorDetails {
7 pub name: String,
8 pub username: String,
9 pub avatar_path: Option<String>,
10 pub rating: Option<f32>,
11}
12
13#[derive(Debug, Deserialize, Serialize)]
14pub struct MovieReview {
15 pub id: String,
16 pub author: String,
17 pub author_details: AuthorDetails,
18 pub content: String,
19 pub url: String,
20 pub created_at: chrono::DateTime<chrono::Utc>,
21 pub updated_at: chrono::DateTime<chrono::Utc>,
22}
23
24impl<E: crate::client::Executor> crate::Client<E> {
25 pub async fn get_movie_reviews(
41 &self,
42 movie_id: u64,
43 params: &Params<'_>,
44 ) -> crate::Result<PaginatedResult<MovieReview>> {
45 let url = format!("/movie/{movie_id}/reviews");
46 self.execute(&url, params).await
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use mockito::Matcher;
53
54 use crate::client::Client;
55 use crate::client::reqwest::Client as ReqwestClient;
56
57 #[tokio::test]
58 async fn it_works() {
59 let mut server = mockito::Server::new_async().await;
60 let client = Client::<ReqwestClient>::builder()
61 .with_api_key("secret".into())
62 .with_base_url(server.url())
63 .build()
64 .unwrap();
65
66 let _m = server
67 .mock("GET", "/movie/550/reviews")
68 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
69 .with_status(200)
70 .with_header("content-type", "application/json")
71 .with_body(include_str!("../../assets/movie-reviews.json"))
72 .create_async()
73 .await;
74
75 let result = client
76 .get_movie_reviews(550, &Default::default())
77 .await
78 .unwrap();
79 assert_eq!(result.page, 1);
80 assert!(!result.results.is_empty());
81 }
82
83 #[tokio::test]
84 async fn invalid_api_key() {
85 let mut server = mockito::Server::new_async().await;
86 let client = Client::<ReqwestClient>::builder()
87 .with_api_key("secret".into())
88 .with_base_url(server.url())
89 .build()
90 .unwrap();
91
92 let _m = server
93 .mock("GET", "/movie/550/reviews")
94 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
95 .with_status(401)
96 .with_header("content-type", "application/json")
97 .with_body(include_str!("../../assets/invalid-api-key.json"))
98 .create_async()
99 .await;
100
101 let err = client
102 .get_movie_reviews(550, &Default::default())
103 .await
104 .unwrap_err();
105 let server_err = err.as_server_error().unwrap();
106 assert_eq!(server_err.status_code, 7);
107 }
108
109 #[tokio::test]
110 async fn resource_not_found() {
111 let mut server = mockito::Server::new_async().await;
112 let client = Client::<ReqwestClient>::builder()
113 .with_api_key("secret".into())
114 .with_base_url(server.url())
115 .build()
116 .unwrap();
117
118 let _m = server
119 .mock("GET", "/movie/550/reviews")
120 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
121 .with_status(404)
122 .with_header("content-type", "application/json")
123 .with_body(include_str!("../../assets/resource-not-found.json"))
124 .create_async()
125 .await;
126
127 let err = client
128 .get_movie_reviews(550, &Default::default())
129 .await
130 .unwrap_err();
131 let server_err = err.as_server_error().unwrap();
132 assert_eq!(server_err.status_code, 34);
133 }
134}
135
136#[cfg(all(test, feature = "integration"))]
137mod integration_tests {
138 use crate::client::Client;
139 use crate::client::reqwest::Client as ReqwestClient;
140
141 #[tokio::test]
142 async fn execute() {
143 let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
144 let client = Client::<ReqwestClient>::new(secret);
145 let result = client
146 .get_movie_reviews(550, &Default::default())
147 .await
148 .unwrap();
149 assert_eq!(result.page, 1);
150 }
151}