gitlab/api/groups/projects/
projects.rs1use derive_builder::Builder;
8
9use crate::api::common::{AccessLevel, NameOrId, SortOrder, VisibilityLevel};
10use crate::api::endpoint_prelude::*;
11use crate::api::ParamValue;
12
13#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
15#[non_exhaustive]
16pub enum GroupProjectsOrderBy {
17 Id,
19 Name,
21 Path,
23 #[default]
25 CreatedAt,
26 UpdatedAt,
28 Similarity,
30 LastActivityAt,
32 StarCount,
34}
35
36impl GroupProjectsOrderBy {
37 fn as_str(self) -> &'static str {
39 match self {
40 GroupProjectsOrderBy::Id => "id",
41 GroupProjectsOrderBy::Name => "name",
42 GroupProjectsOrderBy::Path => "path",
43 GroupProjectsOrderBy::CreatedAt => "created_at",
44 GroupProjectsOrderBy::UpdatedAt => "updated_at",
45 GroupProjectsOrderBy::Similarity => "similarity",
46 GroupProjectsOrderBy::LastActivityAt => "last_activity_at",
47 GroupProjectsOrderBy::StarCount => "star_count",
48 }
49 }
50
51 fn use_keyset_pagination(self) -> bool {
52 matches!(self, Self::Id)
53 }
54}
55
56impl ParamValue<'static> for GroupProjectsOrderBy {
57 fn as_value(&self) -> Cow<'static, str> {
58 self.as_str().into()
59 }
60}
61
62#[derive(Debug, Clone, Builder)]
64#[builder(setter(strip_option))]
65pub struct GroupProjects<'a> {
66 #[builder(setter(into))]
68 group: NameOrId<'a>,
69
70 #[builder(default)]
72 archived: Option<bool>,
73 #[builder(default)]
75 visibility: Option<VisibilityLevel>,
76
77 #[builder(default)]
79 order_by: Option<GroupProjectsOrderBy>,
80 #[builder(default)]
82 sort: Option<SortOrder>,
83 #[builder(setter(into), default)]
87 search: Option<Cow<'a, str>>,
88
89 #[builder(default)]
91 simple: Option<bool>,
92 #[builder(default)]
94 owned: Option<bool>,
95 #[builder(default)]
97 starred: Option<bool>,
98 #[builder(default)]
100 with_issues_enabled: Option<bool>,
101 #[builder(default)]
103 with_merge_requests_enabled: Option<bool>,
104 #[builder(default)]
106 with_shared: Option<bool>,
107 #[builder(default)]
109 include_subgroups: Option<bool>,
110 #[builder(default)]
112 min_access_level: Option<AccessLevel>,
113 #[builder(default)]
115 with_custom_attributes: Option<bool>,
116 #[builder(default)]
118 with_security_reports: Option<bool>,
119}
120
121impl<'a> GroupProjects<'a> {
122 pub fn builder() -> GroupProjectsBuilder<'a> {
124 GroupProjectsBuilder::default()
125 }
126}
127
128impl Endpoint for GroupProjects<'_> {
129 fn method(&self) -> Method {
130 Method::GET
131 }
132
133 fn endpoint(&self) -> Cow<'static, str> {
134 format!("groups/{}/projects", self.group).into()
135 }
136
137 fn parameters(&self) -> QueryParams<'_> {
138 let mut params = QueryParams::default();
139
140 params
141 .push_opt("archived", self.archived)
142 .push_opt("visibility", self.visibility)
143 .push_opt("order_by", self.order_by)
144 .push_opt("sort", self.sort)
145 .push_opt("search", self.search.as_ref())
146 .push_opt("simple", self.simple)
147 .push_opt("owned", self.owned)
148 .push_opt("starred", self.starred)
149 .push_opt("with_issues_enabled", self.with_issues_enabled)
150 .push_opt(
151 "with_merge_requests_enabled",
152 self.with_merge_requests_enabled,
153 )
154 .push_opt("with_shared", self.with_shared)
155 .push_opt("include_subgroups", self.include_subgroups)
156 .push_opt(
157 "min_access_level",
158 self.min_access_level.map(AccessLevel::as_u64),
159 )
160 .push_opt("with_custom_attributes", self.with_custom_attributes)
161 .push_opt("with_security_reports", self.with_security_reports);
162
163 params
164 }
165}
166
167impl Pageable for GroupProjects<'_> {
168 fn use_keyset_pagination(&self) -> bool {
169 self.order_by.unwrap_or_default().use_keyset_pagination()
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use crate::api::common::{AccessLevel, SortOrder, VisibilityLevel};
176 use crate::api::groups::projects::{
177 GroupProjects, GroupProjectsBuilderError, GroupProjectsOrderBy,
178 };
179 use crate::api::{self, Pageable, Query};
180 use crate::test::client::{ExpectedUrl, SingleTestClient};
181
182 #[test]
183 fn order_by_default() {
184 assert_eq!(
185 GroupProjectsOrderBy::default(),
186 GroupProjectsOrderBy::CreatedAt
187 );
188 }
189
190 #[test]
191 fn order_by_as_str() {
192 let items = &[
193 (GroupProjectsOrderBy::Id, "id"),
194 (GroupProjectsOrderBy::Name, "name"),
195 (GroupProjectsOrderBy::Path, "path"),
196 (GroupProjectsOrderBy::CreatedAt, "created_at"),
197 (GroupProjectsOrderBy::UpdatedAt, "updated_at"),
198 (GroupProjectsOrderBy::Similarity, "similarity"),
199 (GroupProjectsOrderBy::LastActivityAt, "last_activity_at"),
200 (GroupProjectsOrderBy::StarCount, "star_count"),
201 ];
202
203 for (i, s) in items {
204 assert_eq!(i.as_str(), *s);
205 }
206 }
207
208 #[test]
209 fn order_by_use_keyset_pagination() {
210 let items = &[
211 (GroupProjectsOrderBy::Id, true),
212 (GroupProjectsOrderBy::Name, false),
213 (GroupProjectsOrderBy::Path, false),
214 (GroupProjectsOrderBy::CreatedAt, false),
215 (GroupProjectsOrderBy::UpdatedAt, false),
216 (GroupProjectsOrderBy::Similarity, false),
217 (GroupProjectsOrderBy::LastActivityAt, false),
218 ];
219
220 for (i, k) in items {
221 assert_eq!(i.use_keyset_pagination(), *k);
222 }
223 }
224
225 #[test]
226 fn group_is_needed() {
227 let err = GroupProjects::builder().build().unwrap_err();
228 crate::test::assert_missing_field!(err, GroupProjectsBuilderError, "group");
229 }
230
231 #[test]
232 fn group_is_sufficient() {
233 GroupProjects::builder().group(1).build().unwrap();
234 }
235
236 #[test]
237 fn endpoint_use_keyset_pagination() {
238 let items = &[
239 (GroupProjectsOrderBy::Id, true),
240 (GroupProjectsOrderBy::Name, false),
241 (GroupProjectsOrderBy::Path, false),
242 (GroupProjectsOrderBy::CreatedAt, false),
243 (GroupProjectsOrderBy::UpdatedAt, false),
244 (GroupProjectsOrderBy::Similarity, false),
245 (GroupProjectsOrderBy::LastActivityAt, false),
246 ];
247
248 for (i, k) in items {
249 let endpoint = GroupProjects::builder()
250 .group("group/subgroup")
251 .order_by(*i)
252 .build()
253 .unwrap();
254 assert_eq!(endpoint.use_keyset_pagination(), *k);
255 }
256 }
257
258 #[test]
259 fn endpoint() {
260 let endpoint = ExpectedUrl::builder()
261 .endpoint("groups/group%2Fsubgroup/projects")
262 .build()
263 .unwrap();
264 let client = SingleTestClient::new_raw(endpoint, "");
265
266 let endpoint = GroupProjects::builder()
267 .group("group/subgroup")
268 .build()
269 .unwrap();
270 api::ignore(endpoint).query(&client).unwrap();
271 }
272
273 #[test]
274 fn endpoint_archived() {
275 let endpoint = ExpectedUrl::builder()
276 .endpoint("groups/group%2Fsubgroup/projects")
277 .add_query_params(&[("archived", "true")])
278 .build()
279 .unwrap();
280 let client = SingleTestClient::new_raw(endpoint, "");
281
282 let endpoint = GroupProjects::builder()
283 .group("group/subgroup")
284 .archived(true)
285 .build()
286 .unwrap();
287 api::ignore(endpoint).query(&client).unwrap();
288 }
289
290 #[test]
291 fn endpoint_visibility() {
292 let endpoint = ExpectedUrl::builder()
293 .endpoint("groups/group%2Fsubgroup/projects")
294 .add_query_params(&[("visibility", "private")])
295 .build()
296 .unwrap();
297 let client = SingleTestClient::new_raw(endpoint, "");
298
299 let endpoint = GroupProjects::builder()
300 .group("group/subgroup")
301 .visibility(VisibilityLevel::Private)
302 .build()
303 .unwrap();
304 api::ignore(endpoint).query(&client).unwrap();
305 }
306
307 #[test]
308 fn endpoint_order_by() {
309 let endpoint = ExpectedUrl::builder()
310 .endpoint("groups/group%2Fsubgroup/projects")
311 .add_query_params(&[("order_by", "id")])
312 .build()
313 .unwrap();
314 let client = SingleTestClient::new_raw(endpoint, "");
315
316 let endpoint = GroupProjects::builder()
317 .group("group/subgroup")
318 .order_by(GroupProjectsOrderBy::Id)
319 .build()
320 .unwrap();
321 api::ignore(endpoint).query(&client).unwrap();
322 }
323
324 #[test]
325 fn endpoint_sort() {
326 let endpoint = ExpectedUrl::builder()
327 .endpoint("groups/group%2Fsubgroup/projects")
328 .add_query_params(&[("sort", "asc")])
329 .build()
330 .unwrap();
331 let client = SingleTestClient::new_raw(endpoint, "");
332
333 let endpoint = GroupProjects::builder()
334 .group("group/subgroup")
335 .sort(SortOrder::Ascending)
336 .build()
337 .unwrap();
338 api::ignore(endpoint).query(&client).unwrap();
339 }
340
341 #[test]
342 fn endpoint_search() {
343 let endpoint = ExpectedUrl::builder()
344 .endpoint("groups/group%2Fsubgroup/projects")
345 .add_query_params(&[("search", "name")])
346 .build()
347 .unwrap();
348 let client = SingleTestClient::new_raw(endpoint, "");
349
350 let endpoint = GroupProjects::builder()
351 .group("group/subgroup")
352 .search("name")
353 .build()
354 .unwrap();
355 api::ignore(endpoint).query(&client).unwrap();
356 }
357
358 #[test]
359 fn endpoint_simple() {
360 let endpoint = ExpectedUrl::builder()
361 .endpoint("groups/group%2Fsubgroup/projects")
362 .add_query_params(&[("simple", "true")])
363 .build()
364 .unwrap();
365 let client = SingleTestClient::new_raw(endpoint, "");
366
367 let endpoint = GroupProjects::builder()
368 .group("group/subgroup")
369 .simple(true)
370 .build()
371 .unwrap();
372 api::ignore(endpoint).query(&client).unwrap();
373 }
374
375 #[test]
376 fn endpoint_owned() {
377 let endpoint = ExpectedUrl::builder()
378 .endpoint("groups/group%2Fsubgroup/projects")
379 .add_query_params(&[("owned", "true")])
380 .build()
381 .unwrap();
382 let client = SingleTestClient::new_raw(endpoint, "");
383
384 let endpoint = GroupProjects::builder()
385 .group("group/subgroup")
386 .owned(true)
387 .build()
388 .unwrap();
389 api::ignore(endpoint).query(&client).unwrap();
390 }
391
392 #[test]
393 fn endpoint_starred() {
394 let endpoint = ExpectedUrl::builder()
395 .endpoint("groups/group%2Fsubgroup/projects")
396 .add_query_params(&[("starred", "true")])
397 .build()
398 .unwrap();
399 let client = SingleTestClient::new_raw(endpoint, "");
400
401 let endpoint = GroupProjects::builder()
402 .group("group/subgroup")
403 .starred(true)
404 .build()
405 .unwrap();
406 api::ignore(endpoint).query(&client).unwrap();
407 }
408
409 #[test]
410 fn endpoint_with_issues_enabled() {
411 let endpoint = ExpectedUrl::builder()
412 .endpoint("groups/group%2Fsubgroup/projects")
413 .add_query_params(&[("with_issues_enabled", "true")])
414 .build()
415 .unwrap();
416 let client = SingleTestClient::new_raw(endpoint, "");
417
418 let endpoint = GroupProjects::builder()
419 .group("group/subgroup")
420 .with_issues_enabled(true)
421 .build()
422 .unwrap();
423 api::ignore(endpoint).query(&client).unwrap();
424 }
425
426 #[test]
427 fn endpoint_with_merge_requests_enabled() {
428 let endpoint = ExpectedUrl::builder()
429 .endpoint("groups/group%2Fsubgroup/projects")
430 .add_query_params(&[("with_merge_requests_enabled", "true")])
431 .build()
432 .unwrap();
433 let client = SingleTestClient::new_raw(endpoint, "");
434
435 let endpoint = GroupProjects::builder()
436 .group("group/subgroup")
437 .with_merge_requests_enabled(true)
438 .build()
439 .unwrap();
440 api::ignore(endpoint).query(&client).unwrap();
441 }
442
443 #[test]
444 fn endpoint_with_shared() {
445 let endpoint = ExpectedUrl::builder()
446 .endpoint("groups/group%2Fsubgroup/projects")
447 .add_query_params(&[("with_shared", "true")])
448 .build()
449 .unwrap();
450 let client = SingleTestClient::new_raw(endpoint, "");
451
452 let endpoint = GroupProjects::builder()
453 .group("group/subgroup")
454 .with_shared(true)
455 .build()
456 .unwrap();
457 api::ignore(endpoint).query(&client).unwrap();
458 }
459
460 #[test]
461 fn endpoint_include_subgroups() {
462 let endpoint = ExpectedUrl::builder()
463 .endpoint("groups/group%2Fsubgroup/projects")
464 .add_query_params(&[("include_subgroups", "true")])
465 .build()
466 .unwrap();
467 let client = SingleTestClient::new_raw(endpoint, "");
468
469 let endpoint = GroupProjects::builder()
470 .group("group/subgroup")
471 .include_subgroups(true)
472 .build()
473 .unwrap();
474 api::ignore(endpoint).query(&client).unwrap();
475 }
476
477 #[test]
478 fn endpoint_min_access_level() {
479 let endpoint = ExpectedUrl::builder()
480 .endpoint("groups/group%2Fsubgroup/projects")
481 .add_query_params(&[("min_access_level", "30")])
482 .build()
483 .unwrap();
484 let client = SingleTestClient::new_raw(endpoint, "");
485
486 let endpoint = GroupProjects::builder()
487 .group("group/subgroup")
488 .min_access_level(AccessLevel::Developer)
489 .build()
490 .unwrap();
491 api::ignore(endpoint).query(&client).unwrap();
492 }
493
494 #[test]
495 fn endpoint_with_custom_attributes() {
496 let endpoint = ExpectedUrl::builder()
497 .endpoint("groups/group%2Fsubgroup/projects")
498 .add_query_params(&[("with_custom_attributes", "true")])
499 .build()
500 .unwrap();
501 let client = SingleTestClient::new_raw(endpoint, "");
502
503 let endpoint = GroupProjects::builder()
504 .group("group/subgroup")
505 .with_custom_attributes(true)
506 .build()
507 .unwrap();
508 api::ignore(endpoint).query(&client).unwrap();
509 }
510
511 #[test]
512 fn endpoint_with_security_reports() {
513 let endpoint = ExpectedUrl::builder()
514 .endpoint("groups/group%2Fsubgroup/projects")
515 .add_query_params(&[("with_security_reports", "true")])
516 .build()
517 .unwrap();
518 let client = SingleTestClient::new_raw(endpoint, "");
519
520 let endpoint = GroupProjects::builder()
521 .group("group/subgroup")
522 .with_security_reports(true)
523 .build()
524 .unwrap();
525 api::ignore(endpoint).query(&client).unwrap();
526 }
527}