redmine_api/api/
queries.rs1use derive_builder::Builder;
18use reqwest::Method;
19use std::borrow::Cow;
20
21use crate::api::{Endpoint, Pageable, ReturnsJsonResponse};
22use serde_repr::{Deserialize_repr, Serialize_repr};
23
24#[derive(
26 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize_repr, Deserialize_repr,
27)]
28#[repr(u8)]
29pub enum Visibility {
30 Private = 0,
32 Roles = 1,
34 Public = 2,
36}
37
38#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
42pub struct QueryListItem {
43 pub id: u64,
45 pub name: String,
47 pub is_public: bool,
49 pub project_id: Option<u64>,
51}
52
53#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
57pub struct Query {
58 pub id: u64,
60 pub name: String,
62 pub is_public: bool,
64 pub project_id: Option<u64>,
66 pub user_id: u64,
68 #[serde(default)]
70 pub description: Option<String>,
71 pub filters: serde_json::Value,
73 pub column_names: Vec<String>,
75 pub sort_criteria: serde_json::Value,
77 pub options: serde_json::Value,
79 #[serde(rename = "type")]
81 pub query_type: String,
82}
83
84#[derive(Debug, Clone, Builder)]
88#[builder(setter(strip_option))]
89#[expect(
90 clippy::empty_structs_with_brackets,
91 reason = "derive_builder requires named-field syntax"
92)]
93pub struct ListQueries {}
94
95impl ReturnsJsonResponse for ListQueries {}
96impl Pageable for ListQueries {
97 fn response_wrapper_key(&self) -> String {
98 "queries".to_string()
99 }
100}
101
102impl ListQueries {
103 #[must_use]
105 pub fn builder() -> ListQueriesBuilder {
106 ListQueriesBuilder::default()
107 }
108}
109
110impl Endpoint for ListQueries {
111 fn method(&self) -> Method {
112 Method::GET
113 }
114
115 fn endpoint(&self) -> Cow<'static, str> {
116 "queries.json".into()
117 }
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
122pub struct QueriesWrapper<T> {
123 pub queries: Vec<T>,
125}
126
127#[cfg(test)]
128mod test {
129 use super::*;
130 use pretty_assertions::assert_eq;
131 use std::error::Error;
132 use tracing_test::traced_test;
133
134 #[traced_test]
135 #[test]
136 fn test_list_queries_first_page() -> Result<(), Box<dyn Error>> {
137 dotenvy::dotenv()?;
138 let redmine = crate::api::Redmine::from_env(
139 reqwest::blocking::Client::builder()
140 .tls_backend_rustls()
141 .build()?,
142 )?;
143 let endpoint = ListQueries::builder().build()?;
144 redmine.json_response_body_page::<_, QueryListItem>(&endpoint, 0, 25)?;
145 Ok(())
146 }
147
148 #[traced_test]
149 #[test]
150 fn test_list_queries_all_pages() -> Result<(), Box<dyn Error>> {
151 dotenvy::dotenv()?;
152 let redmine = crate::api::Redmine::from_env(
153 reqwest::blocking::Client::builder()
154 .tls_backend_rustls()
155 .build()?,
156 )?;
157 let endpoint = ListQueries::builder().build()?;
158 redmine.json_response_body_all_pages::<_, QueryListItem>(&endpoint)?;
159 Ok(())
160 }
161
162 #[traced_test]
167 #[test]
168 fn test_completeness_query_type() -> Result<(), Box<dyn Error>> {
169 dotenvy::dotenv()?;
170 let redmine = crate::api::Redmine::from_env(
171 reqwest::blocking::Client::builder()
172 .tls_backend_rustls()
173 .build()?,
174 )?;
175 let endpoint = ListQueries::builder().build()?;
176 let values: Vec<serde_json::Value> = redmine.json_response_body_all_pages(&endpoint)?;
177 for value in values {
178 let o: QueryListItem = serde_json::from_value(value.clone())?;
179 let reserialized = serde_json::to_value(o)?;
180 assert_eq!(value, reserialized);
181 }
182 Ok(())
183 }
184}