Feature: Add xand tag (#442)

* Feat: Add xand group and check for missing

* Fix: Split and combine err in TestMultiand for consistency

* Feat: Check missing required flags in xand groups

* Feat: Handle combined xor and xand

* Docs: Add info about combined xand and required use

* Docs: Fix language error in xand description

Co-authored-by: Stautis <thkrst@gmail.com>

* Feat: Rename xand to and

* Refactor: Switch from fmt.Sprintf to err.Error

* Refactor: Get requiredAndGroup map in separate function

---------

Co-authored-by: Stautis <thkrst@gmail.com>
This commit is contained in:
Camilla
2024-08-08 08:58:22 +02:00
committed by GitHub
parent 5f9c5cc822
commit ff6d5ba7d5
7 changed files with 195 additions and 14 deletions
+109
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"fmt"
"sort"
"strings"
"testing"
@@ -919,6 +920,21 @@ func TestXor(t *testing.T) {
assert.NoError(t, err)
}
func TestAnd(t *testing.T) {
var cli struct {
Hello bool `and:"another"`
One bool `and:"group"`
Two string `and:"group"`
}
p := mustNew(t, &cli)
_, err := p.Parse([]string{"--hello", "--one"})
assert.EqualError(t, err, "--one and --two must be used together")
p = mustNew(t, &cli)
_, err = p.Parse([]string{"--one", "--two=hi", "--hello"})
assert.NoError(t, err)
}
func TestXorChild(t *testing.T) {
var cli struct {
One bool `xor:"group"`
@@ -936,6 +952,23 @@ func TestXorChild(t *testing.T) {
assert.Error(t, err, "--two and --three can't be used together")
}
func TestAndChild(t *testing.T) {
var cli struct {
One bool `and:"group"`
Cmd struct {
Two string `and:"group"`
Three string `and:"group"`
} `cmd`
}
p := mustNew(t, &cli)
_, err := p.Parse([]string{"--one", "cmd", "--two=hi", "--three=hello"})
assert.NoError(t, err)
p = mustNew(t, &cli)
_, err = p.Parse([]string{"--two=hi", "cmd"})
assert.Error(t, err, "--two and --three must be used together")
}
func TestMultiXor(t *testing.T) {
var cli struct {
Hello bool `xor:"one,two"`
@@ -952,6 +985,47 @@ func TestMultiXor(t *testing.T) {
assert.EqualError(t, err, "--hello and --two can't be used together")
}
func TestMultiAnd(t *testing.T) {
var cli struct {
Hello bool `and:"one,two"`
One bool `and:"one"`
Two string `and:"two"`
}
p := mustNew(t, &cli)
_, err := p.Parse([]string{"--hello"})
// Split and combine error so messages always will be in the same order
// when testing
missingMsgs := strings.Split(err.Error(), ", ")
sort.Strings(missingMsgs)
err = fmt.Errorf("%s", strings.Join(missingMsgs, ", "))
assert.EqualError(t, err, "--hello and --one must be used together, --hello and --two must be used together")
p = mustNew(t, &cli)
_, err = p.Parse([]string{"--two=foo"})
assert.EqualError(t, err, "--hello and --two must be used together")
}
func TestXorAnd(t *testing.T) {
var cli struct {
Hello bool `xor:"one" and:"two"`
One bool `xor:"one"`
Two string `and:"two"`
}
p := mustNew(t, &cli)
_, err := p.Parse([]string{"--hello"})
assert.EqualError(t, err, "--hello and --two must be used together")
p = mustNew(t, &cli)
_, err = p.Parse([]string{"--one"})
assert.NoError(t, err)
p = mustNew(t, &cli)
_, err = p.Parse([]string{"--hello", "--one"})
assert.EqualError(t, err, "--hello and --one can't be used together, --hello and --two must be used together")
}
func TestXorRequired(t *testing.T) {
var cli struct {
One bool `xor:"one,two" required:""`
@@ -972,6 +1046,26 @@ func TestXorRequired(t *testing.T) {
assert.EqualError(t, err, "missing flags: --four, --one or --three, --one or --two")
}
func TestAndRequired(t *testing.T) {
var cli struct {
One bool `and:"one,two" required:""`
Two bool `and:"one" required:""`
Three bool `and:"two"`
Four bool `required:""`
}
p := mustNew(t, &cli)
_, err := p.Parse([]string{"--one", "--two", "--three"})
assert.EqualError(t, err, "missing flags: --four")
p = mustNew(t, &cli)
_, err = p.Parse([]string{"--four"})
assert.EqualError(t, err, "missing flags: --one and --three, --one and --two")
p = mustNew(t, &cli)
_, err = p.Parse([]string{})
assert.EqualError(t, err, "missing flags: --four, --one and --three, --one and --two")
}
func TestXorRequiredMany(t *testing.T) {
var cli struct {
One bool `xor:"one" required:""`
@@ -991,6 +1085,21 @@ func TestXorRequiredMany(t *testing.T) {
assert.EqualError(t, err, "missing flags: --one or --two or --three")
}
func TestAndRequiredMany(t *testing.T) {
var cli struct {
One bool `and:"one" required:""`
Two bool `and:"one" required:""`
Three bool `and:"one" required:""`
}
p := mustNew(t, &cli)
_, err := p.Parse([]string{})
assert.EqualError(t, err, "missing flags: --one and --two and --three")
p = mustNew(t, &cli)
_, err = p.Parse([]string{"--three"})
assert.EqualError(t, err, "missing flags: --one and --two")
}
func TestEnumSequence(t *testing.T) {
var cli struct {
State []string `enum:"a,b,c" default:"a"`