wordstat_rs/
report_list.rs1use serde_json::Value;
2use crate::{WordstatError, check_status};
3use mockall_double::double;
4#[double] use crate::client::Client;
6
7
8#[derive(Debug, PartialEq)]
10pub enum StatusCode {
11 Done,
12 Pending,
13 Failed,
14 Unknown
15}
16
17#[derive(Debug)]
19#[cfg_attr(test, derive(PartialEq))]
20pub struct ReportStatus {
21 pub report_id: i64,
23 pub status: StatusCode
25}
26
27pub async fn get_report_list(client: &Client) -> Result<Vec<ReportStatus>, WordstatError> {
29 let method = "GetWordstatReportList";
30 let result = client.post(method, None).await?;
31
32 check_status(&result)?;
33
34 let Some(data) = result.get("data") else { return Err(WordstatError::BadResponse{ reason: "No data field in response" }) };
35 let Value::Array(reports) = data else { return Err(WordstatError::BadResponse{ reason: "Data field is not an array" }) };
36
37 parse_reports(&reports)
38}
39
40fn parse_reports(data: &Vec<Value>) -> Result<Vec<ReportStatus>, WordstatError> {
41 let mut reports: Vec<ReportStatus> = vec![];
42
43 for report in data {
44 reports.push(parse_report(report)?);
45 }
46
47 Ok(reports)
48}
49
50fn parse_report(report: &Value) -> Result<ReportStatus, WordstatError> {
51 let Some(id_val) = report.get("ReportID") else { return Err(WordstatError::BadResponse{ reason: "No ReportID field" }) };
52 let Some(report_id) = id_val.as_i64() else { return Err(WordstatError::BadResponse{ reason: "ReportID field is not an integer" }) };
53
54 let Some(status_val) = report.get("StatusReport") else { return Err(WordstatError::BadResponse{ reason: "No StatusReport field" }) };
55 let Value::String(status_str) = status_val else { return Err(WordstatError::BadResponse{ reason: "StatusReport field is not a string" }) };
56 let status = match status_str.as_str() {
57 "Done" => { StatusCode::Done }
58 "Pending" => { StatusCode::Pending }
59 "Failed" => { StatusCode::Failed }
60 _ => { StatusCode::Unknown }
61 };
62
63 Ok(ReportStatus {
64 report_id,
65 status
66 })
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn parse_report() {
75 let data = r#"
76 {"ReportID":54312,"StatusReport":"Done"}
77 "#;
78 let input: Value = serde_json::from_str(data).unwrap();
79
80
81 let received = super::parse_report(&input).unwrap();
82
83
84 let expected = ReportStatus {
85 report_id: 54312,
86 status: StatusCode::Done
87 };
88 assert_eq!(received, expected)
89 }
90
91 #[test]
92 #[should_panic]
93 fn parse_invalid_report() {
94 let data = r#"
95 {"Report":54312,"StatusReport":"Done"}
96 "#;
97 let input: Value = serde_json::from_str(data).unwrap();
98
99
100 let received = super::parse_report(&input).unwrap();
101
102
103 let expected = ReportStatus {
104 report_id: 54312,
105 status: StatusCode::Done
106 };
107 assert_eq!(received, expected)
108 }
109
110 #[test]
111 fn get_reposts_list() {
112 let data = r#"
113 {"data" :
114 [
115 {"ReportID":54312,"StatusReport":"Done"},
116 {"ReportID":542,"StatusReport":"Pending"},
117 {"ReportID":5423,"StatusReport":"Failed"},
118 {"ReportID":5424,"StatusReport":"what"}
119 ]}
120 "#;
121 let return_value = serde_json::from_str(data).unwrap();
122
123 let mut mock_client = Client::default();
124 mock_client.expect_post()
125 .withf(|method, _params| method == "GetWordstatReportList")
126 .return_once(move |_method, _params| Ok(return_value));
127
128
129 let received = futures::executor::block_on(super::get_report_list(&mock_client)).unwrap();
130
131
132 let expected = vec![
133 ReportStatus {
134 report_id: 54312,
135 status: StatusCode::Done,
136 },
137 ReportStatus {
138 report_id: 542,
139 status: StatusCode::Pending,
140 },
141 ReportStatus {
142 report_id: 5423,
143 status: StatusCode::Failed,
144 },
145 ReportStatus {
146 report_id: 5424,
147 status: StatusCode::Unknown,
148 },
149 ];
150
151 assert_eq!(received, expected)
152 }
153}