tmdb_api/certification/
list.rs

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