1use 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 pub async fn list_movie_genres(&self, params: &Params<'_>) -> crate::Result<Response> {
39 self.execute(MOVIE_PATH, params).await
40 }
41
42 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}