feat(cli): positional whitelist grammar with required direction, enable/disable, validation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+51
-35
@@ -132,48 +132,64 @@ func TestAccountEditPartialPreservesOtherFields(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A missing direction (e.g. `whitelist list`) must report the real problem —
|
||||
// the in|out direction — not the misleading "--account is required".
|
||||
func TestWhitelistMissingDirectionReported(t *testing.T) {
|
||||
func TestWhitelistRequiresDirection(t *testing.T) {
|
||||
adminEnv(t)
|
||||
code, _, errOut := run(t, "whitelist", "list", "--account", "bobby")
|
||||
if code == 0 {
|
||||
t.Fatal("missing direction must be a usage error")
|
||||
}
|
||||
if strings.Contains(errOut, "--account is required") {
|
||||
t.Fatalf("misleading error; want a direction complaint, got: %q", errOut)
|
||||
}
|
||||
if !strings.Contains(errOut, "in") || !strings.Contains(errOut, "out") {
|
||||
t.Fatalf("error should name the in|out direction, got: %q", errOut)
|
||||
run(t, "account", "add", "bobby", "--imap-host", "h", "--username", "u@x.com")
|
||||
code, _, errOut := run(t, "whitelist", "add", "bobby", "a@x.com")
|
||||
if code != 2 || !strings.Contains(errOut, "--in") || !strings.Contains(errOut, "--out") {
|
||||
t.Fatalf("missing direction must name --in/--out: code=%d err=%q", code, errOut)
|
||||
}
|
||||
}
|
||||
|
||||
// A missing subcommand (e.g. `whitelist out --account x`) must report the real
|
||||
// problem — the add|remove|list subcommand — not "--account is required".
|
||||
func TestWhitelistMissingSubcommandReported(t *testing.T) {
|
||||
func TestWhitelistAddListRemove(t *testing.T) {
|
||||
adminEnv(t)
|
||||
code, _, errOut := run(t, "whitelist", "out", "--account", "bobby")
|
||||
if code == 0 {
|
||||
t.Fatal("missing subcommand must be a usage error")
|
||||
}
|
||||
if strings.Contains(errOut, "--account is required") {
|
||||
t.Fatalf("misleading error; want a subcommand complaint, got: %q", errOut)
|
||||
}
|
||||
if !strings.Contains(errOut, "add") || !strings.Contains(errOut, "list") {
|
||||
t.Fatalf("error should name the add|remove|list subcommand, got: %q", errOut)
|
||||
}
|
||||
}
|
||||
|
||||
// The happy path still works after the direction/subcommand validation.
|
||||
func TestWhitelistListWorks(t *testing.T) {
|
||||
adminEnv(t)
|
||||
run(t, "account", "add", "--name", "bobby", "--imap-host", "h", "--username", "u@x.com")
|
||||
if code, _, e := run(t, "whitelist", "out", "add", "--account", "bobby", "--address", "@x.com"); code != 0 {
|
||||
run(t, "account", "add", "bobby", "--imap-host", "h", "--username", "u@x.com")
|
||||
if code, _, e := run(t, "whitelist", "add", "bobby", "a@x.com", "@y.com", "--out"); code != 0 {
|
||||
t.Fatalf("add failed: %s", e)
|
||||
}
|
||||
code, out, _ := run(t, "whitelist", "out", "list", "--account", "bobby")
|
||||
if code != 0 || !strings.Contains(out, "@x.com") {
|
||||
t.Fatalf("list: code=%d out=%q", code, out)
|
||||
code, out, _ := run(t, "whitelist", "list", "bobby", "--out")
|
||||
if code != 0 || !strings.Contains(out, "a@x.com") || !strings.Contains(out, "@y.com") || !strings.Contains(out, "DISABLED") {
|
||||
t.Fatalf("list wrong: code=%d out=%q", code, out)
|
||||
}
|
||||
if code, _, e := run(t, "whitelist", "rm", "bobby", "a@x.com", "--out"); code != 0 { // alias
|
||||
t.Fatalf("rm failed: %s", e)
|
||||
}
|
||||
_, out, _ = run(t, "whitelist", "ls", "bobby", "--out") // alias
|
||||
if strings.Contains(out, "a@x.com") {
|
||||
t.Fatalf("address not removed:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWhitelistRejectsBadAddress(t *testing.T) {
|
||||
adminEnv(t)
|
||||
run(t, "account", "add", "bobby", "--imap-host", "h", "--username", "u@x.com")
|
||||
if code, _, e := run(t, "whitelist", "add", "bobby", "notanaddress", "--in"); code != 2 || !strings.Contains(e, "invalid address") {
|
||||
t.Fatalf("bad address must be rejected: code=%d err=%q", code, e)
|
||||
}
|
||||
// The original bug: a missing address must not silently insert a blank row.
|
||||
if code, _, _ := run(t, "whitelist", "add", "bobby", "--in"); code != 2 {
|
||||
t.Fatal("add with no address must be a usage error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWhitelistEnableDisable(t *testing.T) {
|
||||
adminEnv(t)
|
||||
run(t, "account", "add", "bobby", "--imap-host", "h", "--username", "u@x.com")
|
||||
// Enabling an empty whitelist warns but succeeds.
|
||||
code, _, errOut := run(t, "whitelist", "enable", "bobby", "--in")
|
||||
if code != 0 || !strings.Contains(errOut, "empty") {
|
||||
t.Fatalf("enable empty: code=%d err=%q", code, errOut)
|
||||
}
|
||||
_, out, _ := run(t, "whitelist", "list", "bobby", "--in")
|
||||
if !strings.Contains(out, "ENABLED") {
|
||||
t.Fatalf("expected ENABLED:\n%s", out)
|
||||
}
|
||||
if code, _, e := run(t, "whitelist", "disable", "bobby", "--in"); code != 0 {
|
||||
t.Fatalf("disable failed: %s", e)
|
||||
}
|
||||
_, out, _ = run(t, "whitelist", "list", "bobby", "--in")
|
||||
if !strings.Contains(out, "DISABLED") {
|
||||
t.Fatalf("expected DISABLED:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user