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