From b4de813bf57746b890c6a4ab1c9cf090375f6d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 30 Oct 2026 13:56:12 +0000 Subject: [PATCH 1/2] Fix GHInvitation getId() always returning 0 and add missing getters GHInvitation declared its own `private int id` field which shadowed the `private long id` in GHObject. Jackson deserialized the API's id into the shadow field, but GHObject.getId() read the parent's field which was always 0. Remove the shadowing field, switch accept()/decline() to use getId(), add the missing `expired` field, and expose getters for all fields that were previously inaccessible: invitee, inviter, permission, repository, expired. Fixes hub4j/github-api#1598 --- .../java/org/kohsuke/github/GHInvitation.java | 61 +++- .../org/kohsuke/github/GHInvitationTest.java | 73 ++++ .../__files/1-orgs_hub4j-test-org.json | 41 +++ .../__files/2-r_h_github-api.json | 330 ++++++++++++++++++ .../__files/3-r_h_g_invitations.json | 55 +++ .../testListInvitations/__files/4-user.json | 36 ++ .../mappings/1-orgs_hub4j-test-org.json | 28 ++ .../mappings/2-r_h_github-api.json | 28 ++ .../mappings/3-r_h_g_invitations.json | 28 ++ .../testListInvitations/mappings/4-user.json | 49 +++ 10 files changed, 725 insertions(+), 4 deletions(-) create mode 100644 src/test/java/org/kohsuke/github/GHInvitationTest.java create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/1-orgs_hub4j-test-org.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/2-r_h_github-api.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/3-r_h_g_invitations.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/4-user.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/1-orgs_hub4j-test-org.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/2-r_h_github-api.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/3-r_h_g_invitations.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/4-user.json diff --git a/src/main/java/org/kohsuke/github/GHInvitation.java b/src/main/java/org/kohsuke/github/GHInvitation.java index 726179d897..6f4aa06c7d 100644 --- a/src/main/java/org/kohsuke/github/GHInvitation.java +++ b/src/main/java/org/kohsuke/github/GHInvitation.java @@ -11,6 +11,7 @@ * * @see GitHub#getMyInvitations() GitHub#getMyInvitations() * @see GHRepository#listInvitations() GHRepository#listInvitations() + * @see Repository invitations API */ @SuppressFBWarnings( value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", @@ -18,12 +19,12 @@ justification = "JSON API") public class GHInvitation extends GHObject { + private boolean expired; private String htmlUrl; - - private int id; private GHUser invitee, inviter; private String permissions; private GHRepository repository; + /** * Create default GHInvitation instance */ @@ -35,9 +36,11 @@ public GHInvitation() { * * @throws IOException * the io exception + * @see Accept a + * repository invitation */ public void accept() throws IOException { - root().createRequest().method("PATCH").withUrlPath("/user/repository_invitations/" + id).send(); + root().createRequest().method("PATCH").withUrlPath("/user/repository_invitations/" + getId()).send(); } /** @@ -45,9 +48,11 @@ public void accept() throws IOException { * * @throws IOException * the io exception + * @see Decline + * a repository invitation */ public void decline() throws IOException { - root().createRequest().method("DELETE").withUrlPath("/user/repository_invitations/" + id).send(); + root().createRequest().method("DELETE").withUrlPath("/user/repository_invitations/" + getId()).send(); } /** @@ -58,4 +63,52 @@ public void decline() throws IOException { public URL getHtmlUrl() { return GitHubClient.parseURL(htmlUrl); } + + /** + * Gets the invitee (the user being invited). + * + * @return the invitee + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getInvitee() { + return invitee; + } + + /** + * Gets the inviter (the user who created the invitation). + * + * @return the inviter + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getInviter() { + return inviter; + } + + /** + * Gets the permission associated with the invitation. + * + * @return the permission (e.g. "read", "write", "admin", "triage", "maintain") + */ + public String getPermission() { + return permissions; + } + + /** + * Gets the repository for this invitation. + * + * @return the repository + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getRepository() { + return repository; + } + + /** + * Whether this invitation has expired. + * + * @return true if expired + */ + public boolean isExpired() { + return expired; + } } diff --git a/src/test/java/org/kohsuke/github/GHInvitationTest.java b/src/test/java/org/kohsuke/github/GHInvitationTest.java new file mode 100644 index 0000000000..3d58c2859b --- /dev/null +++ b/src/test/java/org/kohsuke/github/GHInvitationTest.java @@ -0,0 +1,73 @@ +package org.kohsuke.github; + +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +import static org.hamcrest.Matchers.*; + +/** + * Tests for {@link GHInvitation}. + * + * @author Yoann Rodiere + */ +public class GHInvitationTest extends AbstractGitHubWireMockTest { + + /** + * Create default GHInvitationTest instance + */ + public GHInvitationTest() { + } + + /** + * Test that listing repository invitations returns correct data for all fields. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testListInvitations() throws IOException { + GHRepository repo = getRepository(); + List invitations = repo.listInvitations().toList(); + + assertThat(invitations, hasSize(1)); + + GHInvitation invitation = invitations.get(0); + + assertThat(invitation.getId(), equalTo(1L)); + assertThat(invitation.getNodeId(), equalTo("MDEwOlJlcG9zaXRvcnkxMjk2MjY5")); + assertThat(invitation.getPermission(), equalTo("write")); + assertThat(invitation.isExpired(), equalTo(false)); + assertThat(invitation.getHtmlUrl().toString(), + equalTo("https://github.com/hub4j-test-org/github-api/invitations")); + assertThat(invitation.getCreatedAt().toString(), equalTo("2016-06-13T14:52:50Z")); + + GHUser invitee = invitation.getInvitee(); + assertThat(invitee, notNullValue()); + assertThat(invitee.getLogin(), equalTo("octocat-invitee")); + + GHUser inviter = invitation.getInviter(); + assertThat(inviter, notNullValue()); + assertThat(inviter.getLogin(), equalTo("octocat")); + + GHRepository invitationRepo = invitation.getRepository(); + assertThat(invitationRepo, notNullValue()); + assertThat(invitationRepo.getName(), equalTo("github-api")); + } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + } + + /** + * Gets the repository. + * + * @return the repository + * @throws IOException + * Signals that an I/O exception has occurred. + */ + protected GHRepository getRepository() throws IOException { + return getRepository(gitHub); + } +} diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/1-orgs_hub4j-test-org.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/1-orgs_hub4j-test-org.json new file mode 100644 index 0000000000..75b2dc2753 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/1-orgs_hub4j-test-org.json @@ -0,0 +1,41 @@ +{ + "login": "hub4j-test-org", + "id": 7544739, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", + "url": "https://api.github.com/orgs/hub4j-test-org", + "repos_url": "https://api.github.com/orgs/hub4j-test-org/repos", + "events_url": "https://api.github.com/orgs/hub4j-test-org/events", + "hooks_url": "https://api.github.com/orgs/hub4j-test-org/hooks", + "issues_url": "https://api.github.com/orgs/hub4j-test-org/issues", + "members_url": "https://api.github.com/orgs/hub4j-test-org/members{/member}", + "public_members_url": "https://api.github.com/orgs/hub4j-test-org/public_members{/member}", + "avatar_url": "https://avatars3.githubusercontent.com/u/7544739?v=4", + "description": null, + "is_verified": false, + "has_organization_projects": true, + "has_repository_projects": true, + "public_repos": 10, + "public_gists": 0, + "followers": 0, + "following": 0, + "html_url": "https://github.com/hub4j-test-org", + "created_at": "2014-05-10T19:39:11Z", + "updated_at": "2015-04-20T00:42:30Z", + "type": "Organization", + "total_private_repos": 0, + "owned_private_repos": 0, + "private_gists": 0, + "disk_usage": 132, + "collaborators": 0, + "billing_email": "kk@kohsuke.org", + "default_repository_permission": "none", + "members_can_create_repositories": false, + "two_factor_requirement_enabled": false, + "plan": { + "name": "free", + "space": 976562499, + "private_repos": 0, + "filled_seats": 7, + "seats": 0 + } +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/2-r_h_github-api.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/2-r_h_github-api.json new file mode 100644 index 0000000000..02c3a00302 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/2-r_h_github-api.json @@ -0,0 +1,330 @@ +{ + "id": 206888201, + "node_id": "MDEwOlJlcG9zaXRvcnkyMDY4ODgyMDE=", + "name": "github-api", + "full_name": "hub4j-test-org/github-api", + "private": false, + "owner": { + "login": "hub4j-test-org", + "id": 7544739, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", + "avatar_url": "https://avatars3.githubusercontent.com/u/7544739?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/hub4j-test-org", + "html_url": "https://github.com/hub4j-test-org", + "followers_url": "https://api.github.com/users/hub4j-test-org/followers", + "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", + "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", + "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", + "repos_url": "https://api.github.com/users/hub4j-test-org/repos", + "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/hub4j-test-org/github-api", + "description": "Tricky", + "fork": true, + "url": "https://api.github.com/repos/hub4j-test-org/github-api", + "forks_url": "https://api.github.com/repos/hub4j-test-org/github-api/forks", + "keys_url": "https://api.github.com/repos/hub4j-test-org/github-api/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/hub4j-test-org/github-api/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/hub4j-test-org/github-api/teams", + "hooks_url": "https://api.github.com/repos/hub4j-test-org/github-api/hooks", + "issue_events_url": "https://api.github.com/repos/hub4j-test-org/github-api/issues/events{/number}", + "events_url": "https://api.github.com/repos/hub4j-test-org/github-api/events", + "assignees_url": "https://api.github.com/repos/hub4j-test-org/github-api/assignees{/user}", + "branches_url": "https://api.github.com/repos/hub4j-test-org/github-api/branches{/branch}", + "tags_url": "https://api.github.com/repos/hub4j-test-org/github-api/tags", + "blobs_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/hub4j-test-org/github-api/statuses/{sha}", + "languages_url": "https://api.github.com/repos/hub4j-test-org/github-api/languages", + "stargazers_url": "https://api.github.com/repos/hub4j-test-org/github-api/stargazers", + "contributors_url": "https://api.github.com/repos/hub4j-test-org/github-api/contributors", + "subscribers_url": "https://api.github.com/repos/hub4j-test-org/github-api/subscribers", + "subscription_url": "https://api.github.com/repos/hub4j-test-org/github-api/subscription", + "commits_url": "https://api.github.com/repos/hub4j-test-org/github-api/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/hub4j-test-org/github-api/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/github-api/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/hub4j-test-org/github-api/contents/{+path}", + "compare_url": "https://api.github.com/repos/hub4j-test-org/github-api/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/hub4j-test-org/github-api/merges", + "archive_url": "https://api.github.com/repos/hub4j-test-org/github-api/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/hub4j-test-org/github-api/downloads", + "issues_url": "https://api.github.com/repos/hub4j-test-org/github-api/issues{/number}", + "pulls_url": "https://api.github.com/repos/hub4j-test-org/github-api/pulls{/number}", + "milestones_url": "https://api.github.com/repos/hub4j-test-org/github-api/milestones{/number}", + "notifications_url": "https://api.github.com/repos/hub4j-test-org/github-api/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/hub4j-test-org/github-api/labels{/name}", + "releases_url": "https://api.github.com/repos/hub4j-test-org/github-api/releases{/id}", + "deployments_url": "https://api.github.com/repos/hub4j-test-org/github-api/deployments", + "created_at": "2019-09-06T23:26:04Z", + "updated_at": "2019-09-30T22:36:47Z", + "pushed_at": "2019-10-21T22:34:49Z", + "git_url": "git://github.com/hub4j-test-org/github-api.git", + "ssh_url": "git@github.com:hub4j-test-org/github-api.git", + "clone_url": "https://github.com/hub4j-test-org/github-api.git", + "svn_url": "https://github.com/hub4j-test-org/github-api", + "homepage": "http://github-api.kohsuke.org/", + "size": 11391, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Java", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "main", + "permissions": { + "admin": true, + "push": true, + "pull": true + }, + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "organization": { + "login": "hub4j-test-org", + "id": 7544739, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", + "avatar_url": "https://avatars3.githubusercontent.com/u/7544739?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/hub4j-test-org", + "html_url": "https://github.com/hub4j-test-org", + "followers_url": "https://api.github.com/users/hub4j-test-org/followers", + "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", + "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", + "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", + "repos_url": "https://api.github.com/users/hub4j-test-org/repos", + "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", + "type": "Organization", + "site_admin": false + }, + "parent": { + "id": 617210, + "node_id": "MDEwOlJlcG9zaXRvcnk2MTcyMTA=", + "name": "github-api", + "full_name": "hub4j/github-api", + "private": false, + "owner": { + "login": "hub4j", + "id": 54909825, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjU0OTA5ODI1", + "avatar_url": "https://avatars3.githubusercontent.com/u/54909825?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/hub4j", + "html_url": "https://github.com/hub4j", + "followers_url": "https://api.github.com/users/hub4j/followers", + "following_url": "https://api.github.com/users/hub4j/following{/other_user}", + "gists_url": "https://api.github.com/users/hub4j/gists{/gist_id}", + "starred_url": "https://api.github.com/users/hub4j/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/hub4j/subscriptions", + "organizations_url": "https://api.github.com/users/hub4j/orgs", + "repos_url": "https://api.github.com/users/hub4j/repos", + "events_url": "https://api.github.com/users/hub4j/events{/privacy}", + "received_events_url": "https://api.github.com/users/hub4j/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/hub4j/github-api", + "description": "Java API for GitHub", + "fork": false, + "url": "https://api.github.com/repos/hub4j/github-api", + "forks_url": "https://api.github.com/repos/hub4j/github-api/forks", + "keys_url": "https://api.github.com/repos/hub4j/github-api/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/hub4j/github-api/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/hub4j/github-api/teams", + "hooks_url": "https://api.github.com/repos/hub4j/github-api/hooks", + "issue_events_url": "https://api.github.com/repos/hub4j/github-api/issues/events{/number}", + "events_url": "https://api.github.com/repos/hub4j/github-api/events", + "assignees_url": "https://api.github.com/repos/hub4j/github-api/assignees{/user}", + "branches_url": "https://api.github.com/repos/hub4j/github-api/branches{/branch}", + "tags_url": "https://api.github.com/repos/hub4j/github-api/tags", + "blobs_url": "https://api.github.com/repos/hub4j/github-api/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/hub4j/github-api/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/hub4j/github-api/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/hub4j/github-api/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/hub4j/github-api/statuses/{sha}", + "languages_url": "https://api.github.com/repos/hub4j/github-api/languages", + "stargazers_url": "https://api.github.com/repos/hub4j/github-api/stargazers", + "contributors_url": "https://api.github.com/repos/hub4j/github-api/contributors", + "subscribers_url": "https://api.github.com/repos/hub4j/github-api/subscribers", + "subscription_url": "https://api.github.com/repos/hub4j/github-api/subscription", + "commits_url": "https://api.github.com/repos/hub4j/github-api/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/hub4j/github-api/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/hub4j/github-api/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/hub4j/github-api/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/hub4j/github-api/contents/{+path}", + "compare_url": "https://api.github.com/repos/hub4j/github-api/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/hub4j/github-api/merges", + "archive_url": "https://api.github.com/repos/hub4j/github-api/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/hub4j/github-api/downloads", + "issues_url": "https://api.github.com/repos/hub4j/github-api/issues{/number}", + "pulls_url": "https://api.github.com/repos/hub4j/github-api/pulls{/number}", + "milestones_url": "https://api.github.com/repos/hub4j/github-api/milestones{/number}", + "notifications_url": "https://api.github.com/repos/hub4j/github-api/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/hub4j/github-api/labels{/name}", + "releases_url": "https://api.github.com/repos/hub4j/github-api/releases{/id}", + "deployments_url": "https://api.github.com/repos/hub4j/github-api/deployments", + "created_at": "2010-04-19T04:13:03Z", + "updated_at": "2019-10-28T06:11:20Z", + "pushed_at": "2019-10-29T23:24:04Z", + "git_url": "git://github.com/hub4j/github-api.git", + "ssh_url": "git@github.com:hub4j/github-api.git", + "clone_url": "https://github.com/hub4j/github-api.git", + "svn_url": "https://github.com/hub4j/github-api", + "homepage": "http://github-api.kohsuke.org/", + "size": 14742, + "stargazers_count": 568, + "watchers_count": 568, + "language": "Java", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 433, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 66, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "forks": 433, + "open_issues": 66, + "watchers": 568, + "default_branch": "main" + }, + "source": { + "id": 617210, + "node_id": "MDEwOlJlcG9zaXRvcnk2MTcyMTA=", + "name": "github-api", + "full_name": "hub4j/github-api", + "private": false, + "owner": { + "login": "hub4j", + "id": 54909825, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjU0OTA5ODI1", + "avatar_url": "https://avatars3.githubusercontent.com/u/54909825?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/hub4j", + "html_url": "https://github.com/hub4j", + "followers_url": "https://api.github.com/users/hub4j/followers", + "following_url": "https://api.github.com/users/hub4j/following{/other_user}", + "gists_url": "https://api.github.com/users/hub4j/gists{/gist_id}", + "starred_url": "https://api.github.com/users/hub4j/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/hub4j/subscriptions", + "organizations_url": "https://api.github.com/users/hub4j/orgs", + "repos_url": "https://api.github.com/users/hub4j/repos", + "events_url": "https://api.github.com/users/hub4j/events{/privacy}", + "received_events_url": "https://api.github.com/users/hub4j/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/hub4j/github-api", + "description": "Java API for GitHub", + "fork": false, + "url": "https://api.github.com/repos/hub4j/github-api", + "forks_url": "https://api.github.com/repos/hub4j/github-api/forks", + "keys_url": "https://api.github.com/repos/hub4j/github-api/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/hub4j/github-api/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/hub4j/github-api/teams", + "hooks_url": "https://api.github.com/repos/hub4j/github-api/hooks", + "issue_events_url": "https://api.github.com/repos/hub4j/github-api/issues/events{/number}", + "events_url": "https://api.github.com/repos/hub4j/github-api/events", + "assignees_url": "https://api.github.com/repos/hub4j/github-api/assignees{/user}", + "branches_url": "https://api.github.com/repos/hub4j/github-api/branches{/branch}", + "tags_url": "https://api.github.com/repos/hub4j/github-api/tags", + "blobs_url": "https://api.github.com/repos/hub4j/github-api/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/hub4j/github-api/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/hub4j/github-api/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/hub4j/github-api/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/hub4j/github-api/statuses/{sha}", + "languages_url": "https://api.github.com/repos/hub4j/github-api/languages", + "stargazers_url": "https://api.github.com/repos/hub4j/github-api/stargazers", + "contributors_url": "https://api.github.com/repos/hub4j/github-api/contributors", + "subscribers_url": "https://api.github.com/repos/hub4j/github-api/subscribers", + "subscription_url": "https://api.github.com/repos/hub4j/github-api/subscription", + "commits_url": "https://api.github.com/repos/hub4j/github-api/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/hub4j/github-api/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/hub4j/github-api/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/hub4j/github-api/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/hub4j/github-api/contents/{+path}", + "compare_url": "https://api.github.com/repos/hub4j/github-api/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/hub4j/github-api/merges", + "archive_url": "https://api.github.com/repos/hub4j/github-api/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/hub4j/github-api/downloads", + "issues_url": "https://api.github.com/repos/hub4j/github-api/issues{/number}", + "pulls_url": "https://api.github.com/repos/hub4j/github-api/pulls{/number}", + "milestones_url": "https://api.github.com/repos/hub4j/github-api/milestones{/number}", + "notifications_url": "https://api.github.com/repos/hub4j/github-api/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/hub4j/github-api/labels{/name}", + "releases_url": "https://api.github.com/repos/hub4j/github-api/releases{/id}", + "deployments_url": "https://api.github.com/repos/hub4j/github-api/deployments", + "created_at": "2010-04-19T04:13:03Z", + "updated_at": "2019-10-28T06:11:20Z", + "pushed_at": "2019-10-29T23:24:04Z", + "git_url": "git://github.com/hub4j/github-api.git", + "ssh_url": "git@github.com:hub4j/github-api.git", + "clone_url": "https://github.com/hub4j/github-api.git", + "svn_url": "https://github.com/hub4j/github-api", + "homepage": "http://github-api.kohsuke.org/", + "size": 14742, + "stargazers_count": 568, + "watchers_count": 568, + "language": "Java", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 433, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 66, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "forks": 433, + "open_issues": 66, + "watchers": 568, + "default_branch": "main" + }, + "network_count": 433, + "subscribers_count": 0 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/3-r_h_g_invitations.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/3-r_h_g_invitations.json new file mode 100644 index 0000000000..ce66275476 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/3-r_h_g_invitations.json @@ -0,0 +1,55 @@ +[ + { + "id": 1, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "repository": { + "id": 206888201, + "node_id": "MDEwOlJlcG9zaXRvcnkyMDY4ODgyMDE=", + "name": "github-api", + "full_name": "hub4j-test-org/github-api", + "private": false, + "owner": { + "login": "hub4j-test-org", + "id": 7544739, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", + "avatar_url": "https://avatars3.githubusercontent.com/u/7544739?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/hub4j-test-org", + "html_url": "https://github.com/hub4j-test-org", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/hub4j-test-org/github-api", + "description": "Tricky", + "fork": true, + "url": "https://api.github.com/repos/hub4j-test-org/github-api" + }, + "invitee": { + "login": "octocat-invitee", + "id": 2, + "node_id": "MDQ6VXNlcjI=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat-invitee", + "html_url": "https://github.com/octocat-invitee", + "type": "User", + "site_admin": false + }, + "inviter": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "type": "User", + "site_admin": false + }, + "permissions": "write", + "created_at": "2016-06-13T14:52:50Z", + "expired": false, + "url": "https://api.github.com/repos/hub4j-test-org/github-api/invitations/1", + "html_url": "https://github.com/hub4j-test-org/github-api/invitations" + } +] diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/4-user.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/4-user.json new file mode 100644 index 0000000000..86985ddbdd --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/__files/4-user.json @@ -0,0 +1,36 @@ +{ + "login": "yrodiere", + "id": 412878, + "node_id": "MDQ6VXNlcjQxMjg3OA==", + "avatar_url": "https://avatars.githubusercontent.com/u/412878?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/yrodiere", + "html_url": "https://github.com/yrodiere", + "followers_url": "https://api.github.com/users/yrodiere/followers", + "following_url": "https://api.github.com/users/yrodiere/following{/other_user}", + "gists_url": "https://api.github.com/users/yrodiere/gists{/gist_id}", + "starred_url": "https://api.github.com/users/yrodiere/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/yrodiere/subscriptions", + "organizations_url": "https://api.github.com/users/yrodiere/orgs", + "repos_url": "https://api.github.com/users/yrodiere/repos", + "events_url": "https://api.github.com/users/yrodiere/events{/privacy}", + "received_events_url": "https://api.github.com/users/yrodiere/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false, + "name": "Yoann Rodière", + "company": null, + "blog": "", + "location": null, + "email": "yoann@hibernate.org", + "hireable": null, + "bio": null, + "twitter_username": null, + "notification_email": "yoann@hibernate.org", + "public_repos": 187, + "public_gists": 19, + "followers": 104, + "following": 4, + "created_at": "2010-09-23T12:31:20Z", + "updated_at": "2026-10-26T11:39:23Z" +} diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/1-orgs_hub4j-test-org.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/1-orgs_hub4j-test-org.json new file mode 100644 index 0000000000..43c3bf4d94 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/1-orgs_hub4j-test-org.json @@ -0,0 +1,28 @@ +{ + "id": "a1b2c3d4-0001-0001-0001-000000000001", + "name": "orgs_hub4j-test-org", + "request": { + "url": "/orgs/hub4j-test-org", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "1-orgs_hub4j-test-org.json", + "headers": { + "Content-Type": "application/json; charset=utf-8", + "Server": "GitHub.com", + "Status": "200 OK", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4999", + "X-RateLimit-Reset": "1572397284" + } + }, + "uuid": "a1b2c3d4-0001-0001-0001-000000000001", + "persistent": true, + "insertionIndex": 1 +} diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/2-r_h_github-api.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/2-r_h_github-api.json new file mode 100644 index 0000000000..6a306e6263 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/2-r_h_github-api.json @@ -0,0 +1,28 @@ +{ + "id": "a1b2c3d4-0002-0002-0002-000000000002", + "name": "repos_hub4j-test-org_github-api", + "request": { + "url": "/repos/hub4j-test-org/github-api", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "2-r_h_github-api.json", + "headers": { + "Content-Type": "application/json; charset=utf-8", + "Server": "GitHub.com", + "Status": "200 OK", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4998", + "X-RateLimit-Reset": "1572397284" + } + }, + "uuid": "a1b2c3d4-0002-0002-0002-000000000002", + "persistent": true, + "insertionIndex": 2 +} diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/3-r_h_g_invitations.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/3-r_h_g_invitations.json new file mode 100644 index 0000000000..eca046a91f --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/3-r_h_g_invitations.json @@ -0,0 +1,28 @@ +{ + "id": "a1b2c3d4-0003-0003-0003-000000000003", + "name": "repos_hub4j-test-org_github-api_invitations", + "request": { + "url": "/repos/hub4j-test-org/github-api/invitations", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "3-r_h_g_invitations.json", + "headers": { + "Content-Type": "application/json; charset=utf-8", + "Server": "GitHub.com", + "Status": "200 OK", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4997", + "X-RateLimit-Reset": "1572397284" + } + }, + "uuid": "a1b2c3d4-0003-0003-0003-000000000003", + "persistent": true, + "insertionIndex": 3 +} diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/4-user.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/4-user.json new file mode 100644 index 0000000000..2275fcc459 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testListInvitations/mappings/4-user.json @@ -0,0 +1,49 @@ +{ + "id": "c5a9a219-7f13-4459-94c3-faa67d3803e2", + "name": "user", + "request": { + "url": "/user", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "4-user.json", + "headers": { + "Date": "Fri, 30 Oct 2026 13:52:34 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "W/\"12918be026567debe49fad011c00cba55426ef532aec0a1439d528dd246653ec\"", + "Last-Modified": "Mon, 26 Oct 2026 11:39:23 GMT", + "X-OAuth-Scopes": "repo", + "X-Accepted-OAuth-Scopes": "", + "github-authentication-token-expiration": "2026-11-06 13:50:38 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset, Warning", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4999", + "X-RateLimit-Reset": "1793371954", + "X-RateLimit-Used": "1", + "X-RateLimit-Resource": "core", + "X-GitHub-Request-Id": "A490:1E8157:D2D050:130F4CD:6AE4A122", + "x-github-edge-region": "fra" + } + }, + "uuid": "c5a9a219-7f13-4459-94c3-faa67d3803e2", + "persistent": true, + "insertionIndex": 4 +} From 08ecf77ed7306a653f64ba21b8c07d5965ca79f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 2 Nov 2026 11:10:01 +0000 Subject: [PATCH 2/2] Add tests for GHInvitation accept() and decline() Cover the accept and decline methods with tests that verify the invitation disappears and the collaborator status changes after accepting or declining. WireMock replay files need to be recorded. --- .../org/kohsuke/github/GHInvitationTest.java | 38 ++++++ .../testAcceptInvitation/__files/1-user.json | 36 ++++++ .../__files/2-u_r_invitations.json | 121 ++++++++++++++++++ .../testAcceptInvitation/mappings/1-user.json | 49 +++++++ .../mappings/2-u_r_invitations.json | 51 ++++++++ .../mappings/3-u_r_i_1.json | 54 ++++++++ .../mappings/4-u_r_invitations.json | 50 ++++++++ .../testDeclineInvitation/__files/1-user.json | 36 ++++++ .../__files/2-u_r_invitations.json | 121 ++++++++++++++++++ .../mappings/1-user.json | 49 +++++++ .../mappings/2-u_r_invitations.json | 51 ++++++++ .../mappings/3-u_r_i_1.json | 44 +++++++ .../mappings/4-u_r_invitations.json | 50 ++++++++ 13 files changed, 750 insertions(+) create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/__files/1-user.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/__files/2-u_r_invitations.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/1-user.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/2-u_r_invitations.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/3-u_r_i_1.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/4-u_r_invitations.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/__files/1-user.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/__files/2-u_r_invitations.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/1-user.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/2-u_r_invitations.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/3-u_r_i_1.json create mode 100644 src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/4-u_r_invitations.json diff --git a/src/test/java/org/kohsuke/github/GHInvitationTest.java b/src/test/java/org/kohsuke/github/GHInvitationTest.java index 3d58c2859b..4d905bc64e 100644 --- a/src/test/java/org/kohsuke/github/GHInvitationTest.java +++ b/src/test/java/org/kohsuke/github/GHInvitationTest.java @@ -20,6 +20,44 @@ public class GHInvitationTest extends AbstractGitHubWireMockTest { public GHInvitationTest() { } + /** + * Test accepting a repository invitation. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testAcceptInvitation() throws IOException { + List invitations = gitHub.getMyInvitations(); + assertThat(invitations, hasSize(1)); + + GHInvitation invitation = invitations.get(0); + assertThat(invitation.getId(), not(equalTo(0L))); + + invitation.accept(); + + assertThat(gitHub.getMyInvitations(), is(empty())); + } + + /** + * Test declining a repository invitation. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testDeclineInvitation() throws IOException { + List invitations = gitHub.getMyInvitations(); + assertThat(invitations, hasSize(1)); + + GHInvitation invitation = invitations.get(0); + assertThat(invitation.getId(), not(equalTo(0L))); + + invitation.decline(); + + assertThat(gitHub.getMyInvitations(), is(empty())); + } + /** * Test that listing repository invitations returns correct data for all fields. * diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/__files/1-user.json new file mode 100644 index 0000000000..efbb445f20 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/__files/1-user.json @@ -0,0 +1,36 @@ +{ + "login": "yrodiere-agent", + "id": 279624850, + "node_id": "U_kgDOEKq8kg", + "avatar_url": "https://avatars.githubusercontent.com/u/279624850?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/yrodiere-agent", + "html_url": "https://github.com/yrodiere-agent", + "followers_url": "https://api.github.com/users/yrodiere-agent/followers", + "following_url": "https://api.github.com/users/yrodiere-agent/following{/other_user}", + "gists_url": "https://api.github.com/users/yrodiere-agent/gists{/gist_id}", + "starred_url": "https://api.github.com/users/yrodiere-agent/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/yrodiere-agent/subscriptions", + "organizations_url": "https://api.github.com/users/yrodiere-agent/orgs", + "repos_url": "https://api.github.com/users/yrodiere-agent/repos", + "events_url": "https://api.github.com/users/yrodiere-agent/events{/privacy}", + "received_events_url": "https://api.github.com/users/yrodiere-agent/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false, + "name": "yrodiere-agent", + "company": null, + "blog": "", + "location": null, + "email": null, + "hireable": null, + "bio": null, + "twitter_username": null, + "notification_email": null, + "public_repos": 0, + "public_gists": 0, + "followers": 0, + "following": 0, + "created_at": "2026-04-27T06:23:17Z", + "updated_at": "2026-09-04T14:14:37Z" +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/__files/2-u_r_invitations.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/__files/2-u_r_invitations.json new file mode 100644 index 0000000000..4ad06045a2 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/__files/2-u_r_invitations.json @@ -0,0 +1,121 @@ +[ + { + "id": 1, + "node_id": "RI_kwDODFTdCc4UVBHu", + "repository": { + "id": 206888201, + "node_id": "MDEwOlJlcG9zaXRvcnkyMDY4ODgyMDE=", + "name": "github-api", + "full_name": "hub4j-test-org/github-api", + "private": false, + "owner": { + "login": "hub4j-test-org", + "id": 7544739, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", + "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/hub4j-test-org", + "html_url": "https://github.com/hub4j-test-org", + "followers_url": "https://api.github.com/users/hub4j-test-org/followers", + "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", + "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", + "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", + "repos_url": "https://api.github.com/users/hub4j-test-org/repos", + "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", + "type": "Organization", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/hub4j-test-org/github-api", + "description": "Tricky", + "fork": true, + "url": "https://api.github.com/repos/hub4j-test-org/github-api", + "forks_url": "https://api.github.com/repos/hub4j-test-org/github-api/forks", + "keys_url": "https://api.github.com/repos/hub4j-test-org/github-api/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/hub4j-test-org/github-api/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/hub4j-test-org/github-api/teams", + "hooks_url": "https://api.github.com/repos/hub4j-test-org/github-api/hooks", + "issue_events_url": "https://api.github.com/repos/hub4j-test-org/github-api/issues/events{/number}", + "events_url": "https://api.github.com/repos/hub4j-test-org/github-api/events", + "assignees_url": "https://api.github.com/repos/hub4j-test-org/github-api/assignees{/user}", + "branches_url": "https://api.github.com/repos/hub4j-test-org/github-api/branches{/branch}", + "tags_url": "https://api.github.com/repos/hub4j-test-org/github-api/tags", + "blobs_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/hub4j-test-org/github-api/statuses/{sha}", + "languages_url": "https://api.github.com/repos/hub4j-test-org/github-api/languages", + "stargazers_url": "https://api.github.com/repos/hub4j-test-org/github-api/stargazers", + "contributors_url": "https://api.github.com/repos/hub4j-test-org/github-api/contributors", + "subscribers_url": "https://api.github.com/repos/hub4j-test-org/github-api/subscribers", + "subscription_url": "https://api.github.com/repos/hub4j-test-org/github-api/subscription", + "commits_url": "https://api.github.com/repos/hub4j-test-org/github-api/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/hub4j-test-org/github-api/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/github-api/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/hub4j-test-org/github-api/contents/{+path}", + "compare_url": "https://api.github.com/repos/hub4j-test-org/github-api/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/hub4j-test-org/github-api/merges", + "archive_url": "https://api.github.com/repos/hub4j-test-org/github-api/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/hub4j-test-org/github-api/downloads", + "issues_url": "https://api.github.com/repos/hub4j-test-org/github-api/issues{/number}", + "pulls_url": "https://api.github.com/repos/hub4j-test-org/github-api/pulls{/number}", + "milestones_url": "https://api.github.com/repos/hub4j-test-org/github-api/milestones{/number}", + "notifications_url": "https://api.github.com/repos/hub4j-test-org/github-api/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/hub4j-test-org/github-api/labels{/name}", + "releases_url": "https://api.github.com/repos/hub4j-test-org/github-api/releases{/id}", + "deployments_url": "https://api.github.com/repos/hub4j-test-org/github-api/deployments" + }, + "invitee": { + "login": "yrodiere-agent", + "id": 279624850, + "node_id": "U_kgDOEKq8kg", + "avatar_url": "https://avatars.githubusercontent.com/u/279624850?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/yrodiere-agent", + "html_url": "https://github.com/yrodiere-agent", + "followers_url": "https://api.github.com/users/yrodiere-agent/followers", + "following_url": "https://api.github.com/users/yrodiere-agent/following{/other_user}", + "gists_url": "https://api.github.com/users/yrodiere-agent/gists{/gist_id}", + "starred_url": "https://api.github.com/users/yrodiere-agent/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/yrodiere-agent/subscriptions", + "organizations_url": "https://api.github.com/users/yrodiere-agent/orgs", + "repos_url": "https://api.github.com/users/yrodiere-agent/repos", + "events_url": "https://api.github.com/users/yrodiere-agent/events{/privacy}", + "received_events_url": "https://api.github.com/users/yrodiere-agent/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "inviter": { + "login": "yrodiere", + "id": 412878, + "node_id": "MDQ6VXNlcjQxMjg3OA==", + "avatar_url": "https://avatars.githubusercontent.com/u/412878?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/yrodiere", + "html_url": "https://github.com/yrodiere", + "followers_url": "https://api.github.com/users/yrodiere/followers", + "following_url": "https://api.github.com/users/yrodiere/following{/other_user}", + "gists_url": "https://api.github.com/users/yrodiere/gists{/gist_id}", + "starred_url": "https://api.github.com/users/yrodiere/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/yrodiere/subscriptions", + "organizations_url": "https://api.github.com/users/yrodiere/orgs", + "repos_url": "https://api.github.com/users/yrodiere/repos", + "events_url": "https://api.github.com/users/yrodiere/events{/privacy}", + "received_events_url": "https://api.github.com/users/yrodiere/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "permissions": "write", + "created_at": "2026-11-02T13:23:59Z", + "url": "https://api.github.com/user/repository_invitations/1", + "html_url": "https://github.com/hub4j-test-org/github-api/invitations", + "expired": false + } +] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/1-user.json new file mode 100644 index 0000000000..95112b8905 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/1-user.json @@ -0,0 +1,49 @@ +{ + "id": "924e81b8-535d-4700-9af2-9f72bad48f35", + "name": "user", + "request": { + "url": "/user", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "1-user.json", + "headers": { + "Date": "Mon, 02 Nov 2026 13:24:19 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "W/\"a55a9a5b7e53d10e84d5557c28122b6ad3ef9bc0a8eb3e3682e2975a94a25329\"", + "Last-Modified": "Fri, 04 Sep 2026 14:14:37 GMT", + "X-OAuth-Scopes": "repo", + "X-Accepted-OAuth-Scopes": "", + "github-authentication-token-expiration": "2026-11-09 13:08:42 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset, Warning", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4982", + "X-RateLimit-Reset": "1793628076", + "X-RateLimit-Used": "18", + "X-RateLimit-Resource": "core", + "X-GitHub-Request-Id": "ECA6:149D9:5F0249A:8A9795E:6AE88F03", + "x-github-edge-region": "fra" + } + }, + "uuid": "924e81b8-535d-4700-9af2-9f72bad48f35", + "persistent": true, + "insertionIndex": 1 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/2-u_r_invitations.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/2-u_r_invitations.json new file mode 100644 index 0000000000..603b72a176 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/2-u_r_invitations.json @@ -0,0 +1,51 @@ +{ + "id": "4165881b-461e-42ca-9925-707da6a93216", + "name": "user_repository_invitations", + "request": { + "url": "/user/repository_invitations", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "2-u_r_invitations.json", + "headers": { + "Date": "Mon, 02 Nov 2026 13:24:20 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "W/\"e7f79be5d115e574783b3b0bec22147486669ea9f42126f1d16540986955efa7\"", + "X-OAuth-Scopes": "repo", + "X-Accepted-OAuth-Scopes": "public_repo, repo, repo:invite", + "github-authentication-token-expiration": "2026-11-09 13:08:42 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset, Warning", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4980", + "X-RateLimit-Reset": "1793628076", + "X-RateLimit-Used": "20", + "X-RateLimit-Resource": "core", + "X-GitHub-Request-Id": "ECBC:3EFA6:61AAC6E:8E7EB25:6AE88F04", + "x-github-edge-region": "fra" + } + }, + "uuid": "4165881b-461e-42ca-9925-707da6a93216", + "persistent": true, + "scenarioName": "scenario-1-user-repository_invitations", + "requiredScenarioState": "Started", + "newScenarioState": "scenario-1-user-repository_invitations-2", + "insertionIndex": 2 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/3-u_r_i_1.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/3-u_r_i_1.json new file mode 100644 index 0000000000..c169e3f499 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/3-u_r_i_1.json @@ -0,0 +1,54 @@ +{ + "id": "f0c2739e-0217-4176-8746-6b50911423e7", + "name": "user_repository_invitations_1", + "request": { + "url": "/user/repository_invitations/1", + "method": "PATCH", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + }, + "bodyPatterns": [ + { + "equalToJson": "{}", + "ignoreArrayOrder": true, + "ignoreExtraElements": false + } + ] + }, + "response": { + "status": 204, + "headers": { + "Date": "Mon, 02 Nov 2026 13:24:21 GMT", + "X-OAuth-Scopes": "repo", + "X-Accepted-OAuth-Scopes": "public_repo, repo, repo:invite", + "github-authentication-token-expiration": "2026-11-09 13:08:42 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "Deprecation": "Tue, 10 Mar 2026 00:00:00 GMT", + "Sunset": "Fri, 10 Mar 2028 00:00:00 GMT", + "x-github-api-version-selected": "2022-11-28", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset, Warning", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Vary": "Accept-Encoding, Accept, X-Requested-With", + "Server": "github.com", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4997", + "X-RateLimit-Reset": "1793629417", + "X-RateLimit-Used": "3", + "X-RateLimit-Resource": "core", + "X-GitHub-Request-Id": "ECC2:23B4D:5EF0DEE:8AA631B:6AE88F04", + "x-github-edge-region": "fra", + "Link": "; rel=\"deprecation\"; type=\"text/html\"" + } + }, + "uuid": "f0c2739e-0217-4176-8746-6b50911423e7", + "persistent": true, + "insertionIndex": 3 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/4-u_r_invitations.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/4-u_r_invitations.json new file mode 100644 index 0000000000..9f4cd457a3 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testAcceptInvitation/mappings/4-u_r_invitations.json @@ -0,0 +1,50 @@ +{ + "id": "ee492612-d843-4bc4-83a2-ab5656687d75", + "name": "user_repository_invitations", + "request": { + "url": "/user/repository_invitations", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 200, + "body": "[]", + "headers": { + "Date": "Mon, 02 Nov 2026 13:24:21 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "\"1e2d905c5dc00df7d2cdd14168ee742552386c53ed3565f43b5e5140b51c2999\"", + "X-OAuth-Scopes": "repo", + "X-Accepted-OAuth-Scopes": "public_repo, repo, repo:invite", + "github-authentication-token-expiration": "2026-11-09 13:08:42 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset, Warning", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4996", + "X-RateLimit-Reset": "1793629417", + "X-RateLimit-Used": "4", + "X-RateLimit-Resource": "core", + "X-GitHub-Request-Id": "ECCE:171C:498A900:6A40809:6AE88F05", + "x-github-edge-region": "fra" + } + }, + "uuid": "ee492612-d843-4bc4-83a2-ab5656687d75", + "persistent": true, + "scenarioName": "scenario-1-user-repository_invitations", + "requiredScenarioState": "scenario-1-user-repository_invitations-2", + "insertionIndex": 4 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/__files/1-user.json new file mode 100644 index 0000000000..efbb445f20 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/__files/1-user.json @@ -0,0 +1,36 @@ +{ + "login": "yrodiere-agent", + "id": 279624850, + "node_id": "U_kgDOEKq8kg", + "avatar_url": "https://avatars.githubusercontent.com/u/279624850?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/yrodiere-agent", + "html_url": "https://github.com/yrodiere-agent", + "followers_url": "https://api.github.com/users/yrodiere-agent/followers", + "following_url": "https://api.github.com/users/yrodiere-agent/following{/other_user}", + "gists_url": "https://api.github.com/users/yrodiere-agent/gists{/gist_id}", + "starred_url": "https://api.github.com/users/yrodiere-agent/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/yrodiere-agent/subscriptions", + "organizations_url": "https://api.github.com/users/yrodiere-agent/orgs", + "repos_url": "https://api.github.com/users/yrodiere-agent/repos", + "events_url": "https://api.github.com/users/yrodiere-agent/events{/privacy}", + "received_events_url": "https://api.github.com/users/yrodiere-agent/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false, + "name": "yrodiere-agent", + "company": null, + "blog": "", + "location": null, + "email": null, + "hireable": null, + "bio": null, + "twitter_username": null, + "notification_email": null, + "public_repos": 0, + "public_gists": 0, + "followers": 0, + "following": 0, + "created_at": "2026-04-27T06:23:17Z", + "updated_at": "2026-09-04T14:14:37Z" +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/__files/2-u_r_invitations.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/__files/2-u_r_invitations.json new file mode 100644 index 0000000000..768049cc58 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/__files/2-u_r_invitations.json @@ -0,0 +1,121 @@ +[ + { + "id": 1, + "node_id": "RI_kwDODFTdCc4UVA3Y", + "repository": { + "id": 206888201, + "node_id": "MDEwOlJlcG9zaXRvcnkyMDY4ODgyMDE=", + "name": "github-api", + "full_name": "hub4j-test-org/github-api", + "private": false, + "owner": { + "login": "hub4j-test-org", + "id": 7544739, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", + "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/hub4j-test-org", + "html_url": "https://github.com/hub4j-test-org", + "followers_url": "https://api.github.com/users/hub4j-test-org/followers", + "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", + "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", + "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", + "repos_url": "https://api.github.com/users/hub4j-test-org/repos", + "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", + "type": "Organization", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/hub4j-test-org/github-api", + "description": "Tricky", + "fork": true, + "url": "https://api.github.com/repos/hub4j-test-org/github-api", + "forks_url": "https://api.github.com/repos/hub4j-test-org/github-api/forks", + "keys_url": "https://api.github.com/repos/hub4j-test-org/github-api/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/hub4j-test-org/github-api/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/hub4j-test-org/github-api/teams", + "hooks_url": "https://api.github.com/repos/hub4j-test-org/github-api/hooks", + "issue_events_url": "https://api.github.com/repos/hub4j-test-org/github-api/issues/events{/number}", + "events_url": "https://api.github.com/repos/hub4j-test-org/github-api/events", + "assignees_url": "https://api.github.com/repos/hub4j-test-org/github-api/assignees{/user}", + "branches_url": "https://api.github.com/repos/hub4j-test-org/github-api/branches{/branch}", + "tags_url": "https://api.github.com/repos/hub4j-test-org/github-api/tags", + "blobs_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/hub4j-test-org/github-api/statuses/{sha}", + "languages_url": "https://api.github.com/repos/hub4j-test-org/github-api/languages", + "stargazers_url": "https://api.github.com/repos/hub4j-test-org/github-api/stargazers", + "contributors_url": "https://api.github.com/repos/hub4j-test-org/github-api/contributors", + "subscribers_url": "https://api.github.com/repos/hub4j-test-org/github-api/subscribers", + "subscription_url": "https://api.github.com/repos/hub4j-test-org/github-api/subscription", + "commits_url": "https://api.github.com/repos/hub4j-test-org/github-api/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/hub4j-test-org/github-api/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/hub4j-test-org/github-api/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/github-api/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/hub4j-test-org/github-api/contents/{+path}", + "compare_url": "https://api.github.com/repos/hub4j-test-org/github-api/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/hub4j-test-org/github-api/merges", + "archive_url": "https://api.github.com/repos/hub4j-test-org/github-api/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/hub4j-test-org/github-api/downloads", + "issues_url": "https://api.github.com/repos/hub4j-test-org/github-api/issues{/number}", + "pulls_url": "https://api.github.com/repos/hub4j-test-org/github-api/pulls{/number}", + "milestones_url": "https://api.github.com/repos/hub4j-test-org/github-api/milestones{/number}", + "notifications_url": "https://api.github.com/repos/hub4j-test-org/github-api/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/hub4j-test-org/github-api/labels{/name}", + "releases_url": "https://api.github.com/repos/hub4j-test-org/github-api/releases{/id}", + "deployments_url": "https://api.github.com/repos/hub4j-test-org/github-api/deployments" + }, + "invitee": { + "login": "yrodiere-agent", + "id": 279624850, + "node_id": "U_kgDOEKq8kg", + "avatar_url": "https://avatars.githubusercontent.com/u/279624850?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/yrodiere-agent", + "html_url": "https://github.com/yrodiere-agent", + "followers_url": "https://api.github.com/users/yrodiere-agent/followers", + "following_url": "https://api.github.com/users/yrodiere-agent/following{/other_user}", + "gists_url": "https://api.github.com/users/yrodiere-agent/gists{/gist_id}", + "starred_url": "https://api.github.com/users/yrodiere-agent/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/yrodiere-agent/subscriptions", + "organizations_url": "https://api.github.com/users/yrodiere-agent/orgs", + "repos_url": "https://api.github.com/users/yrodiere-agent/repos", + "events_url": "https://api.github.com/users/yrodiere-agent/events{/privacy}", + "received_events_url": "https://api.github.com/users/yrodiere-agent/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "inviter": { + "login": "yrodiere", + "id": 412878, + "node_id": "MDQ6VXNlcjQxMjg3OA==", + "avatar_url": "https://avatars.githubusercontent.com/u/412878?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/yrodiere", + "html_url": "https://github.com/yrodiere", + "followers_url": "https://api.github.com/users/yrodiere/followers", + "following_url": "https://api.github.com/users/yrodiere/following{/other_user}", + "gists_url": "https://api.github.com/users/yrodiere/gists{/gist_id}", + "starred_url": "https://api.github.com/users/yrodiere/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/yrodiere/subscriptions", + "organizations_url": "https://api.github.com/users/yrodiere/orgs", + "repos_url": "https://api.github.com/users/yrodiere/repos", + "events_url": "https://api.github.com/users/yrodiere/events{/privacy}", + "received_events_url": "https://api.github.com/users/yrodiere/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "permissions": "write", + "created_at": "2026-11-02T13:18:49Z", + "url": "https://api.github.com/user/repository_invitations/1", + "html_url": "https://github.com/hub4j-test-org/github-api/invitations", + "expired": false + } +] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/1-user.json new file mode 100644 index 0000000000..8b874e839a --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/1-user.json @@ -0,0 +1,49 @@ +{ + "id": "e2422524-0195-4165-8291-39650585f807", + "name": "user", + "request": { + "url": "/user", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "1-user.json", + "headers": { + "Date": "Mon, 02 Nov 2026 13:23:36 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "W/\"a55a9a5b7e53d10e84d5557c28122b6ad3ef9bc0a8eb3e3682e2975a94a25329\"", + "Last-Modified": "Fri, 04 Sep 2026 14:14:37 GMT", + "X-OAuth-Scopes": "repo", + "X-Accepted-OAuth-Scopes": "", + "github-authentication-token-expiration": "2026-11-09 13:08:42 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset, Warning", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4985", + "X-RateLimit-Reset": "1793628076", + "X-RateLimit-Used": "15", + "X-RateLimit-Resource": "core", + "X-GitHub-Request-Id": "E6A0:360B:63D3667:91AD4DA:6AE88ED8", + "x-github-edge-region": "fra" + } + }, + "uuid": "e2422524-0195-4165-8291-39650585f807", + "persistent": true, + "insertionIndex": 1 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/2-u_r_invitations.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/2-u_r_invitations.json new file mode 100644 index 0000000000..25ffdd805f --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/2-u_r_invitations.json @@ -0,0 +1,51 @@ +{ + "id": "69b72560-deb9-417f-bff0-6c4b7192e02c", + "name": "user_repository_invitations", + "request": { + "url": "/user/repository_invitations", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "2-u_r_invitations.json", + "headers": { + "Date": "Mon, 02 Nov 2026 13:23:37 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "W/\"309916eb6cbb62599b1600511e3b137a881677c87c03ae487124b77258e21b66\"", + "X-OAuth-Scopes": "repo", + "X-Accepted-OAuth-Scopes": "public_repo, repo, repo:invite", + "github-authentication-token-expiration": "2026-11-09 13:08:42 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset, Warning", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4983", + "X-RateLimit-Reset": "1793628076", + "X-RateLimit-Used": "17", + "X-RateLimit-Resource": "core", + "X-GitHub-Request-Id": "E6BC:16A0A7:622003C:8F19B9C:6AE88ED9", + "x-github-edge-region": "fra" + } + }, + "uuid": "69b72560-deb9-417f-bff0-6c4b7192e02c", + "persistent": true, + "scenarioName": "scenario-1-user-repository_invitations", + "requiredScenarioState": "Started", + "newScenarioState": "scenario-1-user-repository_invitations-2", + "insertionIndex": 2 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/3-u_r_i_1.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/3-u_r_i_1.json new file mode 100644 index 0000000000..788f78842b --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/3-u_r_i_1.json @@ -0,0 +1,44 @@ +{ + "id": "c77bcdbe-3bdb-4ea6-8079-f1bbada63aeb", + "name": "user_repository_invitations_1", + "request": { + "url": "/user/repository_invitations/1", + "method": "DELETE", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 204, + "headers": { + "Date": "Mon, 02 Nov 2026 13:23:38 GMT", + "X-OAuth-Scopes": "repo", + "X-Accepted-OAuth-Scopes": "public_repo, repo, repo:invite", + "github-authentication-token-expiration": "2026-11-09 13:08:42 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset, Warning", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Vary": "Accept-Encoding, Accept, X-Requested-With", + "Server": "github.com", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4999", + "X-RateLimit-Reset": "1793629417", + "X-RateLimit-Used": "1", + "X-RateLimit-Resource": "core", + "X-GitHub-Request-Id": "E6C8:164823:5ED35F6:8A08431:6AE88ED9", + "x-github-edge-region": "fra" + } + }, + "uuid": "c77bcdbe-3bdb-4ea6-8079-f1bbada63aeb", + "persistent": true, + "insertionIndex": 3 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/4-u_r_invitations.json b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/4-u_r_invitations.json new file mode 100644 index 0000000000..f3528244ba --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHInvitationTest/wiremock/testDeclineInvitation/mappings/4-u_r_invitations.json @@ -0,0 +1,50 @@ +{ + "id": "42382b66-db20-48c0-9c81-d0d10e32d2cc", + "name": "user_repository_invitations", + "request": { + "url": "/user/repository_invitations", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github+json" + } + } + }, + "response": { + "status": 200, + "body": "[]", + "headers": { + "Date": "Mon, 02 Nov 2026 13:23:38 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "\"1e2d905c5dc00df7d2cdd14168ee742552386c53ed3565f43b5e5140b51c2999\"", + "X-OAuth-Scopes": "repo", + "X-Accepted-OAuth-Scopes": "public_repo, repo, repo:invite", + "github-authentication-token-expiration": "2026-11-09 13:08:42 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset, Warning", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4998", + "X-RateLimit-Reset": "1793629417", + "X-RateLimit-Used": "2", + "X-RateLimit-Resource": "core", + "X-GitHub-Request-Id": "E6CC:149D9:5EDFD40:8A66063:6AE88EDA", + "x-github-edge-region": "fra" + } + }, + "uuid": "42382b66-db20-48c0-9c81-d0d10e32d2cc", + "persistent": true, + "scenarioName": "scenario-1-user-repository_invitations", + "requiredScenarioState": "scenario-1-user-repository_invitations-2", + "insertionIndex": 4 +} \ No newline at end of file