tmdb_api/movie/
changes.rs1pub use crate::changes::list::Params;
2use crate::client::Executor;
3
4#[derive(Clone, Debug, Deserialize, Serialize)]
5pub struct MovieChange {
6 pub key: String,
7 pub items: Vec<MovieChangeItem>,
8}
9
10#[derive(Clone, Debug, Deserialize, Serialize)]
11pub struct MovieChangeItem {
12 pub id: String,
13 pub action: String,
14 pub time: chrono::DateTime<chrono::Utc>,
15 pub iso_639_1: String,
16 pub iso_3166_1: String,
17 }
21
22#[derive(Clone, Debug, Deserialize)]
23pub struct Response {
24 pub changes: Vec<MovieChange>,
25}
26
27impl<E: Executor> crate::Client<E> {
28 pub async fn get_movie_changes(
44 &self,
45 movie_id: u64,
46 params: &Params,
47 ) -> crate::Result<Response> {
48 let url = format!("/movie/{movie_id}/changes");
49 self.execute(&url, params).await
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use mockito::Matcher;
56
57 use crate::client::Client;
58 use crate::client::reqwest::Client as ReqwestClient;
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::<ReqwestClient>::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::<ReqwestClient>::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::<ReqwestClient>::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::Client as ReqwestClient;
146
147 #[tokio::test]
148 async fn execute() {
149 let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
150 let client = Client::<ReqwestClient>::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, ¶ms).await.unwrap();
155 assert!(result.changes.is_empty());
156 }
157}