tmdb_api/movie/
alternative_titles.rs

1use std::borrow::Cow;
2
3use crate::client::Executor;
4
5#[derive(Clone, Debug, Default, serde::Serialize)]
6pub struct Params<'a> {
7    /// The country to filter the alternative titles
8    #[serde(skip_serializing_if = "Option::is_none")]
9    pub country: Option<Cow<'a, str>>,
10}
11
12impl<'a> Params<'a> {
13    pub fn set_country(&mut self, value: impl Into<Cow<'a, str>>) {
14        self.country = Some(value.into());
15    }
16
17    pub fn with_country(mut self, value: impl Into<Cow<'a, str>>) -> Self {
18        self.set_country(value);
19        self
20    }
21}
22
23#[derive(Clone, Debug, Deserialize, Serialize)]
24pub struct MovieAlternativeTitle {
25    pub iso_3166_1: String,
26    pub title: String,
27    #[serde(
28        deserialize_with = "crate::util::empty_string::deserialize",
29        rename = "type"
30    )]
31    pub kind: Option<String>,
32}
33
34#[derive(Clone, Debug, Deserialize)]
35pub struct Response {
36    pub titles: Vec<MovieAlternativeTitle>,
37}
38
39impl<E: Executor> crate::Client<E> {
40    /// Command to get alternative titles for a movie
41    ///
42    /// ```rust
43    /// use tmdb_api::client::Client;
44    /// use tmdb_api::client::reqwest::Client as ReqwestClient;
45    ///
46    /// #[tokio::main]
47    /// async fn main() {
48    ///     let client = Client::<ReqwestClient>::new("this-is-my-secret-token".into());
49    ///     match client.get_movie_alternative_titles(42, &Default::default()).await {
50    ///         Ok(res) => println!("found: {:#?}", res),
51    ///         Err(err) => eprintln!("error: {:?}", err),
52    ///     };
53    /// }
54    /// ```
55    pub async fn get_movie_alternative_titles(
56        &self,
57        movie_id: u64,
58        params: &Params<'_>,
59    ) -> crate::Result<Response> {
60        let url = format!("/movie/{movie_id}/alternative_titles");
61        self.execute(&url, params).await
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use mockito::Matcher;
68
69    use crate::client::Client;
70    use crate::client::reqwest::Client as ReqwestClient;
71
72    #[tokio::test]
73    async fn it_works() {
74        let mut server = mockito::Server::new_async().await;
75        let m = server
76            .mock("GET", "/movie/3/alternative_titles")
77            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
78            .with_status(200)
79            .with_header("content-type", "application/json")
80            .with_body(include_str!("../../assets/movie-alternative-titles.json"))
81            .create_async()
82            .await;
83
84        let client = Client::<ReqwestClient>::builder()
85            .with_api_key("secret".into())
86            .with_base_url(server.url())
87            .build()
88            .unwrap();
89        let result = client
90            .get_movie_alternative_titles(3, &Default::default())
91            .await
92            .unwrap();
93        assert!(!result.titles.is_empty());
94
95        m.assert_async().await;
96    }
97
98    #[tokio::test]
99    async fn invalid_api_key() {
100        let mut server = mockito::Server::new_async().await;
101        let m = server
102            .mock("GET", "/movie/1/alternative_titles")
103            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
104            .with_status(401)
105            .with_header("content-type", "application/json")
106            .with_body(include_str!("../../assets/invalid-api-key.json"))
107            .create_async()
108            .await;
109
110        let client = Client::<ReqwestClient>::builder()
111            .with_api_key("secret".into())
112            .with_base_url(server.url())
113            .build()
114            .unwrap();
115        let err = client
116            .get_movie_alternative_titles(1, &Default::default())
117            .await
118            .unwrap_err();
119        let server_err = err.as_server_error().unwrap();
120        assert_eq!(server_err.status_code, 7);
121
122        m.assert_async().await;
123    }
124
125    #[tokio::test]
126    async fn resource_not_found() {
127        let mut server = mockito::Server::new_async().await;
128        let m = server
129            .mock("GET", "/movie/1/alternative_titles")
130            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
131            .with_status(404)
132            .with_header("content-type", "application/json")
133            .with_body(include_str!("../../assets/resource-not-found.json"))
134            .create_async()
135            .await;
136
137        let client = Client::<ReqwestClient>::builder()
138            .with_api_key("secret".into())
139            .with_base_url(server.url())
140            .build()
141            .unwrap();
142        let err = client
143            .get_movie_alternative_titles(1, &Default::default())
144            .await
145            .unwrap_err();
146        let server_err = err.as_server_error().unwrap();
147        assert_eq!(server_err.status_code, 34);
148
149        m.assert_async().await;
150    }
151}
152
153#[cfg(all(test, feature = "integration"))]
154mod integration_tests {
155    use crate::client::Client;
156    use crate::client::reqwest::Client as ReqwestClient;
157
158    #[tokio::test]
159    async fn execute() {
160        let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
161        let client = Client::<ReqwestClient>::new(secret);
162        let result = client
163            .get_movie_alternative_titles(3, &Default::default())
164            .await
165            .unwrap();
166        assert!(!result.titles.is_empty());
167    }
168}