tmdb_api/certification/
list.rs1use 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#[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}