tmdb_api/watch_provider/
list.rs1use std::borrow::Cow;
2use std::collections::HashMap;
3
4use super::WatchProvider;
5use crate::client::Executor;
6use crate::common::Results;
7
8#[derive(Debug, Default, serde::Serialize)]
9pub struct Params<'a> {
10 #[serde(skip_serializing_if = "Option::is_none")]
12 pub watch_region: Option<Cow<'a, str>>,
13 #[serde(skip_serializing_if = "Option::is_none")]
16 pub language: Option<Cow<'a, str>>,
17}
18
19impl<'a> Params<'a> {
20 pub fn set_watch_region(&mut self, value: impl Into<Cow<'a, str>>) {
21 self.watch_region = Some(value.into());
22 }
23
24 pub fn with_watch_region(mut self, value: impl Into<Cow<'a, str>>) -> Self {
25 self.set_watch_region(value);
26 self
27 }
28
29 pub fn set_language(&mut self, value: impl Into<Cow<'a, str>>) {
30 self.language = Some(value.into());
31 }
32
33 pub fn with_language(mut self, value: impl Into<Cow<'a, str>>) -> Self {
34 self.set_language(value);
35 self
36 }
37}
38
39#[derive(Clone, Debug, Deserialize, Serialize)]
40pub struct WatchProviderDetail {
41 pub display_priorities: HashMap<String, u64>,
43 #[serde(flatten)]
44 pub inner: WatchProvider,
45}
46
47impl<E: Executor> crate::Client<E> {
48 pub async fn list_movie_watch_providers(
64 &self,
65 params: &Params<'_>,
66 ) -> crate::Result<Results<Vec<WatchProviderDetail>>> {
67 self.execute("/watch/providers/movie", params).await
68 }
69
70 pub async fn list_tvshow_watch_providers(
86 &self,
87 params: &Params<'_>,
88 ) -> crate::Result<Results<Vec<WatchProviderDetail>>> {
89 self.execute("/watch/providers/tv", params).await
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use mockito::Matcher;
96
97 use crate::client::Client;
98 use crate::client::reqwest::Client as ReqwestClient;
99
100 #[tokio::test]
101 async fn movie_works() {
102 let mut server = mockito::Server::new_async().await;
103 let _m = server
104 .mock("GET", "/watch/providers/movie")
105 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
106 .with_status(200)
107 .with_header("content-type", "application/json")
108 .with_body(include_str!("../../assets/watch-provider-movie-list.json"))
109 .create_async()
110 .await;
111 let client = Client::<ReqwestClient>::builder()
112 .with_api_key("secret".into())
113 .with_base_url(server.url())
114 .build()
115 .unwrap();
116 let result = client
117 .list_movie_watch_providers(&Default::default())
118 .await
119 .unwrap();
120 assert!(!result.results.is_empty());
121 }
122
123 #[tokio::test]
124 async fn tv_works() {
125 let mut server = mockito::Server::new_async().await;
126 let _m = server
127 .mock("GET", "/watch/providers/tv")
128 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
129 .with_status(200)
130 .with_header("content-type", "application/json")
131 .with_body(include_str!("../../assets/watch-provider-tv-list.json"))
132 .create_async()
133 .await;
134
135 let client = Client::<ReqwestClient>::builder()
136 .with_api_key("secret".into())
137 .with_base_url(server.url())
138 .build()
139 .unwrap();
140 let result = client
141 .list_tvshow_watch_providers(&Default::default())
142 .await
143 .unwrap();
144 assert!(!result.results.is_empty());
145 }
146
147 #[tokio::test]
148 async fn invalid_api_key() {
149 let mut server = mockito::Server::new_async().await;
150 let _m = server
151 .mock("GET", "/watch/providers/tv")
152 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
153 .with_status(401)
154 .with_header("content-type", "application/json")
155 .with_body(include_str!("../../assets/invalid-api-key.json"))
156 .create_async()
157 .await;
158
159 let client = Client::<ReqwestClient>::builder()
160 .with_api_key("secret".into())
161 .with_base_url(server.url())
162 .build()
163 .unwrap();
164 let err = client
165 .list_tvshow_watch_providers(&Default::default())
166 .await
167 .unwrap_err();
168 let server_err = err.as_server_error().unwrap();
169 assert_eq!(server_err.status_code, 7);
170 }
171
172 #[tokio::test]
173 async fn resource_not_found() {
174 let mut server = mockito::Server::new_async().await;
175 let _m = server
176 .mock("GET", "/watch/providers/tv")
177 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
178 .with_status(404)
179 .with_header("content-type", "application/json")
180 .with_body(include_str!("../../assets/resource-not-found.json"))
181 .create_async()
182 .await;
183 let client = Client::<ReqwestClient>::builder()
184 .with_api_key("secret".into())
185 .with_base_url(server.url())
186 .build()
187 .unwrap();
188 let err = client
189 .list_tvshow_watch_providers(&Default::default())
190 .await
191 .unwrap_err();
192 let server_err = err.as_server_error().unwrap();
193 assert_eq!(server_err.status_code, 34);
194 }
195}
196
197#[cfg(all(test, feature = "integration"))]
198mod integration_tests {
199 use super::Params;
200 use crate::client::Client;
201 use crate::client::reqwest::Client as ReqwestClient;
202
203 #[tokio::test]
204 async fn execute_tv() {
205 let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
206 let client = Client::<ReqwestClient>::new(secret);
207 let params = Params::default().with_language("en-US");
208 let result = client.list_tvshow_watch_providers(¶ms).await.unwrap();
209 assert!(!result.results.is_empty());
210 }
211
212 #[tokio::test]
213 async fn execute_movie() {
214 let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
215 let client = Client::<ReqwestClient>::new(secret);
216 let params = Params::default().with_language("en-US");
217 let result = client.list_movie_watch_providers(¶ms).await.unwrap();
218 assert!(!result.results.is_empty());
219 }
220}