tmdb_api/
genre.rs

1//! https://developer.themoviedb.org/reference/genre-movie-list
2//! https://developer.themoviedb.org/reference/genre-tv-list
3
4use crate::client::Executor;
5
6const TV_PATH: &str = "/genre/tv/list";
7const MOVIE_PATH: &str = "/genre/movie/list";
8
9#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
10pub struct Genre {
11    pub id: u64,
12    pub name: String,
13}
14
15#[derive(Clone, Debug, Deserialize)]
16pub struct Response {
17    pub genres: Vec<Genre>,
18}
19
20pub type Params<'a> = crate::common::LanguageParams<'a>;
21
22impl<E: Executor> crate::Client<E> {
23    /// List genres for movies
24    ///
25    /// ```rust
26    /// use tmdb_api::Client;
27    /// use tmdb_api::client::reqwest::Client as ReqwestClient;
28    ///
29    /// #[tokio::main]
30    /// async fn main() {
31    ///     let client = Client::<ReqwestClient>::new("this-is-my-secret-token".into());
32    ///     match client.list_movie_genres(&Default::default()).await {
33    ///         Ok(res) => println!("found: {:#?}", res),
34    ///         Err(err) => eprintln!("error: {:?}", err),
35    ///     };
36    /// }
37    /// ```
38    pub async fn list_movie_genres(&self, params: &Params<'_>) -> crate::Result<Response> {
39        self.execute(MOVIE_PATH, params).await
40    }
41
42    /// List genres for tvshows
43    ///
44    /// ```rust
45    /// use tmdb_api::Client;
46    /// use tmdb_api::client::reqwest::Client as ReqwestClient;
47    ///
48    /// #[tokio::main]
49    /// async fn main() {
50    ///     let client = Client::<ReqwestClient>::new("this-is-my-secret-token".into());
51    ///     match client.list_tvshow_genres(&Default::default()).await {
52    ///         Ok(res) => println!("found: {:#?}", res),
53    ///         Err(err) => eprintln!("error: {:?}", err),
54    ///     };
55    /// }
56    /// ```
57    pub async fn list_tvshow_genres(&self, params: &Params<'_>) -> crate::Result<Response> {
58        self.execute(TV_PATH, params).await
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use mockito::Matcher;
65
66    use crate::client::Client;
67    use crate::client::reqwest::Client as ReqwestClient;
68
69    #[tokio::test]
70    async fn movie_works() {
71        let mut server = mockito::Server::new_async().await;
72        let m = server
73            .mock("GET", super::MOVIE_PATH)
74            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
75            .with_status(200)
76            .with_header("content-type", "application/json")
77            .with_body(include_str!("../assets/genre-movie-list.json"))
78            .create_async()
79            .await;
80
81        let client = Client::<ReqwestClient>::builder()
82            .with_api_key("secret".into())
83            .with_base_url(server.url())
84            .build()
85            .unwrap();
86        let result = client.list_movie_genres(&Default::default()).await.unwrap();
87        assert!(!result.genres.is_empty());
88
89        m.assert_async().await;
90    }
91
92    #[tokio::test]
93    async fn tv_works() {
94        let mut server = mockito::Server::new_async().await;
95        let m = server
96            .mock("GET", super::TV_PATH)
97            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
98            .with_status(200)
99            .with_header("content-type", "application/json")
100            .with_body(include_str!("../assets/genre-tv-list.json"))
101            .create_async()
102            .await;
103
104        let client = Client::<ReqwestClient>::builder()
105            .with_api_key("secret".into())
106            .with_base_url(server.url())
107            .build()
108            .unwrap();
109        let result = client
110            .list_tvshow_genres(&Default::default())
111            .await
112            .unwrap();
113        assert!(!result.genres.is_empty());
114
115        m.assert_async().await;
116    }
117
118    #[tokio::test]
119    async fn invalid_api_key() {
120        let mut server = mockito::Server::new_async().await;
121        let m = server
122            .mock("GET", super::TV_PATH)
123            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
124            .with_status(401)
125            .with_header("content-type", "application/json")
126            .with_body(include_str!("../assets/invalid-api-key.json"))
127            .create_async()
128            .await;
129        let client = Client::<ReqwestClient>::builder()
130            .with_api_key("secret".into())
131            .with_base_url(server.url())
132            .build()
133            .unwrap();
134
135        let err = client
136            .list_tvshow_genres(&Default::default())
137            .await
138            .unwrap_err();
139        let server_err = err.as_server_error().unwrap();
140        assert_eq!(server_err.status_code, 7);
141
142        m.assert_async().await;
143    }
144
145    #[tokio::test]
146    async fn resource_not_found() {
147        let mut server = mockito::Server::new_async().await;
148        let m = server
149            .mock("GET", super::TV_PATH)
150            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
151            .with_status(404)
152            .with_header("content-type", "application/json")
153            .with_body(include_str!("../assets/resource-not-found.json"))
154            .create_async()
155            .await;
156        let client = Client::<ReqwestClient>::builder()
157            .with_api_key("secret".into())
158            .with_base_url(server.url())
159            .build()
160            .unwrap();
161        let err = client
162            .list_tvshow_genres(&Default::default())
163            .await
164            .unwrap_err();
165        let server_err = err.as_server_error().unwrap();
166        assert_eq!(server_err.status_code, 34);
167        m.assert_async().await;
168    }
169}
170
171#[cfg(all(test, feature = "integration"))]
172mod integration_tests {
173    use super::Params;
174    use crate::client::Client;
175    use crate::client::reqwest::Client as ReqwestClient;
176
177    #[tokio::test]
178    async fn execute_tv() {
179        let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
180        let client = Client::<ReqwestClient>::new(secret);
181        let result = client
182            .list_tvshow_genres(&Params::default().with_language("en-US"))
183            .await
184            .unwrap();
185        assert!(!result.genres.is_empty());
186    }
187
188    #[tokio::test]
189    async fn execute_movie() {
190        let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
191        let client = Client::<ReqwestClient>::new(secret);
192        let result = client
193            .list_movie_genres(&Params::default().with_language("en-US"))
194            .await
195            .unwrap();
196        assert!(!result.genres.is_empty());
197    }
198}