gitlab/api/groups/subgroups/
subgroups.rs1use std::collections::BTreeSet;
8
9use derive_builder::Builder;
10
11use crate::api::common::{AccessLevel, NameOrId, SortOrder};
12use crate::api::endpoint_prelude::*;
13use crate::api::ParamValue;
14
15#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
17#[non_exhaustive]
18pub enum GroupSubgroupsOrderBy {
19 Id,
21 #[default]
23 Name,
24 Path,
26}
27
28impl GroupSubgroupsOrderBy {
29 fn as_str(self) -> &'static str {
31 match self {
32 GroupSubgroupsOrderBy::Id => "id",
33 GroupSubgroupsOrderBy::Name => "name",
34 GroupSubgroupsOrderBy::Path => "path",
35 }
36 }
37}
38
39impl ParamValue<'static> for GroupSubgroupsOrderBy {
40 fn as_value(&self) -> Cow<'static, str> {
41 self.as_str().into()
42 }
43}
44
45#[derive(Debug, Clone, Builder)]
47#[builder(setter(strip_option))]
48pub struct GroupSubgroups<'a> {
49 #[builder(setter(into))]
51 group: NameOrId<'a>,
52
53 #[builder(setter(name = "_skip_groups"), default, private)]
55 skip_groups: BTreeSet<u64>,
56
57 #[builder(default)]
61 all_available: Option<bool>,
62
63 #[builder(setter(into), default)]
67 search: Option<Cow<'a, str>>,
68 #[builder(default)]
70 order_by: Option<GroupSubgroupsOrderBy>,
71 #[builder(default)]
73 sort: Option<SortOrder>,
74
75 #[builder(default)]
77 statistics: Option<bool>,
78 #[builder(default)]
80 with_custom_attributes: Option<bool>,
81 #[builder(default)]
83 owned: Option<bool>,
84 #[builder(default)]
86 min_access_level: Option<AccessLevel>,
87}
88
89impl<'a> GroupSubgroups<'a> {
90 pub fn builder() -> GroupSubgroupsBuilder<'a> {
92 GroupSubgroupsBuilder::default()
93 }
94}
95
96impl GroupSubgroupsBuilder<'_> {
97 pub fn skip_group(&mut self, group_id: u64) -> &mut Self {
99 self.skip_groups
100 .get_or_insert_with(BTreeSet::new)
101 .insert(group_id);
102 self
103 }
104
105 pub fn skip_groups<I>(&mut self, iter: I) -> &mut Self
107 where
108 I: Iterator<Item = u64>,
109 {
110 self.skip_groups
111 .get_or_insert_with(BTreeSet::new)
112 .extend(iter);
113 self
114 }
115}
116
117impl Endpoint for GroupSubgroups<'_> {
118 fn method(&self) -> Method {
119 Method::GET
120 }
121
122 fn endpoint(&self) -> Cow<'static, str> {
123 format!("groups/{}/subgroups", self.group).into()
124 }
125
126 fn parameters(&self) -> QueryParams<'_> {
127 let mut params = QueryParams::default();
128
129 params
130 .push_opt("all_available", self.all_available)
131 .push_opt("search", self.search.as_ref())
132 .push_opt("order_by", self.order_by)
133 .push_opt("sort", self.sort)
134 .push_opt("statistics", self.statistics)
135 .push_opt("with_custom_attributes", self.with_custom_attributes)
136 .push_opt("owned", self.owned)
137 .push_opt(
138 "min_access_level",
139 self.min_access_level.map(AccessLevel::as_u64),
140 )
141 .extend(
142 self.skip_groups
143 .iter()
144 .map(|&value| ("skip_groups[]", value)),
145 );
146
147 params
148 }
149}
150
151impl Pageable for GroupSubgroups<'_> {}
152
153#[cfg(test)]
154mod tests {
155 use crate::api::common::{AccessLevel, SortOrder};
156 use crate::api::groups::subgroups::{
157 GroupSubgroups, GroupSubgroupsBuilderError, GroupSubgroupsOrderBy,
158 };
159 use crate::api::{self, Query};
160 use crate::test::client::{ExpectedUrl, SingleTestClient};
161
162 #[test]
163 fn order_by_default() {
164 assert_eq!(
165 GroupSubgroupsOrderBy::default(),
166 GroupSubgroupsOrderBy::Name,
167 );
168 }
169
170 #[test]
171 fn order_by_as_str() {
172 let items = &[
173 (GroupSubgroupsOrderBy::Id, "id"),
174 (GroupSubgroupsOrderBy::Name, "name"),
175 (GroupSubgroupsOrderBy::Path, "path"),
176 ];
177
178 for (i, s) in items {
179 assert_eq!(i.as_str(), *s);
180 }
181 }
182
183 #[test]
184 fn group_is_needed() {
185 let err = GroupSubgroups::builder().build().unwrap_err();
186 crate::test::assert_missing_field!(err, GroupSubgroupsBuilderError, "group");
187 }
188
189 #[test]
190 fn group_is_sufficient() {
191 GroupSubgroups::builder().group(1).build().unwrap();
192 }
193
194 #[test]
195 fn endpoint() {
196 let endpoint = ExpectedUrl::builder()
197 .endpoint("groups/group%2Fsubgroup/subgroups")
198 .build()
199 .unwrap();
200 let client = SingleTestClient::new_raw(endpoint, "");
201
202 let endpoint = GroupSubgroups::builder()
203 .group("group/subgroup")
204 .build()
205 .unwrap();
206 api::ignore(endpoint).query(&client).unwrap();
207 }
208
209 #[test]
210 fn endpoint_skip_group() {
211 let endpoint = ExpectedUrl::builder()
212 .endpoint("groups/group%2Fsubgroup/subgroups")
213 .add_query_params(&[("skip_groups[]", "1")])
214 .build()
215 .unwrap();
216 let client = SingleTestClient::new_raw(endpoint, "");
217
218 let endpoint = GroupSubgroups::builder()
219 .group("group/subgroup")
220 .skip_group(1)
221 .build()
222 .unwrap();
223 api::ignore(endpoint).query(&client).unwrap();
224 }
225
226 #[test]
227 fn endpoint_skip_groups() {
228 let endpoint = ExpectedUrl::builder()
229 .endpoint("groups/group%2Fsubgroup/subgroups")
230 .add_query_params(&[("skip_groups[]", "42"), ("skip_groups[]", "1337")])
231 .build()
232 .unwrap();
233 let client = SingleTestClient::new_raw(endpoint, "");
234
235 let endpoint = GroupSubgroups::builder()
236 .group("group/subgroup")
237 .skip_group(42)
238 .skip_groups([42, 1337].iter().copied())
239 .build()
240 .unwrap();
241 api::ignore(endpoint).query(&client).unwrap();
242 }
243
244 #[test]
245 fn endpoint_all_available() {
246 let endpoint = ExpectedUrl::builder()
247 .endpoint("groups/group%2Fsubgroup/subgroups")
248 .add_query_params(&[("all_available", "true")])
249 .build()
250 .unwrap();
251 let client = SingleTestClient::new_raw(endpoint, "");
252
253 let endpoint = GroupSubgroups::builder()
254 .group("group/subgroup")
255 .all_available(true)
256 .build()
257 .unwrap();
258 api::ignore(endpoint).query(&client).unwrap();
259 }
260
261 #[test]
262 fn endpoint_search() {
263 let endpoint = ExpectedUrl::builder()
264 .endpoint("groups/group%2Fsubgroup/subgroups")
265 .add_query_params(&[("search", "name")])
266 .build()
267 .unwrap();
268 let client = SingleTestClient::new_raw(endpoint, "");
269
270 let endpoint = GroupSubgroups::builder()
271 .group("group/subgroup")
272 .search("name")
273 .build()
274 .unwrap();
275 api::ignore(endpoint).query(&client).unwrap();
276 }
277
278 #[test]
279 fn endpoint_order_by() {
280 let endpoint = ExpectedUrl::builder()
281 .endpoint("groups/group%2Fsubgroup/subgroups")
282 .add_query_params(&[("order_by", "id")])
283 .build()
284 .unwrap();
285 let client = SingleTestClient::new_raw(endpoint, "");
286
287 let endpoint = GroupSubgroups::builder()
288 .group("group/subgroup")
289 .order_by(GroupSubgroupsOrderBy::Id)
290 .build()
291 .unwrap();
292 api::ignore(endpoint).query(&client).unwrap();
293 }
294
295 #[test]
296 fn endpoint_sort() {
297 let endpoint = ExpectedUrl::builder()
298 .endpoint("groups/group%2Fsubgroup/subgroups")
299 .add_query_params(&[("sort", "asc")])
300 .build()
301 .unwrap();
302 let client = SingleTestClient::new_raw(endpoint, "");
303
304 let endpoint = GroupSubgroups::builder()
305 .group("group/subgroup")
306 .sort(SortOrder::Ascending)
307 .build()
308 .unwrap();
309 api::ignore(endpoint).query(&client).unwrap();
310 }
311
312 #[test]
313 fn endpoint_statistics() {
314 let endpoint = ExpectedUrl::builder()
315 .endpoint("groups/group%2Fsubgroup/subgroups")
316 .add_query_params(&[("statistics", "true")])
317 .build()
318 .unwrap();
319 let client = SingleTestClient::new_raw(endpoint, "");
320
321 let endpoint = GroupSubgroups::builder()
322 .group("group/subgroup")
323 .statistics(true)
324 .build()
325 .unwrap();
326 api::ignore(endpoint).query(&client).unwrap();
327 }
328
329 #[test]
330 fn endpoint_with_custom_attributes() {
331 let endpoint = ExpectedUrl::builder()
332 .endpoint("groups/group%2Fsubgroup/subgroups")
333 .add_query_params(&[("with_custom_attributes", "true")])
334 .build()
335 .unwrap();
336 let client = SingleTestClient::new_raw(endpoint, "");
337
338 let endpoint = GroupSubgroups::builder()
339 .group("group/subgroup")
340 .with_custom_attributes(true)
341 .build()
342 .unwrap();
343 api::ignore(endpoint).query(&client).unwrap();
344 }
345
346 #[test]
347 fn endpoint_owned() {
348 let endpoint = ExpectedUrl::builder()
349 .endpoint("groups/group%2Fsubgroup/subgroups")
350 .add_query_params(&[("owned", "true")])
351 .build()
352 .unwrap();
353 let client = SingleTestClient::new_raw(endpoint, "");
354
355 let endpoint = GroupSubgroups::builder()
356 .group("group/subgroup")
357 .owned(true)
358 .build()
359 .unwrap();
360 api::ignore(endpoint).query(&client).unwrap();
361 }
362
363 #[test]
364 fn endpoint_min_access_level() {
365 let endpoint = ExpectedUrl::builder()
366 .endpoint("groups/group%2Fsubgroup/subgroups")
367 .add_query_params(&[("min_access_level", "30")])
368 .build()
369 .unwrap();
370 let client = SingleTestClient::new_raw(endpoint, "");
371
372 let endpoint = GroupSubgroups::builder()
373 .group("group/subgroup")
374 .min_access_level(AccessLevel::Developer)
375 .build()
376 .unwrap();
377 api::ignore(endpoint).query(&client).unwrap();
378 }
379}