From 948eccfd0016bf0b2b4ceb4c31d85ab7bc596c29 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Fri, 24 Oct 2025 10:15:37 -0400 Subject: [PATCH 1/3] feat: admin: add invite client and tests --- admin_invite.go | 151 +++++++++++++++++++++++++++++++++++++++ admin_invite_test.go | 163 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 314 insertions(+) create mode 100644 admin_invite.go create mode 100644 admin_invite_test.go diff --git a/admin_invite.go b/admin_invite.go new file mode 100644 index 000000000..ba2a078ec --- /dev/null +++ b/admin_invite.go @@ -0,0 +1,151 @@ +package openai + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +const ( + adminInvitesSuffix = "/organization/invites" +) + +var ( + // adminInviteRoles is a list of valid roles for an Admin Invite. + adminInviteRoles = []string{"owner", "member"} +) + +// AdminInvite represents an Admin Invite. +type AdminInvite struct { + Object string `json:"object"` + ID string `json:"id"` + Email string `json:"email"` + Role string `json:"role"` + Status string `json:"status"` + InvitedAt int64 `json:"invited_at"` + ExpiresAt int64 `json:"expires_at"` + AcceptedAt int64 `json:"accepted_at"` + Projects []AdminInviteProject `json:"projects"` + + httpHeader +} + +// AdminInviteProject represents a project associated with an Admin Invite. +type AdminInviteProject struct { + ID string `json:"id"` + Role string `json:"role"` +} + +// AdminInviteList represents a list of Admin Invites. +type AdminInviteList struct { + Object string `json:"object"` + AdminInvites []AdminInvite `json:"data"` + FirstID string `json:"first_id"` + LastID string `json:"last_id"` + HasMore bool `json:"has_more"` + + httpHeader +} + +// AdminInviteDeleteResponse represents the response from deleting an Admin Invite. +type AdminInviteDeleteResponse struct { + ID string `json:"id"` + Object string `json:"object"` + Deleted bool `json:"deleted"` + + httpHeader +} + +// ListAdminInvites lists Admin Invites associated with the organization. +func (c *Client) ListAdminInvites( + ctx context.Context, + limit *int, + after *string, +) (response AdminInviteList, err error) { + urlValues := url.Values{} + if limit != nil { + urlValues.Add("limit", fmt.Sprintf("%d", *limit)) + } + if after != nil { + urlValues.Add("after", *after) + } + + encodedValues := "" + if len(urlValues) > 0 { + encodedValues = "?" + urlValues.Encode() + } + + urlSuffix := adminInvitesSuffix + encodedValues + req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix)) + if err != nil { + return + } + + err = c.sendRequest(req, &response) + return +} + +// CreateAdminInvite creates a new Admin Invite. +func (c *Client) CreateAdminInvite( + ctx context.Context, + email string, + role string, + projects *[]AdminInviteProject, +) (response AdminInvite, err error) { + // Validate the role. + if !containsSubstr(adminInviteRoles, role) { + return response, fmt.Errorf("invalid admin role: %s", role) + } + + // Create the request object. + request := struct { + Email string `json:"email"` + Role string `json:"role"` + Projects *[]AdminInviteProject `json:"projects,omitempty"` + }{ + Email: email, + Role: role, + Projects: projects, + } + + urlSuffix := adminInvitesSuffix + req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(urlSuffix), withBody(request)) + if err != nil { + return + } + + err = c.sendRequest(req, &response) + + return +} + +// RetrieveAdminInvite retrieves an Admin Invite. +func (c *Client) RetrieveAdminInvite( + ctx context.Context, + inviteID string, +) (response AdminInvite, err error) { + urlSuffix := fmt.Sprintf("%s/%s", adminInvitesSuffix, inviteID) + req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix)) + if err != nil { + return + } + + err = c.sendRequest(req, &response) + return +} + +// DeleteAdminInvite deletes an Admin Invite. +func (c *Client) DeleteAdminInvite( + ctx context.Context, + inviteID string, +) (response AdminInviteDeleteResponse, err error) { + urlSuffix := fmt.Sprintf("%s/%s", adminInvitesSuffix, inviteID) + req, err := c.newRequest(ctx, http.MethodDelete, c.fullURL(urlSuffix)) + if err != nil { + return + } + + err = c.sendRequest(req, &response) + return +} diff --git a/admin_invite_test.go b/admin_invite_test.go new file mode 100644 index 000000000..47dbccb53 --- /dev/null +++ b/admin_invite_test.go @@ -0,0 +1,163 @@ +package openai_test + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "testing" + + "github.com/sashabaranov/go-openai" + "github.com/sashabaranov/go-openai/internal/test/checks" +) + +func TestAdminInvite(t *testing.T) { + adminInviteObject := "organization.invite" + adminInviteID := "invite-abc-123" + adminInviteEmail := "invite@openai.com" + adminInviteRole := "owner" + adminInviteStatus := "pending" + + adminInviteInvitedAt := int64(1711471533) + adminInviteExpiresAt := int64(1711471533) + adminInviteAcceptedAt := int64(1711471533) + adminInviteProjects := []openai.AdminInviteProject{ + { + ID: "project-id", + Role: "owner", + }, + } + + client, server, teardown := setupOpenAITestServer() + defer teardown() + + server.RegisterHandler( + "/v1/organization/invites", + func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + resBytes, _ := json.Marshal(openai.AdminInviteList{ + Object: "list", + AdminInvites: []openai.AdminInvite{ + { + Object: adminInviteObject, + ID: adminInviteID, + Email: adminInviteEmail, + Role: adminInviteRole, + Status: adminInviteStatus, + InvitedAt: adminInviteInvitedAt, + ExpiresAt: adminInviteExpiresAt, + AcceptedAt: adminInviteAcceptedAt, + Projects: adminInviteProjects, + }, + }, + FirstID: "first_id", + LastID: "last_id", + HasMore: false, + }) + fmt.Fprintln(w, string(resBytes)) + + case http.MethodPost: + resBytes, _ := json.Marshal(openai.AdminInvite{ + Object: adminInviteObject, + ID: adminInviteID, + Email: adminInviteEmail, + Role: adminInviteRole, + Status: adminInviteStatus, + InvitedAt: adminInviteInvitedAt, + ExpiresAt: adminInviteExpiresAt, + AcceptedAt: adminInviteAcceptedAt, + Projects: adminInviteProjects, + }) + fmt.Fprintln(w, string(resBytes)) + } + }, + ) + + server.RegisterHandler( + "/v1/organization/invites/"+adminInviteID, + func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodDelete: + resBytes, _ := json.Marshal(openai.AdminInviteDeleteResponse{ + ID: adminInviteID, + Object: adminInviteObject, + Deleted: true, + }) + fmt.Fprintln(w, string(resBytes)) + + case http.MethodGet: + resBytes, _ := json.Marshal(openai.AdminInvite{ + Object: adminInviteObject, + ID: adminInviteID, + Email: adminInviteEmail, + Role: adminInviteRole, + Status: adminInviteStatus, + InvitedAt: adminInviteInvitedAt, + ExpiresAt: adminInviteExpiresAt, + AcceptedAt: adminInviteAcceptedAt, + Projects: adminInviteProjects, + }) + fmt.Fprintln(w, string(resBytes)) + } + }, + ) + + ctx := context.Background() + + t.Run("ListAdminInvites", func(t *testing.T) { + adminInvites, err := client.ListAdminInvites(ctx, nil, nil) + checks.NoError(t, err, "ListAdminInvites error") + + if len(adminInvites.AdminInvites) != 1 { + t.Fatalf("expected 1 admin invite, got %d", len(adminInvites.AdminInvites)) + } + + if adminInvites.AdminInvites[0].ID != adminInviteID { + t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvites.AdminInvites[0].ID) + } + }) + + t.Run("ListAdminInvitesFilter", func(t *testing.T) { + limit := 10 + after := "after-id" + + adminInvites, err := client.ListAdminInvites(ctx, &limit, &after) + checks.NoError(t, err, "ListAdminInvites error") + + if len(adminInvites.AdminInvites) != 1 { + t.Fatalf("expected 1 admin invite, got %d", len(adminInvites.AdminInvites)) + } + + if adminInvites.AdminInvites[0].ID != adminInviteID { + t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvites.AdminInvites[0].ID) + } + }) + + t.Run("CreateAdminInvite", func(t *testing.T) { + adminInvite, err := client.CreateAdminInvite(ctx, adminInviteEmail, adminInviteRole, &adminInviteProjects) + checks.NoError(t, err, "CreateAdminInvite error") + + if adminInvite.ID != adminInviteID { + t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvite.ID) + } + }) + + t.Run("RetrieveAdminInvite", func(t *testing.T) { + adminInvite, err := client.RetrieveAdminInvite(ctx, adminInviteID) + checks.NoError(t, err, "RetrieveAdminInvite error") + + if adminInvite.ID != adminInviteID { + t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvite.ID) + } + }) + + t.Run("DeleteAdminInvite", func(t *testing.T) { + adminInviteDeleteResponse, err := client.DeleteAdminInvite(ctx, adminInviteID) + checks.NoError(t, err, "DeleteAdminInvite error") + + if !adminInviteDeleteResponse.Deleted { + t.Errorf("expected admin invite to be deleted, got not deleted") + } + }) +} From d0c98f896d024c121da79e24861170f9a4fb91ae Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Fri, 24 Oct 2025 10:26:29 -0400 Subject: [PATCH 2/3] Added additional test cases --- admin_invite_test.go | 57 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/admin_invite_test.go b/admin_invite_test.go index 47dbccb53..62f37ee82 100644 --- a/admin_invite_test.go +++ b/admin_invite_test.go @@ -118,6 +118,36 @@ func TestAdminInvite(t *testing.T) { } }) + t.Run("ListAdminInvitesWithOnlyLimit", func(t *testing.T) { + limit := 5 + + adminInvites, err := client.ListAdminInvites(ctx, &limit, nil) + checks.NoError(t, err, "ListAdminInvites error") + + if len(adminInvites.AdminInvites) != 1 { + t.Fatalf("expected 1 admin invite, got %d", len(adminInvites.AdminInvites)) + } + + if adminInvites.AdminInvites[0].ID != adminInviteID { + t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvites.AdminInvites[0].ID) + } + }) + + t.Run("ListAdminInvitesWithOnlyAfter", func(t *testing.T) { + after := "after-token" + + adminInvites, err := client.ListAdminInvites(ctx, nil, &after) + checks.NoError(t, err, "ListAdminInvites error") + + if len(adminInvites.AdminInvites) != 1 { + t.Fatalf("expected 1 admin invite, got %d", len(adminInvites.AdminInvites)) + } + + if adminInvites.AdminInvites[0].ID != adminInviteID { + t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvites.AdminInvites[0].ID) + } + }) + t.Run("ListAdminInvitesFilter", func(t *testing.T) { limit := 10 after := "after-id" @@ -143,6 +173,33 @@ func TestAdminInvite(t *testing.T) { } }) + t.Run("CreateAdminInviteWithoutProjects", func(t *testing.T) { + adminInvite, err := client.CreateAdminInvite(ctx, adminInviteEmail, adminInviteRole, nil) + checks.NoError(t, err, "CreateAdminInvite error") + + if adminInvite.ID != adminInviteID { + t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvite.ID) + } + }) + + t.Run("CreateAdminInviteWithMemberRole", func(t *testing.T) { + memberRole := "member" + adminInvite, err := client.CreateAdminInvite(ctx, adminInviteEmail, memberRole, &adminInviteProjects) + checks.NoError(t, err, "CreateAdminInvite error") + + if adminInvite.ID != adminInviteID { + t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvite.ID) + } + }) + + t.Run("CreateAdminInviteInvalidRole", func(t *testing.T) { + invalidRole := "invalid-role" + _, err := client.CreateAdminInvite(ctx, adminInviteEmail, invalidRole, &adminInviteProjects) + if err == nil { + t.Fatal("expected error for invalid role, got nil") + } + }) + t.Run("RetrieveAdminInvite", func(t *testing.T) { adminInvite, err := client.RetrieveAdminInvite(ctx, adminInviteID) checks.NoError(t, err, "RetrieveAdminInvite error") From 215ba634de42917d0017e98e9a1b4e31f6085b1a Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Fri, 24 Oct 2025 13:05:16 -0400 Subject: [PATCH 3/3] Refactored tests for lint validation --- admin_invite_test.go | 324 +++++++++++++++++++++++-------------------- 1 file changed, 177 insertions(+), 147 deletions(-) diff --git a/admin_invite_test.go b/admin_invite_test.go index 62f37ee82..6435bcb68 100644 --- a/admin_invite_test.go +++ b/admin_invite_test.go @@ -8,213 +8,243 @@ import ( "testing" "github.com/sashabaranov/go-openai" + "github.com/sashabaranov/go-openai/internal/test" "github.com/sashabaranov/go-openai/internal/test/checks" ) -func TestAdminInvite(t *testing.T) { - adminInviteObject := "organization.invite" - adminInviteID := "invite-abc-123" - adminInviteEmail := "invite@openai.com" - adminInviteRole := "owner" - adminInviteStatus := "pending" - - adminInviteInvitedAt := int64(1711471533) - adminInviteExpiresAt := int64(1711471533) - adminInviteAcceptedAt := int64(1711471533) - adminInviteProjects := []openai.AdminInviteProject{ - { - ID: "project-id", - Role: "owner", +type adminInviteFixture struct { + object string + inviteID string + email string + role string + memberRole string + status string + invitedAt int64 + expiresAt int64 + acceptedAt int64 + projects []openai.AdminInviteProject +} + +func newAdminInviteFixture() *adminInviteFixture { + return &adminInviteFixture{ + object: "organization.invite", + inviteID: "invite-abc-123", + email: "invite@openai.com", + role: "owner", + memberRole: "member", + status: "pending", + invitedAt: 1711471533, + expiresAt: 1711471533, + acceptedAt: 1711471533, + projects: []openai.AdminInviteProject{ + { + ID: "project-id", + Role: "owner", + }, }, } +} + +func (f *adminInviteFixture) newInvite() openai.AdminInvite { + return openai.AdminInvite{ + Object: f.object, + ID: f.inviteID, + Email: f.email, + Role: f.role, + Status: f.status, + InvitedAt: f.invitedAt, + ExpiresAt: f.expiresAt, + AcceptedAt: f.acceptedAt, + Projects: f.projects, + } +} + +func (f *adminInviteFixture) listResponse() openai.AdminInviteList { + return openai.AdminInviteList{ + Object: "list", + AdminInvites: []openai.AdminInvite{f.newInvite()}, + FirstID: "first_id", + LastID: "last_id", + HasMore: false, + } +} + +func (f *adminInviteFixture) deleteResponse() openai.AdminInviteDeleteResponse { + return openai.AdminInviteDeleteResponse{ + ID: f.inviteID, + Object: f.object, + Deleted: true, + } +} + +func (f *adminInviteFixture) projectsPointer() *[]openai.AdminInviteProject { + return &f.projects +} + +type adminInviteTestEnv struct { + ctx context.Context + client *openai.Client + fixture *adminInviteFixture +} + +func newAdminInviteTestEnv(t *testing.T) *adminInviteTestEnv { + t.Helper() client, server, teardown := setupOpenAITestServer() - defer teardown() + t.Cleanup(teardown) + fixture := newAdminInviteFixture() + registerAdminInviteHandlers(server, fixture) + + return &adminInviteTestEnv{ + ctx: context.Background(), + client: client, + fixture: fixture, + } +} + +func registerAdminInviteHandlers(server *test.ServerTest, fixture *adminInviteFixture) { server.RegisterHandler( "/v1/organization/invites", func(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: - resBytes, _ := json.Marshal(openai.AdminInviteList{ - Object: "list", - AdminInvites: []openai.AdminInvite{ - { - Object: adminInviteObject, - ID: adminInviteID, - Email: adminInviteEmail, - Role: adminInviteRole, - Status: adminInviteStatus, - InvitedAt: adminInviteInvitedAt, - ExpiresAt: adminInviteExpiresAt, - AcceptedAt: adminInviteAcceptedAt, - Projects: adminInviteProjects, - }, - }, - FirstID: "first_id", - LastID: "last_id", - HasMore: false, - }) - fmt.Fprintln(w, string(resBytes)) - + respondWithJSON(w, fixture.listResponse()) case http.MethodPost: - resBytes, _ := json.Marshal(openai.AdminInvite{ - Object: adminInviteObject, - ID: adminInviteID, - Email: adminInviteEmail, - Role: adminInviteRole, - Status: adminInviteStatus, - InvitedAt: adminInviteInvitedAt, - ExpiresAt: adminInviteExpiresAt, - AcceptedAt: adminInviteAcceptedAt, - Projects: adminInviteProjects, - }) - fmt.Fprintln(w, string(resBytes)) + respondWithJSON(w, fixture.newInvite()) } }, ) server.RegisterHandler( - "/v1/organization/invites/"+adminInviteID, + "/v1/organization/invites/"+fixture.inviteID, func(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodDelete: - resBytes, _ := json.Marshal(openai.AdminInviteDeleteResponse{ - ID: adminInviteID, - Object: adminInviteObject, - Deleted: true, - }) - fmt.Fprintln(w, string(resBytes)) - + respondWithJSON(w, fixture.deleteResponse()) case http.MethodGet: - resBytes, _ := json.Marshal(openai.AdminInvite{ - Object: adminInviteObject, - ID: adminInviteID, - Email: adminInviteEmail, - Role: adminInviteRole, - Status: adminInviteStatus, - InvitedAt: adminInviteInvitedAt, - ExpiresAt: adminInviteExpiresAt, - AcceptedAt: adminInviteAcceptedAt, - Projects: adminInviteProjects, - }) - fmt.Fprintln(w, string(resBytes)) + respondWithJSON(w, fixture.newInvite()) } }, ) +} - ctx := context.Background() +func respondWithJSON(w http.ResponseWriter, payload interface{}) { + resBytes, _ := json.Marshal(payload) + fmt.Fprintln(w, string(resBytes)) +} - t.Run("ListAdminInvites", func(t *testing.T) { - adminInvites, err := client.ListAdminInvites(ctx, nil, nil) - checks.NoError(t, err, "ListAdminInvites error") +func (e *adminInviteTestEnv) assertInviteID(t *testing.T, got string) { + t.Helper() - if len(adminInvites.AdminInvites) != 1 { - t.Fatalf("expected 1 admin invite, got %d", len(adminInvites.AdminInvites)) - } + if got != e.fixture.inviteID { + t.Errorf("expected admin invite ID %s, got %s", e.fixture.inviteID, got) + } +} - if adminInvites.AdminInvites[0].ID != adminInviteID { - t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvites.AdminInvites[0].ID) - } - }) +func (e *adminInviteTestEnv) assertSingleInviteResponse(t *testing.T, resp openai.AdminInviteList) { + t.Helper() - t.Run("ListAdminInvitesWithOnlyLimit", func(t *testing.T) { - limit := 5 + if len(resp.AdminInvites) != 1 { + t.Fatalf("expected 1 admin invite, got %d", len(resp.AdminInvites)) + } - adminInvites, err := client.ListAdminInvites(ctx, &limit, nil) - checks.NoError(t, err, "ListAdminInvites error") + e.assertInviteID(t, resp.AdminInvites[0].ID) +} - if len(adminInvites.AdminInvites) != 1 { - t.Fatalf("expected 1 admin invite, got %d", len(adminInvites.AdminInvites)) - } +func (e *adminInviteTestEnv) runListAdminInvites(t *testing.T, limit *int, after *string) { + t.Helper() - if adminInvites.AdminInvites[0].ID != adminInviteID { - t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvites.AdminInvites[0].ID) - } - }) + adminInvites, err := e.client.ListAdminInvites(e.ctx, limit, after) + checks.NoError(t, err, "ListAdminInvites error") + e.assertSingleInviteResponse(t, adminInvites) +} - t.Run("ListAdminInvitesWithOnlyAfter", func(t *testing.T) { - after := "after-token" +func TestAdminInvite_List(t *testing.T) { + env := newAdminInviteTestEnv(t) - adminInvites, err := client.ListAdminInvites(ctx, nil, &after) - checks.NoError(t, err, "ListAdminInvites error") + t.Run("WithoutFilters", func(t *testing.T) { + env.runListAdminInvites(t, nil, nil) + }) - if len(adminInvites.AdminInvites) != 1 { - t.Fatalf("expected 1 admin invite, got %d", len(adminInvites.AdminInvites)) - } + t.Run("WithOnlyLimit", func(t *testing.T) { + limit := 5 + env.runListAdminInvites(t, &limit, nil) + }) - if adminInvites.AdminInvites[0].ID != adminInviteID { - t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvites.AdminInvites[0].ID) - } + t.Run("WithOnlyAfter", func(t *testing.T) { + after := "after-token" + env.runListAdminInvites(t, nil, &after) }) - t.Run("ListAdminInvitesFilter", func(t *testing.T) { + t.Run("WithLimitAndAfter", func(t *testing.T) { limit := 10 after := "after-id" - - adminInvites, err := client.ListAdminInvites(ctx, &limit, &after) - checks.NoError(t, err, "ListAdminInvites error") - - if len(adminInvites.AdminInvites) != 1 { - t.Fatalf("expected 1 admin invite, got %d", len(adminInvites.AdminInvites)) - } - - if adminInvites.AdminInvites[0].ID != adminInviteID { - t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvites.AdminInvites[0].ID) - } + env.runListAdminInvites(t, &limit, &after) }) +} - t.Run("CreateAdminInvite", func(t *testing.T) { - adminInvite, err := client.CreateAdminInvite(ctx, adminInviteEmail, adminInviteRole, &adminInviteProjects) - checks.NoError(t, err, "CreateAdminInvite error") +func TestAdminInvite_Create(t *testing.T) { + env := newAdminInviteTestEnv(t) - if adminInvite.ID != adminInviteID { - t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvite.ID) - } + t.Run("WithProjects", func(t *testing.T) { + adminInvite, err := env.client.CreateAdminInvite(env.ctx, + env.fixture.email, + env.fixture.role, + env.fixture.projectsPointer(), + ) + checks.NoError(t, err, "CreateAdminInvite error") + env.assertInviteID(t, adminInvite.ID) }) - t.Run("CreateAdminInviteWithoutProjects", func(t *testing.T) { - adminInvite, err := client.CreateAdminInvite(ctx, adminInviteEmail, adminInviteRole, nil) + t.Run("WithoutProjects", func(t *testing.T) { + adminInvite, err := env.client.CreateAdminInvite(env.ctx, + env.fixture.email, + env.fixture.role, + nil, + ) checks.NoError(t, err, "CreateAdminInvite error") - - if adminInvite.ID != adminInviteID { - t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvite.ID) - } + env.assertInviteID(t, adminInvite.ID) }) - t.Run("CreateAdminInviteWithMemberRole", func(t *testing.T) { - memberRole := "member" - adminInvite, err := client.CreateAdminInvite(ctx, adminInviteEmail, memberRole, &adminInviteProjects) + t.Run("WithMemberRole", func(t *testing.T) { + adminInvite, err := env.client.CreateAdminInvite(env.ctx, + env.fixture.email, + env.fixture.memberRole, + env.fixture.projectsPointer(), + ) checks.NoError(t, err, "CreateAdminInvite error") - - if adminInvite.ID != adminInviteID { - t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvite.ID) - } + env.assertInviteID(t, adminInvite.ID) }) - t.Run("CreateAdminInviteInvalidRole", func(t *testing.T) { + t.Run("InvalidRole", func(t *testing.T) { invalidRole := "invalid-role" - _, err := client.CreateAdminInvite(ctx, adminInviteEmail, invalidRole, &adminInviteProjects) + _, err := env.client.CreateAdminInvite(env.ctx, + env.fixture.email, + invalidRole, + env.fixture.projectsPointer(), + ) if err == nil { t.Fatal("expected error for invalid role, got nil") } }) +} - t.Run("RetrieveAdminInvite", func(t *testing.T) { - adminInvite, err := client.RetrieveAdminInvite(ctx, adminInviteID) - checks.NoError(t, err, "RetrieveAdminInvite error") +func TestAdminInvite_Retrieve(t *testing.T) { + env := newAdminInviteTestEnv(t) - if adminInvite.ID != adminInviteID { - t.Errorf("expected admin invite ID %s, got %s", adminInviteID, adminInvite.ID) - } - }) + adminInvite, err := env.client.RetrieveAdminInvite(env.ctx, env.fixture.inviteID) + checks.NoError(t, err, "RetrieveAdminInvite error") + env.assertInviteID(t, adminInvite.ID) +} - t.Run("DeleteAdminInvite", func(t *testing.T) { - adminInviteDeleteResponse, err := client.DeleteAdminInvite(ctx, adminInviteID) - checks.NoError(t, err, "DeleteAdminInvite error") +func TestAdminInvite_Delete(t *testing.T) { + env := newAdminInviteTestEnv(t) - if !adminInviteDeleteResponse.Deleted { - t.Errorf("expected admin invite to be deleted, got not deleted") - } - }) + adminInviteDeleteResponse, err := env.client.DeleteAdminInvite(env.ctx, env.fixture.inviteID) + checks.NoError(t, err, "DeleteAdminInvite error") + + if !adminInviteDeleteResponse.Deleted { + t.Errorf("expected admin invite to be deleted, got not deleted") + } }