1use std::borrow::Cow;
8use std::collections::BTreeSet;
9use std::iter;
10
11use chrono::{DateTime, Utc};
12use derive_builder::Builder;
13use http::Method;
14
15use crate::api::common::{CommaSeparatedList, NameOrId, SortOrder};
16use crate::api::helpers::{Labels, ReactionEmoji};
17use crate::api::{Endpoint, Pageable, QueryParams};
18
19use super::Assignee;
20use super::IssueDueDateFilter;
21use super::IssueEpic;
22use super::IssueHealthStatus;
23use super::IssueIteration;
24use super::IssueMilestone;
25use super::IssueOrderBy;
26use super::IssueScope;
27use super::IssueSearchScope;
28use super::IssueState;
29use super::IssueType;
30use super::IssueWeight;
31
32#[derive(Debug, Builder, Clone)]
36#[builder(setter(strip_option))]
37pub struct ProjectIssues<'a> {
38 #[builder(setter(into))]
40 project: NameOrId<'a>,
41
42 #[builder(setter(name = "_iids"), default, private)]
44 iids: BTreeSet<u64>,
45 #[builder(default)]
47 state: Option<IssueState>,
48 #[builder(setter(name = "_labels"), default, private)]
50 labels: Option<Labels<'a>>,
51 #[builder(default)]
53 with_labels_details: Option<bool>,
54 #[builder(default)]
56 iteration: Option<IssueIteration<'a>>,
57 #[builder(default)]
59 milestone_id: Option<IssueMilestone<'a>>,
60 #[builder(default)]
62 scope: Option<IssueScope>,
63 #[builder(setter(into), default)]
65 author: Option<NameOrId<'a>>,
66 #[builder(setter(name = "_assignee"), default, private)]
68 assignee: Option<Assignee<'a>>,
69 #[builder(setter(name = "_my_reaction_emoji"), default, private)]
71 my_reaction_emoji: Option<ReactionEmoji<'a>>,
72 #[builder(default)]
74 weight: Option<IssueWeight>,
75 #[builder(setter(into), default)]
77 search: Option<Cow<'a, str>>,
78 #[builder(setter(name = "_search_in"), default, private)]
80 search_in: Option<CommaSeparatedList<IssueSearchScope>>,
81 #[builder(default)]
83 created_after: Option<DateTime<Utc>>,
84 #[builder(default)]
86 created_before: Option<DateTime<Utc>>,
87 #[builder(default)]
89 updated_after: Option<DateTime<Utc>>,
90 #[builder(default)]
92 updated_before: Option<DateTime<Utc>>,
93 #[builder(default)]
95 confidential: Option<bool>,
96 #[builder(default)]
98 due_date: Option<IssueDueDateFilter>,
99 #[builder(setter(into), default)]
101 epic_id: Option<IssueEpic>,
102 #[builder(default)]
104 issue_type: Option<IssueType>,
105 #[builder(default)]
107 health_status: Option<IssueHealthStatus>,
108
109 #[builder(default)]
113 order_by: Option<IssueOrderBy>,
114 #[builder(default)]
116 sort: Option<SortOrder>,
117}
118
119impl<'a> ProjectIssues<'a> {
120 pub fn builder() -> ProjectIssuesBuilder<'a> {
122 ProjectIssuesBuilder::default()
123 }
124}
125
126impl<'a> ProjectIssuesBuilder<'a> {
127 pub fn iid(&mut self, iid: u64) -> &mut Self {
129 self.iids.get_or_insert_with(BTreeSet::new).insert(iid);
130 self
131 }
132
133 pub fn iids<I>(&mut self, iter: I) -> &mut Self
135 where
136 I: Iterator<Item = u64>,
137 {
138 self.iids.get_or_insert_with(BTreeSet::new).extend(iter);
139 self
140 }
141
142 pub fn unlabeled(&mut self) -> &mut Self {
144 self.labels = Some(Some(Labels::None));
145 self
146 }
147
148 pub fn with_any_label(&mut self) -> &mut Self {
150 self.labels = Some(Some(Labels::Any));
151 self
152 }
153
154 pub fn label<L>(&mut self, label: L) -> &mut Self
156 where
157 L: Into<Cow<'a, str>>,
158 {
159 let label = label.into();
160 let labels = if let Some(Some(Labels::AllOf(mut set))) = self.labels.take() {
161 set.push(label);
162 set
163 } else {
164 iter::once(label).collect()
165 };
166 self.labels = Some(Some(Labels::AllOf(labels)));
167 self
168 }
169
170 pub fn labels<I, L>(&mut self, iter: I) -> &mut Self
172 where
173 I: IntoIterator<Item = L>,
174 L: Into<Cow<'a, str>>,
175 {
176 let iter = iter.into_iter().map(Into::into);
177 let labels = if let Some(Some(Labels::AllOf(mut set))) = self.labels.take() {
178 set.extend(iter);
179 set
180 } else {
181 iter.collect()
182 };
183 self.labels = Some(Some(Labels::AllOf(labels)));
184 self
185 }
186
187 pub fn unassigned(&mut self) -> &mut Self {
189 self.assignee = Some(Some(Assignee::Unassigned));
190 self
191 }
192
193 pub fn assigned(&mut self) -> &mut Self {
195 self.assignee = Some(Some(Assignee::Assigned));
196 self
197 }
198
199 pub fn assignee_id(&mut self, assignee: u64) -> &mut Self {
201 self.assignee = Some(Some(Assignee::Id(assignee)));
202 self
203 }
204
205 pub fn assignee<A>(&mut self, assignee: A) -> &mut Self
207 where
208 A: Into<Cow<'a, str>>,
209 {
210 let assignee = assignee.into();
211 let assignees = if let Some(Some(Assignee::Usernames(mut set))) = self.assignee.take() {
212 set.insert(assignee);
213 set
214 } else {
215 let mut set = BTreeSet::new();
216 set.insert(assignee);
217 set
218 };
219 self.assignee = Some(Some(Assignee::Usernames(assignees)));
220 self
221 }
222
223 pub fn assignees<I, A>(&mut self, iter: I) -> &mut Self
225 where
226 I: IntoIterator<Item = A>,
227 A: Into<Cow<'a, str>>,
228 {
229 let iter = iter.into_iter().map(Into::into);
230 let assignees = if let Some(Some(Assignee::Usernames(mut set))) = self.assignee.take() {
231 set.extend(iter);
232 set
233 } else {
234 iter.collect()
235 };
236 self.assignee = Some(Some(Assignee::Usernames(assignees)));
237 self
238 }
239
240 pub fn no_reaction(&mut self) -> &mut Self {
242 self.my_reaction_emoji = Some(Some(ReactionEmoji::None));
243 self
244 }
245
246 pub fn any_reaction(&mut self) -> &mut Self {
248 self.my_reaction_emoji = Some(Some(ReactionEmoji::Any));
249 self
250 }
251
252 pub fn my_reaction<E>(&mut self, emoji: E) -> &mut Self
254 where
255 E: Into<Cow<'a, str>>,
256 {
257 self.my_reaction_emoji = Some(Some(ReactionEmoji::Emoji(emoji.into())));
258 self
259 }
260
261 pub fn search_in(&mut self, scope: IssueSearchScope) -> &mut Self {
263 self.search_in
264 .get_or_insert(None)
265 .get_or_insert_with(CommaSeparatedList::new)
266 .push(scope);
267 self
268 }
269}
270
271impl Endpoint for ProjectIssues<'_> {
272 fn method(&self) -> Method {
273 Method::GET
274 }
275
276 fn endpoint(&self) -> Cow<'static, str> {
277 format!("projects/{}/issues", self.project).into()
278 }
279
280 fn parameters(&self) -> QueryParams<'_> {
281 let mut params = QueryParams::default();
282
283 params
284 .extend(self.iids.iter().map(|&value| ("iids[]", value)))
285 .push_opt("state", self.state)
286 .push_opt("labels", self.labels.as_ref())
287 .push_opt("with_labels_details", self.with_labels_details)
288 .push_opt("scope", self.scope)
289 .push_opt("my_reaction_emoji", self.my_reaction_emoji.as_ref())
290 .push_opt("weight", self.weight)
291 .push_opt("search", self.search.as_ref())
292 .push_opt("in", self.search_in.as_ref())
293 .push_opt("created_after", self.created_after)
294 .push_opt("created_before", self.created_before)
295 .push_opt("updated_after", self.updated_after)
296 .push_opt("updated_before", self.updated_before)
297 .push_opt("confidential", self.confidential)
298 .push_opt("due_date", self.due_date)
299 .push_opt("epic_id", self.epic_id)
300 .push_opt("issue_type", self.issue_type)
301 .push_opt("health_status", self.health_status)
302 .push_opt("order_by", self.order_by)
303 .push_opt("sort", self.sort);
304
305 if let Some(milestone_id) = self.milestone_id.as_ref() {
306 match milestone_id {
307 IssueMilestone::Named(name) => {
308 params.push("milestone", name);
309 },
310 milestone => {
311 params.push("milestone_id", milestone);
312 },
313 }
314 }
315 if let Some(author) = self.author.as_ref() {
316 match author {
317 NameOrId::Name(name) => {
318 params.push("author_username", name);
319 },
320 NameOrId::Id(id) => {
321 params.push("author_id", *id);
322 },
323 }
324 }
325 if let Some(iteration) = self.iteration.as_ref() {
326 iteration.add_params(&mut params);
327 }
328 if let Some(assignee) = self.assignee.as_ref() {
329 assignee.add_params(&mut params);
330 }
331
332 params
333 }
334}
335
336impl Pageable for ProjectIssues<'_> {}
337
338#[cfg(test)]
339mod tests {
340 use chrono::{TimeZone, Utc};
341
342 use crate::api::common::SortOrder;
343 use crate::api::issues::{
344 projects::ProjectIssues, projects::ProjectIssuesBuilderError, IssueDueDateFilter,
345 IssueEpic, IssueHealthStatus, IssueIteration, IssueMilestone, IssueOrderBy, IssueScope,
346 IssueSearchScope, IssueState, IssueType, IssueWeight,
347 };
348 use crate::api::{self, Query};
349 use crate::test::client::{ExpectedUrl, SingleTestClient};
350
351 #[test]
352 fn project_is_needed() {
353 let err = ProjectIssues::builder().build().unwrap_err();
354 crate::test::assert_missing_field!(err, ProjectIssuesBuilderError, "project");
355 }
356
357 #[test]
358 fn project_is_sufficient() {
359 ProjectIssues::builder().project(1).build().unwrap();
360 }
361
362 #[test]
363 fn endpoint() {
364 let endpoint = ExpectedUrl::builder()
365 .endpoint("projects/simple%2Fproject/issues")
366 .build()
367 .unwrap();
368 let client = SingleTestClient::new_raw(endpoint, "");
369
370 let endpoint = ProjectIssues::builder()
371 .project("simple/project")
372 .build()
373 .unwrap();
374 api::ignore(endpoint).query(&client).unwrap();
375 }
376
377 #[test]
378 fn endpoint_iids() {
379 let endpoint = ExpectedUrl::builder()
380 .endpoint("projects/simple%2Fproject/issues")
381 .add_query_params(&[("iids[]", "1"), ("iids[]", "2")])
382 .build()
383 .unwrap();
384 let client = SingleTestClient::new_raw(endpoint, "");
385
386 let endpoint = ProjectIssues::builder()
387 .project("simple/project")
388 .iid(1)
389 .iids([1, 2].iter().copied())
390 .build()
391 .unwrap();
392 api::ignore(endpoint).query(&client).unwrap();
393 }
394
395 #[test]
396 fn endpoint_state() {
397 let endpoint = ExpectedUrl::builder()
398 .endpoint("projects/simple%2Fproject/issues")
399 .add_query_params(&[("state", "closed")])
400 .build()
401 .unwrap();
402 let client = SingleTestClient::new_raw(endpoint, "");
403
404 let endpoint = ProjectIssues::builder()
405 .project("simple/project")
406 .state(IssueState::Closed)
407 .build()
408 .unwrap();
409 api::ignore(endpoint).query(&client).unwrap();
410 }
411
412 #[test]
413 fn endpoint_labels() {
414 let endpoint = ExpectedUrl::builder()
415 .endpoint("projects/simple%2Fproject/issues")
416 .add_query_params(&[("labels", "label,label1,label2")])
417 .build()
418 .unwrap();
419 let client = SingleTestClient::new_raw(endpoint, "");
420
421 let endpoint = ProjectIssues::builder()
422 .project("simple/project")
423 .label("label")
424 .labels(["label1", "label2"].iter().cloned())
425 .build()
426 .unwrap();
427 api::ignore(endpoint).query(&client).unwrap();
428 }
429
430 #[test]
431 fn endpoint_labels_unlabeled() {
432 let endpoint = ExpectedUrl::builder()
433 .endpoint("projects/simple%2Fproject/issues")
434 .add_query_params(&[("labels", "None")])
435 .build()
436 .unwrap();
437 let client = SingleTestClient::new_raw(endpoint, "");
438
439 let endpoint = ProjectIssues::builder()
440 .project("simple/project")
441 .unlabeled()
442 .build()
443 .unwrap();
444 api::ignore(endpoint).query(&client).unwrap();
445 }
446
447 #[test]
448 fn endpoint_labels_any() {
449 let endpoint = ExpectedUrl::builder()
450 .endpoint("projects/simple%2Fproject/issues")
451 .add_query_params(&[("labels", "Any")])
452 .build()
453 .unwrap();
454 let client = SingleTestClient::new_raw(endpoint, "");
455
456 let endpoint = ProjectIssues::builder()
457 .project("simple/project")
458 .with_any_label()
459 .build()
460 .unwrap();
461 api::ignore(endpoint).query(&client).unwrap();
462 }
463
464 #[test]
465 fn endpoint_with_labels_details() {
466 let endpoint = ExpectedUrl::builder()
467 .endpoint("projects/simple%2Fproject/issues")
468 .add_query_params(&[("with_labels_details", "true")])
469 .build()
470 .unwrap();
471 let client = SingleTestClient::new_raw(endpoint, "");
472
473 let endpoint = ProjectIssues::builder()
474 .project("simple/project")
475 .with_labels_details(true)
476 .build()
477 .unwrap();
478 api::ignore(endpoint).query(&client).unwrap();
479 }
480
481 #[test]
482 fn endpoint_epic_id() {
483 let endpoint = ExpectedUrl::builder()
484 .endpoint("projects/simple%2Fproject/issues")
485 .add_query_params(&[("epic_id", "1")])
486 .build()
487 .unwrap();
488 let client = SingleTestClient::new_raw(endpoint, "");
489
490 let endpoint = ProjectIssues::builder()
491 .project("simple/project")
492 .epic_id(1)
493 .build()
494 .unwrap();
495 api::ignore(endpoint).query(&client).unwrap();
496 }
497
498 #[test]
499 fn endpoint_epic_id_any() {
500 let endpoint = ExpectedUrl::builder()
501 .endpoint("projects/simple%2Fproject/issues")
502 .add_query_params(&[("epic_id", "Any")])
503 .build()
504 .unwrap();
505 let client = SingleTestClient::new_raw(endpoint, "");
506
507 let endpoint = ProjectIssues::builder()
508 .project("simple/project")
509 .epic_id(IssueEpic::Any)
510 .build()
511 .unwrap();
512 api::ignore(endpoint).query(&client).unwrap();
513 }
514
515 #[test]
516 fn endpoint_epic_id_none() {
517 let endpoint = ExpectedUrl::builder()
518 .endpoint("projects/simple%2Fproject/issues")
519 .add_query_params(&[("epic_id", "None")])
520 .build()
521 .unwrap();
522 let client = SingleTestClient::new_raw(endpoint, "");
523
524 let endpoint = ProjectIssues::builder()
525 .project("simple/project")
526 .epic_id(IssueEpic::None)
527 .build()
528 .unwrap();
529 api::ignore(endpoint).query(&client).unwrap();
530 }
531
532 #[test]
533 fn endpoint_issue_type() {
534 let endpoint = ExpectedUrl::builder()
535 .endpoint("projects/simple%2Fproject/issues")
536 .add_query_params(&[("issue_type", "incident")])
537 .build()
538 .unwrap();
539 let client = SingleTestClient::new_raw(endpoint, "");
540
541 let endpoint = ProjectIssues::builder()
542 .project("simple/project")
543 .issue_type(IssueType::Incident)
544 .build()
545 .unwrap();
546 api::ignore(endpoint).query(&client).unwrap();
547 }
548
549 #[test]
550 fn endpoint_health_status() {
551 let endpoint = ExpectedUrl::builder()
552 .endpoint("projects/simple%2Fproject/issues")
553 .add_query_params(&[("health_status", "at_risk")])
554 .build()
555 .unwrap();
556 let client = SingleTestClient::new_raw(endpoint, "");
557
558 let endpoint = ProjectIssues::builder()
559 .project("simple/project")
560 .health_status(IssueHealthStatus::AtRisk)
561 .build()
562 .unwrap();
563 api::ignore(endpoint).query(&client).unwrap();
564 }
565
566 #[test]
567 fn endpoint_iteration_none() {
568 let endpoint = ExpectedUrl::builder()
569 .endpoint("projects/simple%2Fproject/issues")
570 .add_query_params(&[("iteration_id", "None")])
571 .build()
572 .unwrap();
573 let client = SingleTestClient::new_raw(endpoint, "");
574
575 let endpoint = ProjectIssues::builder()
576 .project("simple/project")
577 .iteration(IssueIteration::None)
578 .build()
579 .unwrap();
580 api::ignore(endpoint).query(&client).unwrap();
581 }
582
583 #[test]
584 fn endpoint_iteration_any() {
585 let endpoint = ExpectedUrl::builder()
586 .endpoint("projects/simple%2Fproject/issues")
587 .add_query_params(&[("iteration_id", "Any")])
588 .build()
589 .unwrap();
590 let client = SingleTestClient::new_raw(endpoint, "");
591
592 let endpoint = ProjectIssues::builder()
593 .project("simple/project")
594 .iteration(IssueIteration::Any)
595 .build()
596 .unwrap();
597 api::ignore(endpoint).query(&client).unwrap();
598 }
599
600 #[test]
601 fn endpoint_iteration_id() {
602 let endpoint = ExpectedUrl::builder()
603 .endpoint("projects/simple%2Fproject/issues")
604 .add_query_params(&[("iteration_id", "1")])
605 .build()
606 .unwrap();
607 let client = SingleTestClient::new_raw(endpoint, "");
608
609 let endpoint = ProjectIssues::builder()
610 .project("simple/project")
611 .iteration(IssueIteration::Id(1))
612 .build()
613 .unwrap();
614 api::ignore(endpoint).query(&client).unwrap();
615 }
616
617 #[test]
618 fn endpoint_iteration_title() {
619 let endpoint = ExpectedUrl::builder()
620 .endpoint("projects/simple%2Fproject/issues")
621 .add_query_params(&[("iteration_title", "title")])
622 .build()
623 .unwrap();
624 let client = SingleTestClient::new_raw(endpoint, "");
625
626 let endpoint = ProjectIssues::builder()
627 .project("simple/project")
628 .iteration(IssueIteration::Title("title".into()))
629 .build()
630 .unwrap();
631 api::ignore(endpoint).query(&client).unwrap();
632 }
633
634 #[test]
635 fn endpoint_milestone_id() {
636 let endpoint = ExpectedUrl::builder()
637 .endpoint("projects/simple%2Fproject/issues")
638 .add_query_params(&[("milestone_id", "Upcoming")])
639 .build()
640 .unwrap();
641 let client = SingleTestClient::new_raw(endpoint, "");
642
643 let endpoint = ProjectIssues::builder()
644 .project("simple/project")
645 .milestone_id(IssueMilestone::Upcoming)
646 .build()
647 .unwrap();
648 api::ignore(endpoint).query(&client).unwrap();
649 }
650
651 #[test]
652 fn endpoint_milestone_id_named() {
653 let endpoint = ExpectedUrl::builder()
654 .endpoint("projects/simple%2Fproject/issues")
655 .add_query_params(&[("milestone", "1.0")])
656 .build()
657 .unwrap();
658 let client = SingleTestClient::new_raw(endpoint, "");
659
660 let endpoint = ProjectIssues::builder()
661 .project("simple/project")
662 .milestone_id(IssueMilestone::named("1.0"))
663 .build()
664 .unwrap();
665 api::ignore(endpoint).query(&client).unwrap();
666 }
667
668 #[test]
669 fn endpoint_scope() {
670 let endpoint = ExpectedUrl::builder()
671 .endpoint("projects/simple%2Fproject/issues")
672 .add_query_params(&[("scope", "all")])
673 .build()
674 .unwrap();
675 let client = SingleTestClient::new_raw(endpoint, "");
676
677 let endpoint = ProjectIssues::builder()
678 .project("simple/project")
679 .scope(IssueScope::All)
680 .build()
681 .unwrap();
682 api::ignore(endpoint).query(&client).unwrap();
683 }
684
685 #[test]
686 fn endpoint_author_id() {
687 let endpoint = ExpectedUrl::builder()
688 .endpoint("projects/simple%2Fproject/issues")
689 .add_query_params(&[("author_id", "1")])
690 .build()
691 .unwrap();
692 let client = SingleTestClient::new_raw(endpoint, "");
693
694 let endpoint = ProjectIssues::builder()
695 .project("simple/project")
696 .author(1)
697 .build()
698 .unwrap();
699 api::ignore(endpoint).query(&client).unwrap();
700 }
701
702 #[test]
703 fn endpoint_author_name() {
704 let endpoint = ExpectedUrl::builder()
705 .endpoint("projects/simple%2Fproject/issues")
706 .add_query_params(&[("author_username", "name")])
707 .build()
708 .unwrap();
709 let client = SingleTestClient::new_raw(endpoint, "");
710
711 let endpoint = ProjectIssues::builder()
712 .project("simple/project")
713 .author("name")
714 .build()
715 .unwrap();
716 api::ignore(endpoint).query(&client).unwrap();
717 }
718
719 #[test]
720 fn endpoint_assignee_unassigned() {
721 let endpoint = ExpectedUrl::builder()
722 .endpoint("projects/simple%2Fproject/issues")
723 .add_query_params(&[("assignee_id", "None")])
724 .build()
725 .unwrap();
726 let client = SingleTestClient::new_raw(endpoint, "");
727
728 let endpoint = ProjectIssues::builder()
729 .project("simple/project")
730 .unassigned()
731 .build()
732 .unwrap();
733 api::ignore(endpoint).query(&client).unwrap();
734 }
735
736 #[test]
737 fn endpoint_assignee_assigned() {
738 let endpoint = ExpectedUrl::builder()
739 .endpoint("projects/simple%2Fproject/issues")
740 .add_query_params(&[("assignee_id", "Any")])
741 .build()
742 .unwrap();
743 let client = SingleTestClient::new_raw(endpoint, "");
744
745 let endpoint = ProjectIssues::builder()
746 .project("simple/project")
747 .assigned()
748 .build()
749 .unwrap();
750 api::ignore(endpoint).query(&client).unwrap();
751 }
752
753 #[test]
754 fn endpoint_assignee_id() {
755 let endpoint = ExpectedUrl::builder()
756 .endpoint("projects/simple%2Fproject/issues")
757 .add_query_params(&[("assignee_id", "1")])
758 .build()
759 .unwrap();
760 let client = SingleTestClient::new_raw(endpoint, "");
761
762 let endpoint = ProjectIssues::builder()
763 .project("simple/project")
764 .assignee_id(1)
765 .build()
766 .unwrap();
767 api::ignore(endpoint).query(&client).unwrap();
768 }
769
770 #[test]
771 fn endpoint_assignee_user() {
772 let endpoint = ExpectedUrl::builder()
773 .endpoint("projects/simple%2Fproject/issues")
774 .add_query_params(&[
775 ("assignee_username[]", "name1"),
776 ("assignee_username[]", "name2"),
777 ])
778 .build()
779 .unwrap();
780 let client = SingleTestClient::new_raw(endpoint, "");
781
782 let endpoint = ProjectIssues::builder()
783 .project("simple/project")
784 .assignee("name1")
785 .assignees(["name1", "name2"].iter().copied())
786 .build()
787 .unwrap();
788 api::ignore(endpoint).query(&client).unwrap();
789 }
790
791 #[test]
792 fn endpoint_my_reaction_emoji() {
793 let endpoint = ExpectedUrl::builder()
794 .endpoint("projects/simple%2Fproject/issues")
795 .add_query_params(&[("my_reaction_emoji", "tada")])
796 .build()
797 .unwrap();
798 let client = SingleTestClient::new_raw(endpoint, "");
799
800 let endpoint = ProjectIssues::builder()
801 .project("simple/project")
802 .my_reaction("tada")
803 .build()
804 .unwrap();
805 api::ignore(endpoint).query(&client).unwrap();
806 }
807
808 #[test]
809 fn endpoint_my_reaction_emoji_no_reaction() {
810 let endpoint = ExpectedUrl::builder()
811 .endpoint("projects/simple%2Fproject/issues")
812 .add_query_params(&[("my_reaction_emoji", "None")])
813 .build()
814 .unwrap();
815 let client = SingleTestClient::new_raw(endpoint, "");
816
817 let endpoint = ProjectIssues::builder()
818 .project("simple/project")
819 .no_reaction()
820 .build()
821 .unwrap();
822 api::ignore(endpoint).query(&client).unwrap();
823 }
824
825 #[test]
826 fn endpoint_my_reaction_emoji_any_reaction() {
827 let endpoint = ExpectedUrl::builder()
828 .endpoint("projects/simple%2Fproject/issues")
829 .add_query_params(&[("my_reaction_emoji", "Any")])
830 .build()
831 .unwrap();
832 let client = SingleTestClient::new_raw(endpoint, "");
833
834 let endpoint = ProjectIssues::builder()
835 .project("simple/project")
836 .any_reaction()
837 .build()
838 .unwrap();
839 api::ignore(endpoint).query(&client).unwrap();
840 }
841
842 #[test]
843 fn endpoint_weight() {
844 let endpoint = ExpectedUrl::builder()
845 .endpoint("projects/simple%2Fproject/issues")
846 .add_query_params(&[("weight", "Any")])
847 .build()
848 .unwrap();
849 let client = SingleTestClient::new_raw(endpoint, "");
850
851 let endpoint = ProjectIssues::builder()
852 .project("simple/project")
853 .weight(IssueWeight::Any)
854 .build()
855 .unwrap();
856 api::ignore(endpoint).query(&client).unwrap();
857 }
858
859 #[test]
860 fn endpoint_search() {
861 let endpoint = ExpectedUrl::builder()
862 .endpoint("projects/simple%2Fproject/issues")
863 .add_query_params(&[("search", "query")])
864 .build()
865 .unwrap();
866 let client = SingleTestClient::new_raw(endpoint, "");
867
868 let endpoint = ProjectIssues::builder()
869 .project("simple/project")
870 .search("query")
871 .build()
872 .unwrap();
873 api::ignore(endpoint).query(&client).unwrap();
874 }
875
876 #[test]
877 fn endpoint_search_in() {
878 let endpoint = ExpectedUrl::builder()
879 .endpoint("projects/simple%2Fproject/issues")
880 .add_query_params(&[("in", "title,description")])
881 .build()
882 .unwrap();
883 let client = SingleTestClient::new_raw(endpoint, "");
884
885 let endpoint = ProjectIssues::builder()
886 .project("simple/project")
887 .search_in(IssueSearchScope::Title)
888 .search_in(IssueSearchScope::Description)
889 .build()
890 .unwrap();
891 api::ignore(endpoint).query(&client).unwrap();
892 }
893
894 #[test]
895 fn endpoint_created_after() {
896 let endpoint = ExpectedUrl::builder()
897 .endpoint("projects/simple%2Fproject/issues")
898 .add_query_params(&[("created_after", "2020-01-01T00:00:00Z")])
899 .build()
900 .unwrap();
901 let client = SingleTestClient::new_raw(endpoint, "");
902
903 let endpoint = ProjectIssues::builder()
904 .project("simple/project")
905 .created_after(Utc.with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap())
906 .build()
907 .unwrap();
908 api::ignore(endpoint).query(&client).unwrap();
909 }
910
911 #[test]
912 fn endpoint_created_before() {
913 let endpoint = ExpectedUrl::builder()
914 .endpoint("projects/simple%2Fproject/issues")
915 .add_query_params(&[("created_before", "2020-01-01T00:00:00Z")])
916 .build()
917 .unwrap();
918 let client = SingleTestClient::new_raw(endpoint, "");
919
920 let endpoint = ProjectIssues::builder()
921 .project("simple/project")
922 .created_before(Utc.with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap())
923 .build()
924 .unwrap();
925 api::ignore(endpoint).query(&client).unwrap();
926 }
927
928 #[test]
929 fn endpoint_updated_after() {
930 let endpoint = ExpectedUrl::builder()
931 .endpoint("projects/simple%2Fproject/issues")
932 .add_query_params(&[("updated_after", "2020-01-01T00:00:00Z")])
933 .build()
934 .unwrap();
935 let client = SingleTestClient::new_raw(endpoint, "");
936
937 let endpoint = ProjectIssues::builder()
938 .project("simple/project")
939 .updated_after(Utc.with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap())
940 .build()
941 .unwrap();
942 api::ignore(endpoint).query(&client).unwrap();
943 }
944
945 #[test]
946 fn endpoint_updated_before() {
947 let endpoint = ExpectedUrl::builder()
948 .endpoint("projects/simple%2Fproject/issues")
949 .add_query_params(&[("updated_before", "2020-01-01T00:00:00Z")])
950 .build()
951 .unwrap();
952 let client = SingleTestClient::new_raw(endpoint, "");
953
954 let endpoint = ProjectIssues::builder()
955 .project("simple/project")
956 .updated_before(Utc.with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap())
957 .build()
958 .unwrap();
959 api::ignore(endpoint).query(&client).unwrap();
960 }
961
962 #[test]
963 fn endpoint_confidential() {
964 let endpoint = ExpectedUrl::builder()
965 .endpoint("projects/simple%2Fproject/issues")
966 .add_query_params(&[("confidential", "true")])
967 .build()
968 .unwrap();
969 let client = SingleTestClient::new_raw(endpoint, "");
970
971 let endpoint = ProjectIssues::builder()
972 .project("simple/project")
973 .confidential(true)
974 .build()
975 .unwrap();
976 api::ignore(endpoint).query(&client).unwrap();
977 }
978
979 #[test]
980 fn endpoint_due_date() {
981 let endpoint = ExpectedUrl::builder()
982 .endpoint("projects/simple%2Fproject/issues")
983 .add_query_params(&[("due_date", "week")])
984 .build()
985 .unwrap();
986 let client = SingleTestClient::new_raw(endpoint, "");
987
988 let endpoint = ProjectIssues::builder()
989 .project("simple/project")
990 .due_date(IssueDueDateFilter::ThisWeek)
991 .build()
992 .unwrap();
993 api::ignore(endpoint).query(&client).unwrap();
994 }
995
996 #[test]
997 fn endpoint_order_by() {
998 let endpoint = ExpectedUrl::builder()
999 .endpoint("projects/simple%2Fproject/issues")
1000 .add_query_params(&[("order_by", "due_date")])
1001 .build()
1002 .unwrap();
1003 let client = SingleTestClient::new_raw(endpoint, "");
1004
1005 let endpoint = ProjectIssues::builder()
1006 .project("simple/project")
1007 .order_by(IssueOrderBy::DueDate)
1008 .build()
1009 .unwrap();
1010 api::ignore(endpoint).query(&client).unwrap();
1011 }
1012
1013 #[test]
1014 fn endpoint_sort() {
1015 let endpoint = ExpectedUrl::builder()
1016 .endpoint("projects/simple%2Fproject/issues")
1017 .add_query_params(&[("sort", "desc")])
1018 .build()
1019 .unwrap();
1020 let client = SingleTestClient::new_raw(endpoint, "");
1021
1022 let endpoint = ProjectIssues::builder()
1023 .project("simple/project")
1024 .sort(SortOrder::Descending)
1025 .build()
1026 .unwrap();
1027 api::ignore(endpoint).query(&client).unwrap();
1028 }
1029}