tmdb_api/movie/
recommendations.rs1use std::borrow::Cow;
2
3use crate::common::PaginatedResult;
4
5#[derive(Clone, Debug, Default)]
25pub struct MovieRecommendations {
26 pub movie_id: u64,
28 pub language: Option<String>,
30 pub page: Option<u32>,
32}
33
34impl MovieRecommendations {
35 pub fn new(movie_id: u64) -> Self {
36 Self {
37 movie_id,
38 language: None,
39 page: None,
40 }
41 }
42
43 pub fn with_language(mut self, value: Option<String>) -> Self {
44 self.language = value;
45 self
46 }
47
48 pub fn with_page(mut self, value: Option<u32>) -> Self {
49 self.page = value;
50 self
51 }
52}
53
54impl crate::prelude::Command for MovieRecommendations {
55 type Output = PaginatedResult<super::MovieShort>;
56
57 fn path(&self) -> Cow<'static, str> {
58 Cow::Owned(format!("/movie/{}/recommendations", self.movie_id))
59 }
60
61 fn params(&self) -> Vec<(&'static str, Cow<'_, str>)> {
62 let mut res = Vec::with_capacity(2);
63 if let Some(language) = self.language.as_ref() {
64 res.push(("language", Cow::Borrowed(language.as_str())));
65 }
66 if let Some(page) = self.page {
67 res.push(("page", Cow::Owned(page.to_string())));
68 }
69 res
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::MovieRecommendations;
76 use crate::client::Client;
77 use crate::client::reqwest::ReqwestExecutor;
78 use crate::prelude::Command;
79 use mockito::Matcher;
80
81 #[tokio::test]
82 async fn it_works() {
83 let mut server = mockito::Server::new_async().await;
84 let client = Client::<ReqwestExecutor>::builder()
85 .with_api_key("secret".into())
86 .with_base_url(server.url())
87 .build()
88 .unwrap();
89
90 let _m = server
91 .mock("GET", "/movie/550/recommendations")
92 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
93 .with_status(200)
94 .with_header("content-type", "application/json")
95 .with_body(include_str!("../../assets/movie-recommendations.json"))
96 .create_async()
97 .await;
98
99 let result = MovieRecommendations::new(550)
100 .execute(&client)
101 .await
102 .unwrap();
103 assert_eq!(result.page, 1);
104 assert!(!result.results.is_empty());
105 }
106
107 #[tokio::test]
108 async fn invalid_api_key() {
109 let mut server = mockito::Server::new_async().await;
110 let client = Client::<ReqwestExecutor>::builder()
111 .with_api_key("secret".into())
112 .with_base_url(server.url())
113 .build()
114 .unwrap();
115
116 let _m = server
117 .mock("GET", "/movie/550/recommendations")
118 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
119 .with_status(401)
120 .with_header("content-type", "application/json")
121 .with_body(include_str!("../../assets/invalid-api-key.json"))
122 .create_async()
123 .await;
124
125 let err = MovieRecommendations::new(550)
126 .execute(&client)
127 .await
128 .unwrap_err();
129 let server_err = err.as_server_error().unwrap();
130 assert_eq!(server_err.status_code, 7);
131 }
132
133 #[tokio::test]
134 async fn resource_not_found() {
135 let mut server = mockito::Server::new_async().await;
136 let client = Client::<ReqwestExecutor>::builder()
137 .with_api_key("secret".into())
138 .with_base_url(server.url())
139 .build()
140 .unwrap();
141
142 let _m = server
143 .mock("GET", "/movie/550/recommendations")
144 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
145 .with_status(404)
146 .with_header("content-type", "application/json")
147 .with_body(include_str!("../../assets/resource-not-found.json"))
148 .create_async()
149 .await;
150
151 let err = MovieRecommendations::new(550)
152 .execute(&client)
153 .await
154 .unwrap_err();
155 let server_err = err.as_server_error().unwrap();
156 assert_eq!(server_err.status_code, 34);
157 }
158}
159
160#[cfg(all(test, feature = "integration"))]
161mod integration_tests {
162 use super::MovieRecommendations;
163 use crate::client::Client;
164 use crate::client::reqwest::ReqwestExecutor;
165 use crate::prelude::Command;
166
167 #[tokio::test]
168 async fn execute() {
169 let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
170 let client = Client::<ReqwestExecutor>::new(secret);
171
172 let result = MovieRecommendations::new(550)
173 .execute(&client)
174 .await
175 .unwrap();
176 assert_eq!(result.page, 1);
177 }
178}