tmdb_api/movie/
now_playing.rs1use chrono::NaiveDate;
2use std::borrow::Cow;
3
4use crate::common::PaginatedResult;
5
6#[derive(Clone, Debug, Default)]
29pub struct MovieNowPlaying {
30 pub language: Option<String>,
32 pub page: Option<u32>,
34 pub region: Option<String>,
36}
37
38impl MovieNowPlaying {
39 pub fn with_language(mut self, value: Option<String>) -> Self {
40 self.language = value;
41 self
42 }
43
44 pub fn with_page(mut self, value: Option<u32>) -> Self {
45 self.page = value;
46 self
47 }
48
49 pub fn with_region(mut self, value: Option<String>) -> Self {
50 self.region = value;
51 self
52 }
53}
54
55#[derive(Clone, Debug, Deserialize, Serialize)]
56pub struct DateRange {
57 #[serde(deserialize_with = "crate::util::empty_string::deserialize")]
58 pub maximum: Option<NaiveDate>,
59 #[serde(deserialize_with = "crate::util::empty_string::deserialize")]
60 pub minimum: Option<NaiveDate>,
61}
62
63#[derive(Clone, Debug, Deserialize, Serialize)]
64pub struct MovieNowPlayingResult {
65 #[serde(flatten)]
66 pub inner: PaginatedResult<super::MovieShort>,
67 pub dates: DateRange,
68}
69
70impl crate::prelude::Command for MovieNowPlaying {
71 type Output = MovieNowPlayingResult;
72
73 fn path(&self) -> Cow<'static, str> {
74 Cow::Borrowed("/movie/now_playing")
75 }
76
77 fn params(&self) -> Vec<(&'static str, Cow<'_, str>)> {
78 let mut res = Vec::new();
79 if let Some(ref language) = self.language {
80 res.push(("language", Cow::Borrowed(language.as_str())))
81 }
82 if let Some(ref page) = self.page {
83 res.push(("page", Cow::Owned(page.to_string())))
84 }
85 if let Some(ref region) = self.region {
86 res.push(("region", Cow::Borrowed(region.as_str())))
87 }
88 res
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::MovieNowPlaying;
95 use crate::client::Client;
96 use crate::client::reqwest::ReqwestExecutor;
97 use crate::prelude::Command;
98 use mockito::Matcher;
99
100 #[tokio::test]
101 async fn it_works() {
102 let mut server = mockito::Server::new_async().await;
103 let client = Client::<ReqwestExecutor>::builder()
104 .with_api_key("secret".into())
105 .with_base_url(server.url())
106 .build()
107 .unwrap();
108
109 let _m = server
110 .mock("GET", "/movie/now_playing")
111 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
112 .with_status(200)
113 .with_header("content-type", "application/json")
114 .with_body(include_str!("../../assets/movie-now-playing.json"))
115 .create_async()
116 .await;
117
118 let result = MovieNowPlaying::default().execute(&client).await.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 = MovieNowPlaying::default()
141 .execute(&client)
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 = MovieNowPlaying::default()
167 .execute(&client)
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 super::MovieNowPlaying;
178 use crate::client::Client;
179 use crate::client::reqwest::ReqwestExecutor;
180 use crate::prelude::Command;
181
182 #[tokio::test]
183 async fn execute() {
184 let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
185 let client = Client::<ReqwestExecutor>::new(secret);
186
187 let _result = MovieNowPlaying::default().execute(&client).await.unwrap();
188 }
189}