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 crate::client::Client;
68    use crate::client::reqwest::Client as ReqwestClient;
69    use mockito::Matcher;
70
71    #[tokio::test]
72    async fn it_works() {
73        let mut server = mockito::Server::new_async().await;
74        let m = server
75            .mock("GET", "/movie/3/alternative_titles")
76            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
77            .with_status(200)
78            .with_header("content-type", "application/json")
79            .with_body(include_str!("../../assets/movie-alternative-titles.json"))
80            .create_async()
81            .await;
82
83        let client = Client::<ReqwestClient>::builder()
84            .with_api_key("secret".into())
85            .with_base_url(server.url())
86            .build()
87            .unwrap();
88        let result = client
89            .get_movie_alternative_titles(3, &Default::default())
90            .await
91            .unwrap();
92        assert!(!result.titles.is_empty());
93
94        m.assert_async().await;
95    }
96
97    #[tokio::test]
98    async fn invalid_api_key() {
99        let mut server = mockito::Server::new_async().await;
100        let m = server
101            .mock("GET", "/movie/1/alternative_titles")
102            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
103            .with_status(401)
104            .with_header("content-type", "application/json")
105            .with_body(include_str!("../../assets/invalid-api-key.json"))
106            .create_async()
107            .await;
108
109        let client = Client::<ReqwestClient>::builder()
110            .with_api_key("secret".into())
111            .with_base_url(server.url())
112            .build()
113            .unwrap();
114        let err = client
115            .get_movie_alternative_titles(1, &Default::default())
116            .await
117            .unwrap_err();
118        let server_err = err.as_server_error().unwrap();
119        assert_eq!(server_err.status_code, 7);
120
121        m.assert_async().await;
122    }
123
124    #[tokio::test]
125    async fn resource_not_found() {
126        let mut server = mockito::Server::new_async().await;
127        let m = server
128            .mock("GET", "/movie/1/alternative_titles")
129            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
130            .with_status(404)
131            .with_header("content-type", "application/json")
132            .with_body(include_str!("../../assets/resource-not-found.json"))
133            .create_async()
134            .await;
135
136        let client = Client::<ReqwestClient>::builder()
137            .with_api_key("secret".into())
138            .with_base_url(server.url())
139            .build()
140            .unwrap();
141        let err = client
142            .get_movie_alternative_titles(1, &Default::default())
143            .await
144            .unwrap_err();
145        let server_err = err.as_server_error().unwrap();
146        assert_eq!(server_err.status_code, 34);
147
148        m.assert_async().await;
149    }
150}
151
152#[cfg(all(test, feature = "integration"))]
153mod integration_tests {
154    use crate::client::Client;
155    use crate::client::reqwest::Client as ReqwestClient;
156
157    #[tokio::test]
158    async fn execute() {
159        let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
160        let client = Client::<ReqwestClient>::new(secret);
161        let result = client
162            .get_movie_alternative_titles(3, &Default::default())
163            .await
164            .unwrap();
165        assert!(!result.titles.is_empty());
166    }
167}