use_github_api/users/
mod.rs1#[cfg(not(test))]
2use crate::url;
3use crate::{check_for_errors, schema::users::contextual_info, GithubClient};
4use serde_json::from_str;
5use std::error::Error;
6
7#[non_exhaustive]
8pub struct Users<'a> {
9 #[cfg_attr(test, allow(dead_code))]
10 client: &'a GithubClient<'a>,
11}
12
13use crate::schema::{
14 users::{list, single},
15 GitHubError,
16};
17impl<'a> Users<'a> {
18 pub(crate) fn new(client: &'a GithubClient<'a>) -> Self {
19 Users { client }
20 }
21
22 pub async fn list(&self, cfg: Option<list::Params>) -> Result<Vec<list::User>, Box<dyn Error>> {
24 #[cfg(test)]
25 let text = crate::mock_response!(&self, "users", "list", cfg);
26 #[cfg(not(test))]
27 let text = {
28 let result = self
29 .client
30 .reqwest_client
31 .get(url!(self, "/users"))
32 .query(&cfg)
33 .send()
34 .await?;
35 result.text().await?
36 };
37 let json_result = from_str::<Vec<list::User>>(&text);
38 match json_result {
39 Ok(data) => Ok(data),
40 Err(err) => {
41 if err.is_data() {
42 let error_data = from_str::<GitHubError>(&text)?;
43 check_for_errors!(error_data, err);
44 } else {
45 Err(err.into())
46 }
47 }
48 }
49 }
50
51 pub async fn user(&self, username: &str) -> Result<single::User, Box<dyn Error>> {
57 #[cfg(test)]
58 let text = crate::mock_response!(&self, "users", "user", username);
59 #[cfg(not(test))]
60 let text = {
61 let result = self
62 .client
63 .reqwest_client
64 .get(url!(self, "/users/{}", username))
65 .send()
66 .await?;
67 result.text().await?
68 };
69
70 match from_str::<single::User>(&text) {
71 Ok(data) => Ok(data),
72 Err(err) => {
73 if err.is_data() {
74 let error_data = from_str::<GitHubError>(&text)?;
75 check_for_errors!(error_data, err);
76 } else {
77 Err(err.into())
78 }
79 }
80 }
81 }
82
83 #[cfg(any(feature = "auth", doc))]
84 #[cfg_attr(docsrs, doc(cfg(feature = "auth")))]
85 pub async fn contextual_info(
90 &self,
91 username: &str,
92 cfg: Option<contextual_info::Params>,
93 ) -> Result<contextual_info::User, Box<dyn Error>> {
94 #[cfg(test)]
95 let text = crate::mock_response!(&self, "users", "contextual_info", (username, cfg));
96 #[cfg(not(test))]
97 let text = {
98 let result = self
99 .client
100 .reqwest_client
101 .get(url!(self, "/users/{}/hovercard", username))
102 .query(&cfg)
103 .send()
104 .await?;
105 result.text().await?
106 };
107
108 match from_str::<contextual_info::User>(&text) {
109 Ok(data) => Ok(data),
110 Err(err) => {
111 if err.is_data() {
112 let error_data = from_str::<GitHubError>(&text)?;
113 check_for_errors!(error_data, err);
114 } else {
115 Err(err.into())
116 }
117 }
118 }
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 #[cfg(feature = "auth")]
125 use crate::constants::FAKE_TOKEN;
126
127 use super::*;
128
129 #[tokio::test]
130 async fn list_works() {
131 let client = GithubClient::new(
132 #[cfg(feature = "enterprise")]
133 "https://something.com/api/v3",
134 #[cfg(feature = "auth")]
135 FAKE_TOKEN,
136 )
137 .unwrap();
138
139 let users = Users::new(&client);
140 let data = users.list(None).await.unwrap();
141 assert_eq!(data[0].login, "mojombo");
142 assert_eq!(data[0].id, 1);
143 }
144
145 #[tokio::test]
146 async fn single_works() {
147 let client = GithubClient::new(
148 #[cfg(feature = "enterprise")]
149 "https://something.com/api/v3",
150 #[cfg(feature = "auth")]
151 FAKE_TOKEN,
152 )
153 .unwrap();
154 let users = Users::new(&client);
155 let data = users.user("mojombo").await.unwrap();
156 assert_eq!(data.login, "mojombo");
157 }
158
159 #[tokio::test]
160 #[cfg(feature = "auth")]
161 async fn context_info_works() {
162 #[cfg(feature = "auth")]
163 let client = GithubClient::new(
164 #[cfg(feature = "enterprise")]
165 "https://something.com/api/v3",
166 FAKE_TOKEN,
167 )
168 .unwrap();
169 let users = Users::new(&client);
170 let data = users.contextual_info("mojombo", None).await.unwrap();
171 assert_eq!(data.contexts[0].message, "Member of @toml-lang");
172 }
173}