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