gogcli/internal/cmd/admin_test.go
2026-03-09 00:45:34 +00:00

173 lines
5.3 KiB
Go

package cmd
import (
"context"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"strings"
"testing"
admin "google.golang.org/api/admin/directory/v1"
"google.golang.org/api/option"
)
func TestRequireAdminAccount_ConsumerBlocked(t *testing.T) {
account, err := requireAdminAccount(&RootFlags{Account: "user@gmail.com"})
if err == nil {
t.Fatal("expected error")
}
if account != "" {
t.Fatalf("expected empty account, got %q", account)
}
if !strings.Contains(err.Error(), "Google Workspace account") {
t.Fatalf("unexpected error: %v", err)
}
}
func TestWrapAdminDirectoryError_MapsPermissions(t *testing.T) {
err := wrapAdminDirectoryError(errors.New("insufficient authentication scopes"), "svc@example.com")
if err == nil || !strings.Contains(err.Error(), "admin.directory.group.member") {
t.Fatalf("unexpected error: %v", err)
}
}
func TestAdminUsersCreate_ValidationErrors(t *testing.T) {
ctx := context.Background()
flags := &RootFlags{Account: "svc@example.com"}
tests := []struct {
name string
cmd AdminUsersCreateCmd
want string
}{
{name: "missing email", cmd: AdminUsersCreateCmd{GivenName: "Ada", FamilyName: "Lovelace", Password: "pw"}, want: "email required"},
{name: "missing given", cmd: AdminUsersCreateCmd{Email: "ada@example.com", FamilyName: "Lovelace", Password: "pw"}, want: "--given required"},
{name: "missing family", cmd: AdminUsersCreateCmd{Email: "ada@example.com", GivenName: "Ada", Password: "pw"}, want: "--family required"},
{name: "missing password", cmd: AdminUsersCreateCmd{Email: "ada@example.com", GivenName: "Ada", FamilyName: "Lovelace"}, want: "--password required"},
{name: "admin unsupported", cmd: AdminUsersCreateCmd{Email: "ada@example.com", GivenName: "Ada", FamilyName: "Lovelace", Password: "pw", Admin: true}, want: "--admin is not supported"},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
if err := tc.cmd.Run(ctx, flags); err == nil || !strings.Contains(err.Error(), tc.want) {
t.Fatalf("Run() error = %v, want substring %q", err, tc.want)
}
})
}
}
func TestAdminUsersList_JSON_AllowsNilName(t *testing.T) {
origNew := newAdminDirectoryService
t.Cleanup(func() { newAdminDirectoryService = origNew })
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !(r.Method == http.MethodGet && strings.Contains(r.URL.Path, "/users")) {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"users": []map[string]any{
{
"primaryEmail": "ada@example.com",
"suspended": false,
"isAdmin": true,
},
},
})
}))
defer srv.Close()
svc, err := admin.NewService(context.Background(),
option.WithoutAuthentication(),
option.WithHTTPClient(srv.Client()),
option.WithEndpoint(srv.URL+"/"),
)
if err != nil {
t.Fatalf("NewService: %v", err)
}
newAdminDirectoryService = func(context.Context, string) (*admin.Service, error) { return svc, nil }
ctx := newCmdJSONContext(t)
out := captureStdout(t, func() {
if err := (&AdminUsersListCmd{Domain: "example.com"}).Run(ctx, &RootFlags{Account: "svc@example.com"}); err != nil {
t.Fatalf("Run: %v", err)
}
})
var parsed struct {
Users []struct {
Email string `json:"email"`
Name string `json:"name"`
Admin bool `json:"admin"`
} `json:"users"`
}
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if len(parsed.Users) != 1 || parsed.Users[0].Email != "ada@example.com" || parsed.Users[0].Name != "" || !parsed.Users[0].Admin {
t.Fatalf("unexpected users: %#v", parsed.Users)
}
}
func TestAdminGroupsMembersAdd_JSON(t *testing.T) {
origNew := newAdminDirectoryService
t.Cleanup(func() { newAdminDirectoryService = origNew })
var gotRole string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !(r.Method == http.MethodPost && strings.Contains(r.URL.Path, "/members")) {
http.NotFound(w, r)
return
}
var body map[string]any
_ = json.NewDecoder(r.Body).Decode(&body)
gotRole, _ = body["role"].(string)
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"email": "dev@example.com",
"role": gotRole,
})
}))
defer srv.Close()
svc, err := admin.NewService(context.Background(),
option.WithoutAuthentication(),
option.WithHTTPClient(srv.Client()),
option.WithEndpoint(srv.URL+"/"),
)
if err != nil {
t.Fatalf("NewService: %v", err)
}
newAdminDirectoryService = func(context.Context, string) (*admin.Service, error) { return svc, nil }
ctx := newCmdJSONContext(t)
out := captureStdout(t, func() {
if err := (&AdminGroupsMembersAddCmd{
GroupEmail: "eng@example.com",
MemberEmail: "dev@example.com",
Role: "owner",
}).Run(ctx, &RootFlags{Account: "svc@example.com"}); err != nil {
t.Fatalf("Run: %v", err)
}
})
if gotRole != adminRoleOwner {
t.Fatalf("unexpected role sent: %q", gotRole)
}
var parsed struct {
Email string `json:"email"`
Role string `json:"role"`
}
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if parsed.Email != "dev@example.com" || parsed.Role != adminRoleOwner {
t.Fatalf("unexpected response: %#v", parsed)
}
}