Skip to content

Commit

Permalink
Add GHIssue#queryComments, with a since() filter
Browse files Browse the repository at this point in the history
  • Loading branch information
yrodiere committed Sep 22, 2022
1 parent adf6a7b commit a628b93
Show file tree
Hide file tree
Showing 84 changed files with 3,355 additions and 1,621 deletions.
14 changes: 13 additions & 1 deletion src/main/java/org/kohsuke/github/GHIssue.java
Expand Up @@ -479,18 +479,30 @@ public List<GHIssueComment> getComments() throws IOException {
}

/**
* Obtains all the comments associated with this issue.
* Obtains all the comments associated with this issue, witout any filter.
*
* @return the paged iterable
* @throws IOException
* the io exception
* @see <a href="https://docs.github.com/en/rest/issues/comments#list-issue-comments">List issue comments</a>
* @see #queryComments() queryComments to apply filters.
*/
public PagedIterable<GHIssueComment> listComments() throws IOException {
return root().createRequest()
.withUrlPath(getIssuesApiRoute() + "/comments")
.toIterable(GHIssueComment[].class, item -> item.wrapUp(this));
}

/**
* Search comments on this issue by specifying filters through a builder pattern.
*
* @return the query builder
* @see <a href="https://docs.github.com/en/rest/issues/comments#list-issue-comments">List issue comments</a>
*/
public GHIssueCommentQueryBuilder queryComments() {
return new GHIssueCommentQueryBuilder(this);
}

@Preview(SQUIRREL_GIRL)
public GHReaction createReaction(ReactionContent content) throws IOException {
return root().createRequest()
Expand Down
61 changes: 61 additions & 0 deletions src/main/java/org/kohsuke/github/GHIssueCommentQueryBuilder.java
@@ -0,0 +1,61 @@
package org.kohsuke.github;

import java.util.Date;

/**
* Builds a query for listing comments on an issue.
* <p>
* Call various methods that set the filter criteria, then the {@link #list()} method to actually retrieve the comments.
*
* <pre>
* GHIssue issue = ...;
* for (GHIssueComment comment : issue.queryComments().since(x).list()) {
* ...
* }
* </pre>
*
* @author Yoann Rodiere
* @see GHIssue#queryComments() GHIssue#queryComments()
* @see <a href="https://docs.github.com/en/rest/issues/comments#list-issue-comments">List issue comments</a>
*/
public class GHIssueCommentQueryBuilder {
private final Requester req;
private final GHIssue issue;

GHIssueCommentQueryBuilder(GHIssue issue) {
this.issue = issue;
this.req = issue.root().createRequest().withUrlPath(issue.getIssuesApiRoute() + "/comments");
}

/**
* Only comments created/updated after this date will be returned.
*
* @param date
* the date
* @return the query builder
*/
public GHIssueCommentQueryBuilder since(Date date) {
req.with("since", GitHubClient.printDate(date));
return this;
}

/**
* Only comments created/updated after this timestamp will be returned.
*
* @param timestamp
* the timestamp
* @return the query builder
*/
public GHIssueCommentQueryBuilder since(long timestamp) {
return since(new Date(timestamp));
}

/**
* Lists up the comments with the criteria added so far.
*
* @return the paged iterable
*/
public PagedIterable<GHIssueComment> list() {
return req.toIterable(GHIssueComment[].class, item -> item.wrapUp(issue));
}
}
79 changes: 77 additions & 2 deletions src/test/java/org/kohsuke/github/GHIssueTest.java
Expand Up @@ -5,13 +5,17 @@
import org.junit.Test;

import java.io.IOException;
import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;

Expand Down Expand Up @@ -43,10 +47,81 @@ public void createIssue() throws Exception {
}

@Test
public void createIssueComment() throws Exception {
public void issueComment() throws Exception {
String name = "createIssueComment";
GHIssue issue = getRepository().createIssue(name).body("## test").create();
issue.comment("Some comment");

List<GHIssueComment> comments;
comments = issue.listComments().toList();
assertThat(comments, hasSize(0));
comments = issue.queryComments().list().toList();
assertThat(comments, hasSize(0));

GHIssueComment firstComment = issue.comment("First comment");
Date firstCommentCreatedAt = firstComment.getCreatedAt();
Date firstCommentCreatedAtPlus1Second = Date
.from(firstComment.getCreatedAt().toInstant().plus(1, ChronoUnit.SECONDS));

comments = issue.listComments().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("First comment"))));

comments = issue.queryComments().list().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("First comment"))));

// Test "since"
comments = issue.queryComments().since(firstCommentCreatedAt).list().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("First comment"))));
comments = issue.queryComments().since(firstCommentCreatedAtPlus1Second).list().toList();
assertThat(comments, hasSize(0));

// "since" is only precise up to the second,
// so if we want to differentiate comments, we need to be completely sure they're created
// at least 1 second from each other.
// Waiting 2 seconds to avoid edge cases.
Thread.sleep(2000);

GHIssueComment secondComment = issue.comment("Second comment");
Date secondCommentCreatedAt = secondComment.getCreatedAt();
Date secondCommentCreatedAtPlus1Second = Date
.from(secondComment.getCreatedAt().toInstant().plus(1, ChronoUnit.SECONDS));
assertThat(
"There's an error in the setup of this test; please fix it."
+ " The second comment should be created at least one second after the first one.",
firstCommentCreatedAtPlus1Second.getTime() <= secondCommentCreatedAt.getTime());

comments = issue.listComments().toList();
assertThat(comments, hasSize(2));
assertThat(comments,
contains(hasProperty("body", equalTo("First comment")),
hasProperty("body", equalTo("Second comment"))));
comments = issue.queryComments().list().toList();
assertThat(comments, hasSize(2));
assertThat(comments,
contains(hasProperty("body", equalTo("First comment")),
hasProperty("body", equalTo("Second comment"))));

// Test "since"
comments = issue.queryComments().since(firstCommentCreatedAt).list().toList();
assertThat(comments, hasSize(2));
assertThat(comments,
contains(hasProperty("body", equalTo("First comment")),
hasProperty("body", equalTo("Second comment"))));
comments = issue.queryComments().since(firstCommentCreatedAtPlus1Second).list().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("Second comment"))));
comments = issue.queryComments().since(secondCommentCreatedAt).list().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("Second comment"))));
comments = issue.queryComments().since(secondCommentCreatedAtPlus1Second).list().toList();
assertThat(comments, hasSize(0));

// Test "since" with timestamp instead of Date
comments = issue.queryComments().since(secondCommentCreatedAt.getTime()).list().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("Second comment"))));
}

@Test
Expand Down
76 changes: 74 additions & 2 deletions src/test/java/org/kohsuke/github/GHPullRequestTest.java
Expand Up @@ -6,8 +6,10 @@
import org.kohsuke.github.GHPullRequest.AutoMerge;

import java.io.IOException;
import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;

Expand Down Expand Up @@ -73,10 +75,80 @@ public void createDraftPullRequest() throws Exception {
}

@Test
public void createPullRequestComment() throws Exception {
public void pullRequestComment() throws Exception {
String name = "createPullRequestComment";
GHPullRequest p = getRepository().createPullRequest(name, "test/stable", "main", "## test");
p.comment("Some comment");

List<GHIssueComment> comments;
comments = p.listComments().toList();
assertThat(comments, hasSize(0));
comments = p.queryComments().list().toList();
assertThat(comments, hasSize(0));

GHIssueComment firstComment = p.comment("First comment");
Date firstCommentCreatedAt = firstComment.getCreatedAt();
Date firstCommentCreatedAtPlus1Second = Date
.from(firstComment.getCreatedAt().toInstant().plus(1, ChronoUnit.SECONDS));

comments = p.listComments().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("First comment"))));
comments = p.queryComments().list().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("First comment"))));

// Test "since"
comments = p.queryComments().since(firstCommentCreatedAt).list().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("First comment"))));
comments = p.queryComments().since(firstCommentCreatedAtPlus1Second).list().toList();
assertThat(comments, hasSize(0));

// "since" is only precise up to the second,
// so if we want to differentiate comments, we need to be completely sure they're created
// at least 1 second from each other.
// Waiting 2 seconds to avoid edge cases.
Thread.sleep(2000);

GHIssueComment secondComment = p.comment("Second comment");
Date secondCommentCreatedAt = secondComment.getCreatedAt();
Date secondCommentCreatedAtPlus1Second = Date
.from(secondComment.getCreatedAt().toInstant().plus(1, ChronoUnit.SECONDS));
assertThat(
"There's an error in the setup of this test; please fix it."
+ " The second comment should be created at least one second after the first one.",
firstCommentCreatedAtPlus1Second.getTime() <= secondCommentCreatedAt.getTime());

comments = p.listComments().toList();
assertThat(comments, hasSize(2));
assertThat(comments,
contains(hasProperty("body", equalTo("First comment")),
hasProperty("body", equalTo("Second comment"))));
comments = p.queryComments().list().toList();
assertThat(comments, hasSize(2));
assertThat(comments,
contains(hasProperty("body", equalTo("First comment")),
hasProperty("body", equalTo("Second comment"))));

// Test "since"
comments = p.queryComments().since(firstCommentCreatedAt).list().toList();
assertThat(comments, hasSize(2));
assertThat(comments,
contains(hasProperty("body", equalTo("First comment")),
hasProperty("body", equalTo("Second comment"))));
comments = p.queryComments().since(firstCommentCreatedAtPlus1Second).list().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("Second comment"))));
comments = p.queryComments().since(secondCommentCreatedAt).list().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("Second comment"))));
comments = p.queryComments().since(secondCommentCreatedAtPlus1Second).list().toList();
assertThat(comments, hasSize(0));

// Test "since" with timestamp instead of Date
comments = p.queryComments().since(secondCommentCreatedAt.getTime()).list().toList();
assertThat(comments, hasSize(1));
assertThat(comments, contains(hasProperty("body", equalTo("Second comment"))));
}

@Test
Expand Down
Expand Up @@ -103,7 +103,7 @@
"triage": true,
"pull": true
},
"temp_clone_token": "AADEZTVSNXJAAABQRALMHX3DFQ3OK",
"temp_clone_token": "AADEZTV5AX4DWMNAEITWHQLDFQ7J2",
"allow_squash_merge": true,
"allow_merge_commit": true,
"allow_rebase_merge": true,
Expand Down Expand Up @@ -136,5 +136,5 @@
"site_admin": false
},
"network_count": 0,
"subscribers_count": 17
"subscribers_count": 16
}
@@ -1,13 +1,13 @@
{
"url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/11",
"url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/15",
"repository_url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest",
"labels_url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/11/labels{/name}",
"comments_url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/11/comments",
"events_url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/11/events",
"html_url": "https://github.com/hub4j-test-org/GHIssueTest/issues/11",
"id": 1382197385,
"node_id": "I_kwDOIC5ExM5SYqiJ",
"number": 11,
"labels_url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/15/labels{/name}",
"comments_url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/15/comments",
"events_url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/15/events",
"html_url": "https://github.com/hub4j-test-org/GHIssueTest/issues/15",
"id": 1382239447,
"node_id": "I_kwDOIC5ExM5SY0zX",
"number": 15,
"title": "createIssueComment",
"user": {
"login": "yrodiere",
Expand Down Expand Up @@ -36,15 +36,15 @@
"assignees": [],
"milestone": null,
"comments": 0,
"created_at": "2022-09-22T10:15:21Z",
"updated_at": "2022-09-22T10:15:21Z",
"created_at": "2022-09-22T10:48:17Z",
"updated_at": "2022-09-22T10:48:17Z",
"closed_at": null,
"author_association": "NONE",
"active_lock_reason": null,
"body": "## test",
"closed_by": null,
"reactions": {
"url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/11/reactions",
"url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/15/reactions",
"total_count": 0,
"+1": 0,
"-1": 0,
Expand All @@ -55,7 +55,7 @@
"rocket": 0,
"eyes": 0
},
"timeline_url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/11/timeline",
"timeline_url": "https://api.github.com/repos/hub4j-test-org/GHIssueTest/issues/15/timeline",
"performed_via_github_app": null,
"state_reason": null
}

0 comments on commit a628b93

Please sign in to comment.