gr/github/
gist.rs

1use crate::{
2    api_traits::{ApiOperation, CodeGist, NumberDeltaErr},
3    cmds::gist::{Gist, GistListBodyArgs},
4    io::{HttpResponse, HttpRunner},
5    remote::{query, URLQueryParamBuilder},
6    Result,
7};
8
9use super::Github;
10
11// https://docs.github.com/en/rest/gists/gists?apiVersion=2022-11-28
12
13impl<R: HttpRunner<Response = HttpResponse>> CodeGist for Github<R> {
14    fn list(&self, args: GistListBodyArgs) -> crate::Result<Vec<Gist>> {
15        let url = self.auth_user_gist_url(false);
16        query::paged(
17            &self.runner,
18            &url,
19            args.body_args,
20            self.request_headers(),
21            None,
22            ApiOperation::Gist,
23            |value| GithubGistFields::from(value).into(),
24        )
25    }
26
27    fn num_pages(&self) -> Result<Option<u32>> {
28        let url = self.auth_user_gist_url(true);
29        query::num_pages(
30            &self.runner,
31            &url,
32            self.request_headers(),
33            ApiOperation::Gist,
34        )
35    }
36
37    fn num_resources(&self) -> Result<Option<NumberDeltaErr>> {
38        let url = self.auth_user_gist_url(true);
39        query::num_resources(
40            &self.runner,
41            &url,
42            self.request_headers(),
43            ApiOperation::Gist,
44        )
45    }
46}
47
48impl<R> Github<R> {
49    fn auth_user_gist_url(&self, first_page: bool) -> String {
50        let url = format!("{}/gists", self.rest_api_basepath);
51        let mut url_query_param = URLQueryParamBuilder::new(&url);
52        if first_page {
53            url_query_param.add_param("page", "1");
54        }
55        url_query_param.build()
56    }
57}
58
59pub struct GithubGistFields {
60    pub gist: Gist,
61}
62
63impl From<&serde_json::Value> for GithubGistFields {
64    fn from(value: &serde_json::Value) -> Self {
65        let gist = Gist::builder()
66            .url(value["html_url"].as_str().unwrap().to_string())
67            .description(value["description"].as_str().unwrap().to_string())
68            .files(
69                value["files"]
70                    .as_object()
71                    .unwrap_or(&serde_json::Map::new())
72                    .keys()
73                    .map(|k| k.to_string())
74                    .collect::<Vec<String>>()
75                    .join(","),
76            )
77            .created_at(value["created_at"].as_str().unwrap_or("").to_string())
78            .build()
79            .unwrap();
80        Self { gist }
81    }
82}
83
84impl From<GithubGistFields> for Gist {
85    fn from(fields: GithubGistFields) -> Self {
86        fields.gist
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use crate::{
93        setup_client,
94        test::utils::{default_github, ContractType, ResponseContracts},
95    };
96
97    use super::*;
98
99    #[test]
100    fn test_github_list_user_gists() {
101        let contracts = ResponseContracts::new(ContractType::Github).add_contract(
102            200,
103            "list_user_gist.json",
104            None,
105        );
106        let args = GistListBodyArgs::builder().body_args(None).build().unwrap();
107        let (client, github) = setup_client!(contracts, default_github(), dyn CodeGist);
108        let gists = github.list(args).unwrap();
109        assert_eq!("https://api.github.com/gists", *client.url());
110        assert_eq!(1, gists.len());
111        assert_eq!(Some(ApiOperation::Gist), *client.api_operation.borrow());
112    }
113
114    #[test]
115    fn test_github_num_pages() {
116        let contracts = ResponseContracts::new(ContractType::Github).add_contract(
117            200,
118            "list_user_gist.json",
119            None,
120        );
121        let (client, github) = setup_client!(contracts, default_github(), dyn CodeGist);
122        let num_pages = github.num_pages().unwrap();
123        assert_eq!("https://api.github.com/gists?page=1", *client.url());
124        assert_eq!(1, num_pages.unwrap());
125        assert_eq!(Some(ApiOperation::Gist), *client.api_operation.borrow());
126    }
127
128    #[test]
129    fn test_github_num_resources() {
130        let contracts = ResponseContracts::new(ContractType::Github).add_contract(
131            200,
132            "list_user_gist.json",
133            None,
134        );
135        let (client, github) = setup_client!(contracts, default_github(), dyn CodeGist);
136        github.num_resources().unwrap();
137        assert_eq!("https://api.github.com/gists?page=1", *client.url());
138        assert_eq!(Some(ApiOperation::Gist), *client.api_operation.borrow());
139    }
140}