tmdb_api/movie/
upcoming.rs

1use std::borrow::Cow;
2
3use crate::common::PaginatedResult;
4
5#[derive(Clone, Debug, Default, serde::Serialize)]
6pub struct Params<'a> {
7    /// ISO 639-1 value to display translated data for the fields that support it.
8    #[serde(skip_serializing_if = "Option::is_none")]
9    pub language: Option<Cow<'a, str>>,
10    /// Specify which page to query.
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub page: Option<u32>,
13    /// Specify a ISO 3166-1 code to filter release dates. Must be uppercase.
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub region: Option<Cow<'a, str>>,
16}
17
18impl<'a> Params<'a> {
19    pub fn set_page(&mut self, value: u32) {
20        self.page = Some(value);
21    }
22
23    pub fn with_page(mut self, value: u32) -> Self {
24        self.set_page(value);
25        self
26    }
27
28    pub fn set_language(&mut self, value: impl Into<Cow<'a, str>>) {
29        self.language = Some(value.into());
30    }
31
32    pub fn with_language(mut self, value: impl Into<Cow<'a, str>>) -> Self {
33        self.set_language(value);
34        self
35    }
36
37    pub fn set_region(&mut self, value: impl Into<Cow<'a, str>>) {
38        self.region = Some(value.into());
39    }
40
41    pub fn with_region(mut self, value: impl Into<Cow<'a, str>>) -> Self {
42        self.set_region(value);
43        self
44    }
45}
46
47impl<E: crate::client::Executor> crate::Client<E> {
48    /// Get a list of upcoming movies in theatres. This is a release type query that looks
49    /// for all movies that have a release type of 2 or 3 within the specified date range.
50    ///
51    /// You can optionally specify a region parameter which will narrow the search to only
52    /// look for theatrical release dates within the specified country.
53    ///
54    /// ```rust
55    /// use tmdb_api::client::Client;
56    /// use tmdb_api::client::reqwest::ReqwestExecutor;
57    ///
58    /// #[tokio::main]
59    /// async fn main() {
60    ///     let client = Client::<ReqwestExecutor>::new("this-is-my-secret-token".into());
61    ///     match client.list_movies_upcoming(&Default::default()).await {
62    ///         Ok(res) => println!("found: {:#?}", res),
63    ///         Err(err) => eprintln!("error: {:?}", err),
64    ///     };
65    /// }
66    /// ```
67    pub async fn list_movies_upcoming(
68        &self,
69        params: &Params<'_>,
70    ) -> crate::Result<PaginatedResult<super::MovieShort>> {
71        self.execute("/movie/upcoming", params).await
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use crate::client::Client;
78    use crate::client::reqwest::ReqwestExecutor;
79    use mockito::Matcher;
80
81    #[tokio::test]
82    async fn it_works() {
83        let mut server = mockito::Server::new_async().await;
84        let client = Client::<ReqwestExecutor>::builder()
85            .with_api_key("secret".into())
86            .with_base_url(server.url())
87            .build()
88            .unwrap();
89
90        let _m = server
91            .mock("GET", "/movie/upcoming")
92            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
93            .with_status(200)
94            .with_header("content-type", "application/json")
95            .with_body(include_str!("../../assets/movie-upcoming.json"))
96            .create_async()
97            .await;
98
99        let result = client
100            .list_movies_upcoming(&Default::default())
101            .await
102            .unwrap();
103        assert_eq!(result.page, 1);
104    }
105
106    #[tokio::test]
107    async fn invalid_api_key() {
108        let mut server = mockito::Server::new_async().await;
109        let client = Client::<ReqwestExecutor>::builder()
110            .with_api_key("secret".into())
111            .with_base_url(server.url())
112            .build()
113            .unwrap();
114
115        let _m = server
116            .mock("GET", "/movie/upcoming")
117            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
118            .with_status(401)
119            .with_header("content-type", "application/json")
120            .with_body(include_str!("../../assets/invalid-api-key.json"))
121            .create_async()
122            .await;
123
124        let err = client
125            .list_movies_upcoming(&Default::default())
126            .await
127            .unwrap_err();
128        let server_err = err.as_server_error().unwrap();
129        assert_eq!(server_err.status_code, 7);
130    }
131
132    #[tokio::test]
133    async fn resource_not_found() {
134        let mut server = mockito::Server::new_async().await;
135        let client = Client::<ReqwestExecutor>::builder()
136            .with_api_key("secret".into())
137            .with_base_url(server.url())
138            .build()
139            .unwrap();
140
141        let _m = server
142            .mock("GET", "/movie/upcoming")
143            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
144            .with_status(404)
145            .with_header("content-type", "application/json")
146            .with_body(include_str!("../../assets/resource-not-found.json"))
147            .create_async()
148            .await;
149
150        let err = client
151            .list_movies_upcoming(&Default::default())
152            .await
153            .unwrap_err();
154        let server_err = err.as_server_error().unwrap();
155        assert_eq!(server_err.status_code, 34);
156    }
157}
158
159#[cfg(all(test, feature = "integration"))]
160mod integration_tests {
161    use crate::client::Client;
162    use crate::client::reqwest::ReqwestExecutor;
163
164    #[tokio::test]
165    async fn execute() {
166        let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
167        let client = Client::<ReqwestExecutor>::new(secret);
168
169        let _result = client
170            .list_movies_upcoming(&Default::default())
171            .await
172            .unwrap();
173    }
174}