feat(mail): add group management commands
Add gt mail group subcommands: - gt mail group list - list all groups - gt mail group show <name> - show group details - gt mail group create <name> [members...] - create new group - gt mail group add <name> <member> - add member - gt mail group remove <name> <member> - remove member - gt mail group delete <name> - delete group Includes validation for group names and member patterns. Supports direct addresses, wildcards, @-patterns, and nested groups. Part of gt-xfqh1e.7 (group commands task). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
Steve Yegge
parent
839fa19e90
commit
b3b980fd79
73
internal/cmd/mail_group_test.go
Normal file
73
internal/cmd/mail_group_test.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package cmd
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestIsValidGroupName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
want bool
|
||||
}{
|
||||
{"ops-team", true},
|
||||
{"all_witnesses", true},
|
||||
{"team123", true},
|
||||
{"A", true},
|
||||
{"abc", true},
|
||||
{"my-cool-group", true},
|
||||
|
||||
// Invalid
|
||||
{"", false},
|
||||
{"with spaces", false},
|
||||
{"with.dots", false},
|
||||
{"@team", false},
|
||||
{"group/name", false},
|
||||
{"team!", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := isValidGroupName(tt.name); got != tt.want {
|
||||
t.Errorf("isValidGroupName(%q) = %v, want %v", tt.name, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidMemberPattern(t *testing.T) {
|
||||
tests := []struct {
|
||||
pattern string
|
||||
want bool
|
||||
}{
|
||||
// Direct addresses
|
||||
{"gastown/crew/max", true},
|
||||
{"mayor/", true},
|
||||
{"deacon/", true},
|
||||
{"gastown/witness", true},
|
||||
|
||||
// Wildcard patterns
|
||||
{"*/witness", true},
|
||||
{"gastown/*", true},
|
||||
{"gastown/crew/*", true},
|
||||
|
||||
// Special patterns
|
||||
{"@town", true},
|
||||
{"@crew", true},
|
||||
{"@witnesses", true},
|
||||
{"@rig/gastown", true},
|
||||
|
||||
// Group names
|
||||
{"ops-team", true},
|
||||
{"all_witnesses", true},
|
||||
|
||||
// Invalid
|
||||
{"", false},
|
||||
{"@", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.pattern, func(t *testing.T) {
|
||||
if got := isValidMemberPattern(tt.pattern); got != tt.want {
|
||||
t.Errorf("isValidMemberPattern(%q) = %v, want %v", tt.pattern, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user