tmdb_api/movie/
changes.rs

1use crate::client::Executor;
2
3pub use crate::changes::list::Params;
4
5#[derive(Clone, Debug, Deserialize, Serialize)]
6pub struct MovieChange {
7    pub key: String,
8    pub items: Vec<MovieChangeItem>,
9}
10
11#[derive(Clone, Debug, Deserialize, Serialize)]
12pub struct MovieChangeItem {
13    pub id: String,
14    pub action: String,
15    pub time: chrono::DateTime<chrono::Utc>,
16    pub iso_639_1: String,
17    pub iso_3166_1: String,
18    // TODO handle really dynamic kind of values
19    // pub value: String,
20    // pub original_value: String,
21}
22
23#[derive(Clone, Debug, Deserialize)]
24pub struct Response {
25    pub changes: Vec<MovieChange>,
26}
27
28impl<E: Executor> crate::Client<E> {
29    /// List changes for a movie
30    ///
31    /// ```rust
32    /// use tmdb_api::client::Client;
33    /// use tmdb_api::client::reqwest::ReqwestExecutor;
34    ///
35    /// #[tokio::main]
36    /// async fn main() {
37    ///     let client = Client::<ReqwestExecutor>::new("this-is-my-secret-token".into());
38    ///     match client.get_movie_changes(42, &Default::default()).await {
39    ///         Ok(res) => println!("found: {:#?}", res),
40    ///         Err(err) => eprintln!("error: {:?}", err),
41    ///     };
42    /// }
43    /// ```
44    pub async fn get_movie_changes(
45        &self,
46        movie_id: u64,
47        params: &Params,
48    ) -> crate::Result<Response> {
49        let url = format!("/movie/{movie_id}/changes");
50        self.execute(&url, params).await
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use crate::client::Client;
57    use crate::client::reqwest::ReqwestExecutor;
58    use mockito::Matcher;
59
60    #[tokio::test]
61    async fn it_works() {
62        let mut server = mockito::Server::new_async().await;
63        let m = server
64            .mock("GET", "/movie/3/changes")
65            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
66            .with_status(200)
67            .with_header("content-type", "application/json")
68            .with_body(include_str!("../../assets/movie-single-changes.json"))
69            .create_async()
70            .await;
71
72        let client = Client::<ReqwestExecutor>::builder()
73            .with_api_key("secret".into())
74            .with_base_url(server.url())
75            .build()
76            .unwrap();
77        let result = client
78            .get_movie_changes(3, &Default::default())
79            .await
80            .unwrap();
81        assert_eq!(result.changes.len(), 1);
82
83        m.assert_async().await;
84    }
85
86    #[tokio::test]
87    async fn invalid_api_key() {
88        let mut server = mockito::Server::new_async().await;
89        let m = server
90            .mock("GET", "/movie/1/changes")
91            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
92            .with_status(401)
93            .with_header("content-type", "application/json")
94            .with_body(include_str!("../../assets/invalid-api-key.json"))
95            .create_async()
96            .await;
97
98        let client = Client::<ReqwestExecutor>::builder()
99            .with_api_key("secret".into())
100            .with_base_url(server.url())
101            .build()
102            .unwrap();
103        let err = client
104            .get_movie_changes(1, &Default::default())
105            .await
106            .unwrap_err();
107        let server_err = err.as_server_error().unwrap();
108        assert_eq!(server_err.status_code, 7);
109
110        m.assert_async().await;
111    }
112
113    #[tokio::test]
114    async fn resource_not_found() {
115        let mut server = mockito::Server::new_async().await;
116        let m = server
117            .mock("GET", "/movie/1/changes")
118            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
119            .with_status(404)
120            .with_header("content-type", "application/json")
121            .with_body(include_str!("../../assets/resource-not-found.json"))
122            .create_async()
123            .await;
124
125        let client = Client::<ReqwestExecutor>::builder()
126            .with_api_key("secret".into())
127            .with_base_url(server.url())
128            .build()
129            .unwrap();
130        let err = client
131            .get_movie_changes(1, &Default::default())
132            .await
133            .unwrap_err();
134        let server_err = err.as_server_error().unwrap();
135        assert_eq!(server_err.status_code, 34);
136
137        m.assert_async().await;
138    }
139}
140
141#[cfg(all(test, feature = "integration"))]
142mod integration_tests {
143    use super::Params;
144    use crate::client::Client;
145    use crate::client::reqwest::ReqwestExecutor;
146
147    #[tokio::test]
148    async fn execute() {
149        let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
150        let client = Client::<ReqwestExecutor>::new(secret);
151        let params = Params::default()
152            .with_start_date(chrono::NaiveDate::from_ymd_opt(2015, 3, 14).unwrap())
153            .with_end_date(chrono::NaiveDate::from_ymd_opt(2019, 3, 14).unwrap());
154        let result = client.get_movie_changes(1, &params).await.unwrap();
155        assert!(result.changes.is_empty());
156    }
157}