tmdb_api/configuration/
countries.rs

1//! https://developer.themoviedb.org/reference/configuration-countries
2
3use std::borrow::Cow;
4
5/// Get a list of all countries
6///
7/// ```rust
8/// use tmdb_api::prelude::Command;
9/// use tmdb_api::Client;
10/// use tmdb_api::client::reqwest::ReqwestExecutor;
11/// use tmdb_api::configuration::countries::Countries;
12///
13/// #[tokio::main]
14/// async fn main() {
15///     let client = Client::<ReqwestExecutor>::new("this-is-my-secret-token".into());
16///     let result = Countries::default().execute(&client).await;
17///     match result {
18///         Ok(res) => println!("found: {res:#?}"),
19///         Err(err) => eprintln!("error: {err:?}"),
20///     };
21/// }
22/// ```
23#[derive(Clone, Debug, Default)]
24pub struct Countries {
25    language: Option<String>,
26}
27
28#[derive(Debug, Deserialize)]
29pub struct CountriesResult {
30    pub iso_3166_1: String,
31    pub english_name: String,
32    pub native_name: String,
33}
34
35impl Countries {
36    pub fn new() -> Self {
37        Self { language: None }
38    }
39
40    pub fn with_language(mut self, value: Option<String>) -> Self {
41        self.language = value;
42        self
43    }
44}
45
46impl crate::prelude::Command for Countries {
47    type Output = Vec<CountriesResult>;
48
49    fn path(&self) -> Cow<'static, str> {
50        Cow::Borrowed("/configuration/countries")
51    }
52
53    fn params(&self) -> Vec<(&'static str, Cow<'_, str>)> {
54        if let Some(ref language) = self.language {
55            vec![("language", Cow::Borrowed(language))]
56        } else {
57            Vec::new()
58        }
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use mockito::Matcher;
65
66    use crate::Client;
67    use crate::client::reqwest::ReqwestExecutor;
68    use crate::prelude::Command;
69
70    use super::Countries;
71
72    #[tokio::test]
73    async fn it_works() {
74        let mut server = mockito::Server::new_async().await;
75        let client = Client::<ReqwestExecutor>::builder()
76            .with_api_key("secret".into())
77            .with_base_url(server.url())
78            .build()
79            .unwrap();
80
81        let _m = server
82            .mock("GET", "/configuration/countries")
83            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
84            .with_status(200)
85            .with_header("content-type", "application/json")
86            .with_body(include_str!("../../assets/configuration-countries.json"))
87            .create_async()
88            .await;
89
90        let result = Countries::default().execute(&client).await.unwrap();
91        assert!(!result.is_empty());
92    }
93
94    #[tokio::test]
95    async fn invalid_api_key() {
96        let mut server = mockito::Server::new_async().await;
97        let client = Client::<ReqwestExecutor>::builder()
98            .with_api_key("secret".into())
99            .with_base_url(server.url())
100            .build()
101            .unwrap();
102
103        let _m = server
104            .mock("GET", "/configuration/countries")
105            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
106            .with_status(401)
107            .with_header("content-type", "application/json")
108            .with_body(include_str!("../../assets/invalid-api-key.json"))
109            .create_async()
110            .await;
111
112        let err = Countries::default().execute(&client).await.unwrap_err();
113        let server_err = err.as_server_error().unwrap();
114        assert_eq!(server_err.status_code, 7);
115    }
116
117    #[tokio::test]
118    async fn resource_not_found() {
119        let mut server = mockito::Server::new_async().await;
120        let client = Client::<ReqwestExecutor>::builder()
121            .with_api_key("secret".into())
122            .with_base_url(server.url())
123            .build()
124            .unwrap();
125
126        let _m = server
127            .mock("GET", "/configuration/countries")
128            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
129            .with_status(404)
130            .with_header("content-type", "application/json")
131            .with_body(include_str!("../../assets/resource-not-found.json"))
132            .create_async()
133            .await;
134
135        let err = Countries::default().execute(&client).await.unwrap_err();
136        let server_err = err.as_server_error().unwrap();
137        assert_eq!(server_err.status_code, 34);
138    }
139}
140
141#[cfg(all(test, feature = "integration"))]
142mod integration_tests {
143    use crate::Client;
144    use crate::client::reqwest::ReqwestExecutor;
145    use crate::prelude::Command;
146
147    use super::Countries;
148
149    #[tokio::test]
150    async fn execute() {
151        let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
152        let client = Client::<ReqwestExecutor>::new(secret);
153
154        let result = Countries::default().execute(&client).await.unwrap();
155        assert!(!result.is_empty());
156    }
157}