tmdb_api/movie/
now_playing.rs1use chrono::NaiveDate;
2use std::borrow::Cow;
3
4use crate::common::PaginatedResult;
5
6#[derive(Clone, Debug, Default, serde::Serialize)]
7pub struct Params<'a> {
8 #[serde(skip_serializing_if = "Option::is_none")]
10 pub language: Option<Cow<'a, str>>,
11 #[serde(skip_serializing_if = "Option::is_none")]
13 pub page: Option<u32>,
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub region: Option<Cow<'a, str>>,
17}
18
19impl<'a> Params<'a> {
20 pub fn set_page(&mut self, value: u32) {
21 self.page = Some(value);
22 }
23
24 pub fn with_page(mut self, value: u32) -> Self {
25 self.set_page(value);
26 self
27 }
28
29 pub fn set_language(&mut self, value: impl Into<Cow<'a, str>>) {
30 self.language = Some(value.into());
31 }
32
33 pub fn with_language(mut self, value: impl Into<Cow<'a, str>>) -> Self {
34 self.set_language(value);
35 self
36 }
37
38 pub fn set_region(&mut self, value: impl Into<Cow<'a, str>>) {
39 self.region = Some(value.into());
40 }
41
42 pub fn with_region(mut self, value: impl Into<Cow<'a, str>>) -> Self {
43 self.set_region(value);
44 self
45 }
46}
47
48#[derive(Clone, Debug, Deserialize, Serialize)]
49pub struct DateRange {
50 #[serde(deserialize_with = "crate::util::empty_string::deserialize")]
51 pub maximum: Option<NaiveDate>,
52 #[serde(deserialize_with = "crate::util::empty_string::deserialize")]
53 pub minimum: Option<NaiveDate>,
54}
55
56#[derive(Clone, Debug, Deserialize, Serialize)]
57pub struct ListMoviesNowPlayingResponse {
58 #[serde(flatten)]
59 pub inner: PaginatedResult<super::MovieShort>,
60 pub dates: DateRange,
61}
62
63impl<E: crate::client::Executor> crate::Client<E> {
64 pub async fn list_movies_now_playing(
84 &self,
85 params: &Params<'_>,
86 ) -> crate::Result<ListMoviesNowPlayingResponse> {
87 self.execute("/movie/now_playing", params).await
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use crate::client::Client;
94 use crate::client::reqwest::ReqwestExecutor;
95 use mockito::Matcher;
96
97 #[tokio::test]
98 async fn it_works() {
99 let mut server = mockito::Server::new_async().await;
100 let client = Client::<ReqwestExecutor>::builder()
101 .with_api_key("secret".into())
102 .with_base_url(server.url())
103 .build()
104 .unwrap();
105
106 let _m = server
107 .mock("GET", "/movie/now_playing")
108 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
109 .with_status(200)
110 .with_header("content-type", "application/json")
111 .with_body(include_str!("../../assets/movie-now-playing.json"))
112 .create_async()
113 .await;
114
115 let result = client
116 .list_movies_now_playing(&Default::default())
117 .await
118 .unwrap();
119 assert_eq!(result.inner.page, 1);
120 }
121
122 #[tokio::test]
123 async fn invalid_api_key() {
124 let mut server = mockito::Server::new_async().await;
125 let client = Client::<ReqwestExecutor>::builder()
126 .with_api_key("secret".into())
127 .with_base_url(server.url())
128 .build()
129 .unwrap();
130
131 let _m = server
132 .mock("GET", "/movie/now_playing")
133 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
134 .with_status(401)
135 .with_header("content-type", "application/json")
136 .with_body(include_str!("../../assets/invalid-api-key.json"))
137 .create_async()
138 .await;
139
140 let err = client
141 .list_movies_now_playing(&Default::default())
142 .await
143 .unwrap_err();
144 let server_err = err.as_server_error().unwrap();
145 assert_eq!(server_err.status_code, 7);
146 }
147
148 #[tokio::test]
149 async fn resource_not_found() {
150 let mut server = mockito::Server::new_async().await;
151 let client = Client::<ReqwestExecutor>::builder()
152 .with_api_key("secret".into())
153 .with_base_url(server.url())
154 .build()
155 .unwrap();
156
157 let _m = server
158 .mock("GET", "/movie/now_playing")
159 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
160 .with_status(404)
161 .with_header("content-type", "application/json")
162 .with_body(include_str!("../../assets/resource-not-found.json"))
163 .create_async()
164 .await;
165
166 let err = client
167 .list_movies_now_playing(&Default::default())
168 .await
169 .unwrap_err();
170 let server_err = err.as_server_error().unwrap();
171 assert_eq!(server_err.status_code, 34);
172 }
173}
174
175#[cfg(all(test, feature = "integration"))]
176mod integration_tests {
177 use crate::client::Client;
178 use crate::client::reqwest::ReqwestExecutor;
179
180 #[tokio::test]
181 async fn execute() {
182 let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
183 let client = Client::<ReqwestExecutor>::new(secret);
184
185 let _result = client
186 .list_movies_now_playing(&Default::default())
187 .await
188 .unwrap();
189 }
190}