mirror of
https://github.com/onyx-and-iris/lottery-cli.git
synced 2026-08-17 00:34:25 +00:00
add AllKinds to the public API. Use it as a single source of truth.
This commit is contained in:
63
kinds.go
63
kinds.go
@@ -1,6 +1,10 @@
|
||||
package lottery
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Kind string
|
||||
|
||||
@@ -12,22 +16,43 @@ const (
|
||||
KindPowerball Kind = "powerball"
|
||||
)
|
||||
|
||||
func ParseKind(kind string) (Kind, error) {
|
||||
switch kind {
|
||||
case "lotto":
|
||||
return KindLotto, nil
|
||||
case "euromillions":
|
||||
return KindEuroMillions, nil
|
||||
case "setforlife":
|
||||
return KindSetForLife, nil
|
||||
case "thunderball":
|
||||
return KindThunderball, nil
|
||||
case "powerball":
|
||||
return KindPowerball, nil
|
||||
default:
|
||||
return "", fmt.Errorf(
|
||||
"invalid lottery kind: %s, must be one of: lotto, euromillions, setforlife, thunderball, powerball",
|
||||
kind,
|
||||
)
|
||||
}
|
||||
var allKinds = []Kind{
|
||||
KindLotto,
|
||||
KindEuroMillions,
|
||||
KindSetForLife,
|
||||
KindThunderball,
|
||||
KindPowerball,
|
||||
}
|
||||
|
||||
var allKindsText = []string{
|
||||
string(KindLotto),
|
||||
string(KindEuroMillions),
|
||||
string(KindSetForLife),
|
||||
string(KindThunderball),
|
||||
string(KindPowerball),
|
||||
}
|
||||
|
||||
var allKindsCSV = strings.Join(allKindsText, ", ")
|
||||
|
||||
// AllKinds returns the complete, ordered list of supported lottery kinds.
|
||||
//
|
||||
// The returned slice is a copy and can be modified safely by callers.
|
||||
func AllKinds() []Kind {
|
||||
kinds := make([]Kind, len(allKinds))
|
||||
copy(kinds, allKinds)
|
||||
return kinds
|
||||
}
|
||||
|
||||
// ParseKind parses a string into a Kind, returning an error if the string is not a valid kind.
|
||||
func ParseKind(kind string) (Kind, error) {
|
||||
parsed := Kind(kind)
|
||||
if slices.Contains(allKinds, parsed) {
|
||||
return parsed, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf(
|
||||
"invalid lottery kind: %s, must be one of: %s",
|
||||
kind,
|
||||
allKindsCSV,
|
||||
)
|
||||
}
|
||||
|
||||
71
kinds_test.go
Normal file
71
kinds_test.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package lottery
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAllKindsReturnsExpectedOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
got := AllKinds()
|
||||
want := []Kind{
|
||||
KindLotto,
|
||||
KindEuroMillions,
|
||||
KindSetForLife,
|
||||
KindThunderball,
|
||||
KindPowerball,
|
||||
}
|
||||
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("expected %d kinds, got %d", len(want), len(got))
|
||||
}
|
||||
|
||||
for i := range want {
|
||||
if got[i] != want[i] {
|
||||
t.Fatalf("kind at index %d: expected %q, got %q", i, want[i], got[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllKindsReturnsCopy(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
first := AllKinds()
|
||||
first[0] = "mutated"
|
||||
|
||||
again := AllKinds()
|
||||
if again[0] != KindLotto {
|
||||
t.Fatalf("expected AllKinds to return a defensive copy")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseKindAcceptsAllKinds(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, kind := range AllKinds() {
|
||||
parsed, err := ParseKind(string(kind))
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error for %q, got %v", kind, err)
|
||||
}
|
||||
if parsed != kind {
|
||||
t.Fatalf("expected %q, got %q", kind, parsed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseKindIncludesAllKindsInError(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := ParseKind("invalid")
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error for invalid kind")
|
||||
}
|
||||
|
||||
message := err.Error()
|
||||
for _, kind := range AllKinds() {
|
||||
if !strings.Contains(message, string(kind)) {
|
||||
t.Fatalf("expected error message to contain kind %q: %s", kind, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user