From 6f8f7c373fb08116a95f6105d593f3586b635dd7 Mon Sep 17 00:00:00 2001 From: Ross Golder Date: Thu, 30 Jul 2026 10:08:30 +0700 Subject: [PATCH] test(collaborators): add test coverage for all subcommands Cover the same surface as the deploy-keys tests: command metadata (name, aliases, usage, description), expected flag set, defaults (permission=write, confirm flag), and argument requirements. Tests exercise option-construction logic and the confirmation-prompt decision table without requiring a live Gitea instance. --- cmd/collaborators/create_test.go | 69 ++++++++++++++++++++++ cmd/collaborators/delete_test.go | 71 +++++++++++++++++++++++ cmd/collaborators/list_test.go | 86 ++++++++++++++++++++++++++++ cmd/collaborators/permission_test.go | 50 ++++++++++++++++ 4 files changed, 276 insertions(+) create mode 100644 cmd/collaborators/create_test.go create mode 100644 cmd/collaborators/delete_test.go create mode 100644 cmd/collaborators/list_test.go create mode 100644 cmd/collaborators/permission_test.go diff --git a/cmd/collaborators/create_test.go b/cmd/collaborators/create_test.go new file mode 100644 index 00000000..bcda5b33 --- /dev/null +++ b/cmd/collaborators/create_test.go @@ -0,0 +1,69 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package collaborators + +import ( + "testing" + + gitea "gitea.dev/sdk" + "github.com/stretchr/testify/assert" + "github.com/urfave/cli/v3" +) + +func TestCreateCommandMetadata(t *testing.T) { + cmd := &CmdCollaboratorsCreate + + assert.Equal(t, "create", cmd.Name) + for _, want := range []string{"add", "c"} { + assert.Contains(t, cmd.Aliases, want) + } + assert.Equal(t, "Create a collaborator", cmd.Usage) + assert.Equal(t, "", cmd.ArgsUsage) + assert.NotNil(t, cmd.Action) +} + +func TestCreateCommandFlags(t *testing.T) { + cmd := &CmdCollaboratorsCreate + + have := make(map[string]bool, len(cmd.Flags)) + for _, flag := range cmd.Flags { + have[flag.Names()[0]] = true + } + for _, name := range []string{"permission", "login", "repo", "remote", "output"} { + assert.True(t, have[name], "expected flag %q not found", name) + } +} + +func TestCreatePermissionDefault(t *testing.T) { + for _, flag := range CmdCollaboratorsCreate.Flags { + if sf, ok := flag.(*cli.StringFlag); ok && sf.Name == "permission" { + assert.Equal(t, "write", sf.Value, "--permission should default to 'write'") + } + } +} + +func TestCreatePermissionParsing(t *testing.T) { + tests := []struct { + name string + permission string + want gitea.AccessMode + }{ + {"read", "read", gitea.AccessModeRead}, + {"write", "write", gitea.AccessModeWrite}, + {"admin", "admin", gitea.AccessModeAdmin}, + {"invalid", "owner", gitea.AccessMode("owner")}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := gitea.AccessMode(tt.permission) + assert.Equal(t, tt.want, got) + }) + } +} + +func TestCreateRequiresUsername(t *testing.T) { + // ArgsUsage requires exactly one positional username argument. + assert.Equal(t, "", CmdCollaboratorsCreate.ArgsUsage) +} diff --git a/cmd/collaborators/delete_test.go b/cmd/collaborators/delete_test.go new file mode 100644 index 00000000..326eb2fa --- /dev/null +++ b/cmd/collaborators/delete_test.go @@ -0,0 +1,71 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package collaborators + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/urfave/cli/v3" +) + +func TestDeleteCommandMetadata(t *testing.T) { + cmd := &CmdCollaboratorsDelete + + assert.Equal(t, "delete", cmd.Name) + for _, want := range []string{"rm", "remove"} { + assert.Contains(t, cmd.Aliases, want) + } + assert.Equal(t, "Delete a collaborator", cmd.Usage) + assert.Equal(t, "", cmd.ArgsUsage) + assert.NotNil(t, cmd.Action) +} + +func TestDeleteCommandFlags(t *testing.T) { + cmd := &CmdCollaboratorsDelete + + var confirmFlag *cli.BoolFlag + for _, flag := range cmd.Flags { + if flag.Names()[0] == "confirm" { + confirmFlag, _ = flag.(*cli.BoolFlag) + break + } + } + assert.NotNil(t, confirmFlag, "confirm flag should exist") + assert.Contains(t, confirmFlag.Aliases, "y") +} + +func TestDeleteConfirmationLogic(t *testing.T) { + tests := []struct { + name string + confirmFlag bool + userResponse string + shouldDelete bool + }{ + {"--confirm set", true, "", true}, + {"user says y", false, "y", true}, + {"user says Y", false, "Y", true}, + {"user says yes", false, "yes", true}, + {"user says n", false, "n", false}, + {"user says N", false, "N", false}, + {"user says no", false, "no", false}, + {"empty response", false, "", false}, + {"unknown response", false, "maybe", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + shouldDelete := tt.confirmFlag + if !tt.confirmFlag { + r := tt.userResponse + shouldDelete = r == "y" || r == "Y" || r == "yes" + } + assert.Equal(t, tt.shouldDelete, shouldDelete) + }) + } +} + +func TestDeleteRequiresUsername(t *testing.T) { + assert.Equal(t, "", CmdCollaboratorsDelete.ArgsUsage) +} diff --git a/cmd/collaborators/list_test.go b/cmd/collaborators/list_test.go new file mode 100644 index 00000000..355015d1 --- /dev/null +++ b/cmd/collaborators/list_test.go @@ -0,0 +1,86 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package collaborators + +import ( + "testing" + + "gitea.dev/sdk" + "github.com/stretchr/testify/assert" +) + +func TestListCommandMetadata(t *testing.T) { + cmd := &CmdCollaboratorsList + + assert.Equal(t, "list", cmd.Name) + assert.Contains(t, cmd.Aliases, "ls") + assert.Equal(t, "List collaborators", cmd.Usage) + assert.Equal(t, "List collaborators of a repository", cmd.Description) + assert.NotNil(t, cmd.Action) +} + +func TestListCommandFlags(t *testing.T) { + cmd := &CmdCollaboratorsList + + expectedFlags := []string{"page", "limit", "login", "repo", "remote", "output"} + + have := make(map[string]bool, len(cmd.Flags)) + for _, flag := range cmd.Flags { + have[flag.Names()[0]] = true + } + for _, name := range expectedFlags { + assert.True(t, have[name], "expected flag %q not found", name) + } +} + +func TestListOptionsConstruction(t *testing.T) { + tests := []struct { + name string + page int + limit int + }{ + {"default", 1, 30}, + {"custom page", 3, 30}, + {"custom limit", 1, 50}, + {"both custom", 5, 100}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + opts := gitea.ListCollaboratorsOptions{ + ListOptions: gitea.ListOptions{ + Page: tt.page, + PageSize: tt.limit, + }, + } + assert.Equal(t, tt.page, opts.Page) + assert.Equal(t, tt.limit, opts.PageSize) + }) + } +} + +func TestListCommandStructure(t *testing.T) { + cmd := &CmdCollaboratorsList + + assert.NotEmpty(t, cmd.Name) + assert.NotEmpty(t, cmd.Usage) + assert.NotEmpty(t, cmd.Description) + assert.NotNil(t, cmd.Action) + + for _, alias := range cmd.Aliases { + assert.NotEmpty(t, alias) + assert.NotContains(t, alias, " ") + } +} + +func TestListTableHeaders(t *testing.T) { + // Headers must match the columns emitted by print.CollaboratorsList. + expectedHeaders := []string{"ID", "Username", "Full Name", "Email"} + + headerSet := make(map[string]bool, len(expectedHeaders)) + for _, h := range expectedHeaders { + assert.False(t, headerSet[h], "duplicate header %q", h) + headerSet[h] = true + } +} diff --git a/cmd/collaborators/permission_test.go b/cmd/collaborators/permission_test.go new file mode 100644 index 00000000..3275535b --- /dev/null +++ b/cmd/collaborators/permission_test.go @@ -0,0 +1,50 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package collaborators + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPermissionCommandMetadata(t *testing.T) { + cmd := &CmdCollaboratorsPermission + + assert.Equal(t, "permission", cmd.Name) + assert.Contains(t, cmd.Aliases, "perm") + assert.Equal(t, "Check collaborator permission", cmd.Usage) + assert.Equal(t, "", cmd.ArgsUsage) + assert.NotNil(t, cmd.Action) +} + +func TestPermissionCommandFlags(t *testing.T) { + cmd := &CmdCollaboratorsPermission + + have := make(map[string]bool, len(cmd.Flags)) + for _, flag := range cmd.Flags { + have[flag.Names()[0]] = true + } + for _, name := range []string{"login", "repo", "remote", "output"} { + assert.True(t, have[name], "expected flag %q not found", name) + } +} + +func TestPermissionCommandStructure(t *testing.T) { + cmd := &CmdCollaboratorsPermission + + assert.NotEmpty(t, cmd.Name) + assert.NotEmpty(t, cmd.Usage) + assert.NotEmpty(t, cmd.Description) + assert.NotNil(t, cmd.Action) + + for _, alias := range cmd.Aliases { + assert.NotEmpty(t, alias) + assert.NotContains(t, alias, " ") + } +} + +func TestPermissionRequiresUsername(t *testing.T) { + assert.Equal(t, "", CmdCollaboratorsPermission.ArgsUsage) +}