tmdb_api/movie/
upcoming.rs1use std::borrow::Cow;
2
3use crate::common::PaginatedResult;
4
5#[derive(Clone, Debug, Default, serde::Serialize)]
6pub struct Params<'a> {
7 #[serde(skip_serializing_if = "Option::is_none")]
9 pub language: Option<Cow<'a, str>>,
10 #[serde(skip_serializing_if = "Option::is_none")]
12 pub page: Option<u32>,
13 #[serde(skip_serializing_if = "Option::is_none")]
15 pub region: Option<Cow<'a, str>>,
16}
17
18impl<'a> Params<'a> {
19 pub fn set_page(&mut self, value: u32) {
20 self.page = Some(value);
21 }
22
23 pub fn with_page(mut self, value: u32) -> Self {
24 self.set_page(value);
25 self
26 }
27
28 pub fn set_language(&mut self, value: impl Into<Cow<'a, str>>) {
29 self.language = Some(value.into());
30 }
31
32 pub fn with_language(mut self, value: impl Into<Cow<'a, str>>) -> Self {
33 self.set_language(value);
34 self
35 }
36
37 pub fn set_region(&mut self, value: impl Into<Cow<'a, str>>) {
38 self.region = Some(value.into());
39 }
40
41 pub fn with_region(mut self, value: impl Into<Cow<'a, str>>) -> Self {
42 self.set_region(value);
43 self
44 }
45}
46
47impl<E: crate::client::Executor> crate::Client<E> {
48 pub async fn list_movies_upcoming(
68 &self,
69 params: &Params<'_>,
70 ) -> crate::Result<PaginatedResult<super::MovieShort>> {
71 self.execute("/movie/upcoming", params).await
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use crate::client::Client;
78 use crate::client::reqwest::Client as ReqwestClient;
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::<ReqwestClient>::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/upcoming")
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-upcoming.json"))
96 .create_async()
97 .await;
98
99 let result = client
100 .list_movies_upcoming(&Default::default())
101 .await
102 .unwrap();
103 assert_eq!(result.page, 1);
104 }
105
106 #[tokio::test]
107 async fn invalid_api_key() {
108 let mut server = mockito::Server::new_async().await;
109 let client = Client::<ReqwestClient>::builder()
110 .with_api_key("secret".into())
111 .with_base_url(server.url())
112 .build()
113 .unwrap();
114
115 let _m = server
116 .mock("GET", "/movie/upcoming")
117 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
118 .with_status(401)
119 .with_header("content-type", "application/json")
120 .with_body(include_str!("../../assets/invalid-api-key.json"))
121 .create_async()
122 .await;
123
124 let err = client
125 .list_movies_upcoming(&Default::default())
126 .await
127 .unwrap_err();
128 let server_err = err.as_server_error().unwrap();
129 assert_eq!(server_err.status_code, 7);
130 }
131
132 #[tokio::test]
133 async fn resource_not_found() {
134 let mut server = mockito::Server::new_async().await;
135 let client = Client::<ReqwestClient>::builder()
136 .with_api_key("secret".into())
137 .with_base_url(server.url())
138 .build()
139 .unwrap();
140
141 let _m = server
142 .mock("GET", "/movie/upcoming")
143 .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
144 .with_status(404)
145 .with_header("content-type", "application/json")
146 .with_body(include_str!("../../assets/resource-not-found.json"))
147 .create_async()
148 .await;
149
150 let err = client
151 .list_movies_upcoming(&Default::default())
152 .await
153 .unwrap_err();
154 let server_err = err.as_server_error().unwrap();
155 assert_eq!(server_err.status_code, 34);
156 }
157}
158
159#[cfg(all(test, feature = "integration"))]
160mod integration_tests {
161 use crate::client::Client;
162 use crate::client::reqwest::Client as ReqwestClient;
163
164 #[tokio::test]
165 async fn execute() {
166 let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
167 let client = Client::<ReqwestClient>::new(secret);
168
169 let _result = client
170 .list_movies_upcoming(&Default::default())
171 .await
172 .unwrap();
173 }
174}