1
0
mirror of https://github.com/juanfont/headscale.git synced 2026-02-23 13:50:36 +01:00
juanfont.headscale/cmd/headscale/cli/patterns_test.go
2025-07-14 07:48:32 +00:00

377 lines
9.1 KiB
Go

package cli
import (
"errors"
"testing"
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
)
func TestResolveUserByNameOrID(t *testing.T) {
tests := []struct {
name string
identifier string
users []*v1.User
expected *v1.User
expectError bool
}{
{
name: "resolve by ID",
identifier: "123",
users: []*v1.User{
{Id: 123, Name: "testuser", Email: "test@example.com"},
},
expected: &v1.User{Id: 123, Name: "testuser", Email: "test@example.com"},
},
{
name: "resolve by name",
identifier: "testuser",
users: []*v1.User{
{Id: 123, Name: "testuser", Email: "test@example.com"},
},
expected: &v1.User{Id: 123, Name: "testuser", Email: "test@example.com"},
},
{
name: "resolve by email",
identifier: "test@example.com",
users: []*v1.User{
{Id: 123, Name: "testuser", Email: "test@example.com"},
},
expected: &v1.User{Id: 123, Name: "testuser", Email: "test@example.com"},
},
{
name: "not found",
identifier: "nonexistent",
users: []*v1.User{},
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// We can't easily test the actual resolution without a real client
// but we can test the logic structure
assert.NotNil(t, ResolveUserByNameOrID)
})
}
}
func TestResolveNodeByIdentifier(t *testing.T) {
tests := []struct {
name string
identifier string
nodes []*v1.Node
expected *v1.Node
expectError bool
}{
{
name: "resolve by ID",
identifier: "123",
nodes: []*v1.Node{
{Id: 123, Name: "testnode", GivenName: "test-device", IpAddresses: []string{"192.168.1.1"}},
},
expected: &v1.Node{Id: 123, Name: "testnode", GivenName: "test-device", IpAddresses: []string{"192.168.1.1"}},
},
{
name: "resolve by hostname",
identifier: "testnode",
nodes: []*v1.Node{
{Id: 123, Name: "testnode", GivenName: "test-device", IpAddresses: []string{"192.168.1.1"}},
},
expected: &v1.Node{Id: 123, Name: "testnode", GivenName: "test-device", IpAddresses: []string{"192.168.1.1"}},
},
{
name: "not found",
identifier: "nonexistent",
nodes: []*v1.Node{},
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Test that the function exists and has the right signature
assert.NotNil(t, ResolveNodeByIdentifier)
})
}
}
func TestValidateRequiredArgs(t *testing.T) {
tests := []struct {
name string
args []string
minArgs int
usage string
expectError bool
}{
{
name: "sufficient args",
args: []string{"arg1", "arg2"},
minArgs: 2,
usage: "command <arg1> <arg2>",
expectError: false,
},
{
name: "insufficient args",
args: []string{"arg1"},
minArgs: 2,
usage: "command <arg1> <arg2>",
expectError: true,
},
{
name: "no args required",
args: []string{},
minArgs: 0,
usage: "command",
expectError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := &cobra.Command{Use: "test"}
err := ValidateRequiredArgs(cmd, tt.args, tt.minArgs, tt.usage)
if tt.expectError {
assert.Error(t, err)
assert.Contains(t, err.Error(), "insufficient arguments")
} else {
assert.NoError(t, err)
}
})
}
}
func TestValidateExactArgs(t *testing.T) {
tests := []struct {
name string
args []string
exactArgs int
usage string
expectError bool
}{
{
name: "exact args",
args: []string{"arg1", "arg2"},
exactArgs: 2,
usage: "command <arg1> <arg2>",
expectError: false,
},
{
name: "too few args",
args: []string{"arg1"},
exactArgs: 2,
usage: "command <arg1> <arg2>",
expectError: true,
},
{
name: "too many args",
args: []string{"arg1", "arg2", "arg3"},
exactArgs: 2,
usage: "command <arg1> <arg2>",
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := &cobra.Command{Use: "test"}
err := ValidateExactArgs(cmd, tt.args, tt.exactArgs, tt.usage)
if tt.expectError {
assert.Error(t, err)
assert.Contains(t, err.Error(), "expected")
} else {
assert.NoError(t, err)
}
})
}
}
func TestProcessMultipleResources(t *testing.T) {
tests := []struct {
name string
items []string
processor func(string) error
continueOnError bool
expectedErrors int
}{
{
name: "all success",
items: []string{"item1", "item2", "item3"},
processor: func(item string) error {
return nil
},
continueOnError: true,
expectedErrors: 0,
},
{
name: "one error, continue",
items: []string{"item1", "error", "item3"},
processor: func(item string) error {
if item == "error" {
return errors.New("test error")
}
return nil
},
continueOnError: true,
expectedErrors: 1,
},
{
name: "one error, stop",
items: []string{"item1", "error", "item3"},
processor: func(item string) error {
if item == "error" {
return errors.New("test error")
}
return nil
},
continueOnError: false,
expectedErrors: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
errors := ProcessMultipleResources(tt.items, tt.processor, tt.continueOnError)
assert.Len(t, errors, tt.expectedErrors)
})
}
}
func TestIsValidationError(t *testing.T) {
tests := []struct {
name string
err error
expected bool
}{
{
name: "insufficient arguments error",
err: errors.New("insufficient arguments provided"),
expected: true,
},
{
name: "required flag error",
err: errors.New("required flag not set"),
expected: true,
},
{
name: "not found error",
err: errors.New("not found matching identifier"),
expected: true,
},
{
name: "ambiguous error",
err: errors.New("ambiguous identifier"),
expected: true,
},
{
name: "network error",
err: errors.New("connection refused"),
expected: false,
},
{
name: "random error",
err: errors.New("some other error"),
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := IsValidationError(tt.err)
assert.Equal(t, tt.expected, result)
})
}
}
func TestWrapCommandError(t *testing.T) {
cmd := &cobra.Command{Use: "test"}
originalErr := errors.New("original error")
action := "create user"
wrappedErr := WrapCommandError(cmd, originalErr, action)
assert.Error(t, wrappedErr)
assert.Contains(t, wrappedErr.Error(), "failed to create user")
assert.Contains(t, wrappedErr.Error(), "original error")
}
func TestCommandPatternHelpers(t *testing.T) {
// Test that the helper functions exist and return valid function types
// Mock functions for testing
listFunc := func(client *ClientWrapper, cmd *cobra.Command) ([]interface{}, error) {
return []interface{}{}, nil
}
tableSetup := func(tr *TableRenderer) {
// Mock table setup
}
createFunc := func(client *ClientWrapper, cmd *cobra.Command, args []string) (interface{}, error) {
return map[string]string{"result": "created"}, nil
}
getFunc := func(client *ClientWrapper, cmd *cobra.Command) (interface{}, error) {
return map[string]string{"result": "found"}, nil
}
deleteFunc := func(client *ClientWrapper, cmd *cobra.Command) (interface{}, error) {
return map[string]string{"result": "deleted"}, nil
}
updateFunc := func(client *ClientWrapper, cmd *cobra.Command, args []string) (interface{}, error) {
return map[string]string{"result": "updated"}, nil
}
// Test helper function creation
listCmdFunc := StandardListCommand(listFunc, tableSetup)
assert.NotNil(t, listCmdFunc)
createCmdFunc := StandardCreateCommand(createFunc, "Created successfully")
assert.NotNil(t, createCmdFunc)
deleteCmdFunc := StandardDeleteCommand(getFunc, deleteFunc, "resource")
assert.NotNil(t, deleteCmdFunc)
updateCmdFunc := StandardUpdateCommand(updateFunc, "Updated successfully")
assert.NotNil(t, updateCmdFunc)
}
func TestExecuteListCommand(t *testing.T) {
// Test that ExecuteListCommand function exists
assert.NotNil(t, ExecuteListCommand)
}
func TestExecuteCreateCommand(t *testing.T) {
// Test that ExecuteCreateCommand function exists
assert.NotNil(t, ExecuteCreateCommand)
}
func TestExecuteGetCommand(t *testing.T) {
// Test that ExecuteGetCommand function exists
assert.NotNil(t, ExecuteGetCommand)
}
func TestExecuteUpdateCommand(t *testing.T) {
// Test that ExecuteUpdateCommand function exists
assert.NotNil(t, ExecuteUpdateCommand)
}
func TestExecuteDeleteCommand(t *testing.T) {
// Test that ExecuteDeleteCommand function exists
assert.NotNil(t, ExecuteDeleteCommand)
}
func TestConfirmAction(t *testing.T) {
// Test that ConfirmAction function exists
assert.NotNil(t, ConfirmAction)
}
func TestConfirmDeletion(t *testing.T) {
// Test that ConfirmDeletion function exists
assert.NotNil(t, ConfirmDeletion)
}