diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 274a82b..a7ab943 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -22,7 +22,7 @@ on:
branches:
- main
env:
- VERSION_NUMBER: 'v0.7.2'
+ VERSION_NUMBER: 'v0.8.0'
REGISTRY_NAME: digitalghostdev/poke-cli
jobs:
diff --git a/README.md b/README.md
index c6cd511..2cd321b 100644
--- a/README.md
+++ b/README.md
@@ -2,14 +2,13 @@
Pokémon CLI
-
+
-

-
+
## Overview
@@ -20,7 +19,7 @@ My aim is to have four commands finished for `v1.0.0`. Read more in the [Roadmap
---
## Demo
-
+
---
## Install
@@ -35,7 +34,19 @@ _Download a pre-built binary_
5. Either change directories into the extracted folder or move the binary to a chosen directory.
6. Run the tool!
-* Example usage:
+> [!IMPORTANT]
+> For macOS, you may have to allow the executable to run as it is not signed. Head to System Settings > Privacy & Security > scroll down and allow executable to run.
+
+
+
+View Image of Settings
+
+
+
+
+
+
+ #### Example usage
```bash
# Windows
.\poke-cli.exe pokemon charizard --types --abilities
@@ -57,7 +68,7 @@ _Use a Docker Image_
* Necessary.
```bash
-docker run --rm -i -t digitalghostdev/poke-cli:v0.7.2 [subcommand] flag]
+docker run --rm -i -t digitalghostdev/poke-cli:v0.8.0 [subcommand] flag]
```
### Go Install
@@ -103,11 +114,10 @@ The architecture behind how the tool works is straight forward.
_Not 100% up-to-date, may add or remove some of these choices_
- [ ] `pokemon`: get data about a specific Pokémon.
- - [x] `--abilities | -a`: display the Pokémon's abilities.
- - [x] `--types | -t`: display the Pokémon's typing.
- - [ ] `--stats | -s`: display the Pokémon's base stats.
- - [ ] `--metrics | -m`: display the Pokémon's metrics. (height, weight, etc.)
-- [ ] `types`: get data about a specific typing.
- - [ ] `--chart | -c`: display the type's damage chart. Undecided.
+ - [x] `-a | --abilities`: display the Pokémon's abilities.
+ - [x] `-s | --stats`: display the Pokémon's base stats.
+ - [x] `-t | --types`: display the Pokémon's typing.
+ - [ ] `-m | --moves`: display learnable moves.
+- [x] `types`: get data about a specific typing.
- [ ] `ability`: get data about a specific ability.
-- [ ] `moves`: get data about a specific move.
\ No newline at end of file
+- [ ] `move`: get data about a specific move.
\ No newline at end of file
diff --git a/cli_test.go b/cli_test.go
index e797a2e..ad5f0d5 100644
--- a/cli_test.go
+++ b/cli_test.go
@@ -110,7 +110,7 @@ func TestRunCLI(t *testing.T) {
{
name: "Latest Flag",
args: []string{"-l"},
- expectedOutput: "Latest Docker image version: v0.7.1\nLatest release tag: v0.7.1\n",
+ expectedOutput: "Latest Docker image version: v0.7.2\nLatest release tag: v0.7.2\n",
expectedCode: 0,
},
}
diff --git a/cmd/pokemon.go b/cmd/pokemon.go
index 6996866..32f56ee 100644
--- a/cmd/pokemon.go
+++ b/cmd/pokemon.go
@@ -7,6 +7,7 @@ import (
"github.com/digitalghost-dev/poke-cli/flags"
"golang.org/x/text/cases"
"golang.org/x/text/language"
+ "math"
"os"
"strings"
)
@@ -22,16 +23,17 @@ func PokemonCommand() {
fmt.Sprintf("\n\t%-30s", styleItalic.Render("Use a hyphen when typing a name with a space.")),
"\n\n",
styleBold.Render("FLAGS:"),
- fmt.Sprintf("\n\t%-30s %s", "-a, --abilities", "Prints out the Pokémon's abilities."),
- fmt.Sprintf("\n\t%-30s %s", "-t, --types", "Prints out the Pokémon's typing."),
- fmt.Sprintf("\n\t%-30s %s", "-h, --help", "Prints out the help menu."),
+ fmt.Sprintf("\n\t%-30s %s", "-a, --abilities", "Prints the Pokémon's abilities."),
+ fmt.Sprintf("\n\t%-30s %s", "-s, --stats", "Prints the Pokémon's base stats."),
+ fmt.Sprintf("\n\t%-30s %s", "-t, --types", "Prints the Pokémon's typing."),
+ fmt.Sprintf("\n\t%-30s %s", "-h, --help", "Prints the help menu."),
)
fmt.Println(helpMessage)
}
flag.Parse()
- pokeFlags, typesFlag, shortTypesFlag, abilitiesFlag, shortAbilitiesFlag := flags.SetupPokemonFlagSet()
+ pokeFlags, abilitiesFlag, shortAbilitiesFlag, statsFlag, shortStatsFlag, typesFlag, shortTypesFlag := flags.SetupPokemonFlagSet()
args := os.Args
@@ -50,10 +52,36 @@ func PokemonCommand() {
os.Exit(1)
}
- _, pokemonName, pokemonID := connections.PokemonApiCall(endpoint, pokemonName, "https://pokeapi.co/api/v2/")
+ _, pokemonName, pokemonID, pokemonWeight, pokemonHeight := connections.PokemonApiCall(endpoint, pokemonName, "https://pokeapi.co/api/v2/")
capitalizedString := cases.Title(language.English).String(pokemonName)
- fmt.Printf("Your selected Pokémon: %s\nNational Pokédex #: %d\n", capitalizedString, pokemonID)
+ // Weight calculation
+ weightKilograms := float64(pokemonWeight) / 10
+ weightPounds := float64(weightKilograms) * 2.20462
+
+ // Height calculation
+ heightMeters := float64(pokemonHeight) / 10
+ heightFeet := heightMeters * 3.28084
+ feet := int(heightFeet)
+ inches := int(math.Round((heightFeet - float64(feet)) * 12)) // Use math.Round to avoid truncation
+
+ // Adjust for rounding to 12 inches (carry over to the next foot)
+ if inches == 12 {
+ feet++
+ inches = 0
+ }
+
+ fmt.Printf(
+ "Your selected Pokémon: %s\nNational Pokédex #: %d\nWeight: %.1fkg (%.1f lbs)\nHeight: %.1fm (%d′%02d″)\n",
+ capitalizedString, pokemonID, weightKilograms, weightPounds, heightFeet, feet, inches,
+ )
+
+ if *abilitiesFlag || *shortAbilitiesFlag {
+ if err := flags.AbilitiesFlag(endpoint, pokemonName); err != nil {
+ fmt.Printf("Error: %s\n", err)
+ os.Exit(1)
+ }
+ }
if *typesFlag || *shortTypesFlag {
if err := flags.TypesFlag(endpoint, pokemonName); err != nil {
@@ -62,8 +90,8 @@ func PokemonCommand() {
}
}
- if *abilitiesFlag || *shortAbilitiesFlag {
- if err := flags.AbilitiesFlag(endpoint, pokemonName); err != nil {
+ if *statsFlag || *shortStatsFlag {
+ if err := flags.StatsFlag(endpoint, pokemonName); err != nil {
fmt.Printf("Error: %s\n", err)
os.Exit(1)
}
diff --git a/cmd/pokemon_test.go b/cmd/pokemon_test.go
index 7eb5140..ed4b723 100644
--- a/cmd/pokemon_test.go
+++ b/cmd/pokemon_test.go
@@ -76,13 +76,6 @@ func TestPokemonCommand(t *testing.T) {
t.Fatalf("Failed to read from pipe: %v", readErr)
}
- // Define expected output based on actual API response
- expectedName := "Bulbasaur"
- expectedID := "1"
-
// Assert output contains expected Pokémon details
- assert.Contains(t, output.String(), "Your selected Pokémon:", "Output should contain Pokémon details header")
- assert.Contains(t, output.String(), expectedName, "Output should contain the Pokémon name")
- assert.Contains(t, output.String(), "National Pokédex #:", "Output should contain Pokémon ID header")
- assert.Contains(t, output.String(), expectedID, "Output should contain the Pokémon ID")
+ assert.Equal(t, output.String(), "Your selected Pokémon: Bulbasaur\nNational Pokédex #: 1\nWeight: 6.9kg (15.2 lbs)\nHeight: 2.3m (2′04″)\n")
}
diff --git a/cmd/validateargs.go b/cmd/validateargs.go
index 16c4d91..5355e87 100644
--- a/cmd/validateargs.go
+++ b/cmd/validateargs.go
@@ -31,7 +31,7 @@ func ValidatePokemonArgs(args []string) error {
return fmt.Errorf("%s", errMessage)
}
- if len(args) > 5 {
+ if len(args) > 6 {
errMessage := errorBorder.Render(errorColor.Render("Error!"), "\nToo many arguments")
return fmt.Errorf("%s", errMessage)
}
diff --git a/connections/connection.go b/connections/connection.go
index fab11e8..df2c12f 100644
--- a/connections/connection.go
+++ b/connections/connection.go
@@ -11,15 +11,10 @@ import (
)
type PokemonJSONStruct struct {
- Name string `json:"name"`
- ID int `json:"id"`
- Types []struct {
- Slot int `json:"slot"`
- Type struct {
- Name string `json:"name"`
- URL string `json:"url"`
- } `json:"type"`
- } `json:"types"`
+ Name string `json:"name"`
+ ID int `json:"id"`
+ Weight int `json:"weight"`
+ Height int `json:"height"`
Abilities []struct {
Ability struct {
Name string `json:"name"`
@@ -28,6 +23,19 @@ type PokemonJSONStruct struct {
Hidden bool `json:"hidden"`
Slot int `json:"slot"`
} `json:"abilities"`
+ Types []struct {
+ Slot int `json:"slot"`
+ Type struct {
+ Name string `json:"name"`
+ URL string `json:"url"`
+ } `json:"type"`
+ } `json:"types"`
+ Stats []struct {
+ BaseStat int `json:"base_stat"`
+ Stat struct {
+ Name string `json:"name"`
+ } `json:"stat"`
+ } `json:"stats"`
}
type TypesJSONStruct struct {
@@ -102,17 +110,17 @@ func ApiCallSetup(url string, target interface{}) error {
return nil
}
-func PokemonApiCall(endpoint string, pokemonName string, baseURL string) (PokemonJSONStruct, string, int) {
+func PokemonApiCall(endpoint string, pokemonName string, baseURL string) (PokemonJSONStruct, string, int, int, int) {
url := baseURL + endpoint + "/" + pokemonName
var pokemonStruct PokemonJSONStruct
err := ApiCallSetup(url, &pokemonStruct)
if err != nil {
- return PokemonJSONStruct{}, "", 0
+ return PokemonJSONStruct{}, "", 0, 0, 0
}
- return pokemonStruct, pokemonStruct.Name, pokemonStruct.ID
+ return pokemonStruct, pokemonStruct.Name, pokemonStruct.ID, pokemonStruct.Weight, pokemonStruct.Height
}
func TypesApiCall(endpoint string, typesName string, baseURL string) (TypesJSONStruct, string, int) {
diff --git a/connections/connection_test.go b/connections/connection_test.go
index b2e0cf5..05f2f9d 100644
--- a/connections/connection_test.go
+++ b/connections/connection_test.go
@@ -9,8 +9,8 @@ import (
"testing"
)
-// TestBaseApiCallSuccess - Test for the ApiCallSetup function
-func TestBaseApiCallSuccess(t *testing.T) {
+// TestBaseApiCall - Test for the ApiCallSetup function
+func TestBaseApiCall(t *testing.T) {
expectedData := map[string]string{"key": "value"}
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -30,11 +30,13 @@ func TestBaseApiCallSuccess(t *testing.T) {
assert.Equal(t, expectedData, target)
}
-// TestPokemonApiCallSuccess - Test for the PokemonApiCall function
-func TestPokemonApiCallSuccess(t *testing.T) {
+// TestPokemonApiCall - Test for the PokemonApiCall function
+func TestPokemonApiCall(t *testing.T) {
expectedPokemon := PokemonJSONStruct{
- Name: "pikachu",
- ID: 25,
+ Name: "pikachu",
+ ID: 25,
+ Weight: 60,
+ Height: 4,
Types: []struct {
Slot int `json:"slot"`
Type struct {
@@ -56,15 +58,17 @@ func TestPokemonApiCallSuccess(t *testing.T) {
}))
defer ts.Close()
- pokemon, name, id := PokemonApiCall("/pokemon", "pikachu", ts.URL)
+ pokemon, name, id, weight, height := PokemonApiCall("/pokemon", "pikachu", ts.URL)
assert.Equal(t, expectedPokemon, pokemon)
assert.Equal(t, "pikachu", name)
assert.Equal(t, 25, id)
+ assert.Equal(t, 60, weight)
+ assert.Equal(t, 4, height)
}
-// TestTypesApiCallSuccess - Test for the TypesApiCall function
-func TestTypesApiCallSuccess(t *testing.T) {
+// TestTypesApiCall - Test for the TypesApiCall function
+func TestTypesApiCall(t *testing.T) {
expectedTypes := TypesJSONStruct{
Name: "electric",
ID: 13,
diff --git a/demo.gif b/demo.gif
index 2b2d24c..c5792bb 100644
Binary files a/demo.gif and b/demo.gif differ
diff --git a/demo.tape b/demo.tape
index 1d195ca..16eccb7 100644
--- a/demo.tape
+++ b/demo.tape
@@ -62,9 +62,9 @@ Require echo
Set Shell "bash"
Set FontSize 32
Set Width 2100
-Set Height 825
+Set Height 1100
-Type "poke-cli pokemon charizard --types --abilities"
+Type "poke-cli pokemon charizard --abilities --stats --types"
Sleep 1s
diff --git a/flags/pokemonflagset.go b/flags/pokemonflagset.go
index 28431ec..81550f8 100644
--- a/flags/pokemonflagset.go
+++ b/flags/pokemonflagset.go
@@ -7,6 +7,7 @@ import (
"fmt"
"github.com/charmbracelet/lipgloss"
"github.com/digitalghost-dev/poke-cli/connections"
+ "strings"
)
var (
@@ -16,38 +17,47 @@ var (
styleBold = lipgloss.NewStyle().Bold(true)
)
-func SetupPokemonFlagSet() (*flag.FlagSet, *bool, *bool, *bool, *bool) {
+func header(header string) {
+ HeaderBold := lipgloss.NewStyle().
+ BorderStyle(lipgloss.NormalBorder()).
+ BorderForeground(lipgloss.Color("#FFCC00")).
+ BorderTop(true).
+ Bold(true).
+ Render(header)
+
+ fmt.Println(HeaderBold)
+}
+
+func SetupPokemonFlagSet() (*flag.FlagSet, *bool, *bool, *bool, *bool, *bool, *bool) {
pokeFlags := flag.NewFlagSet("pokeFlags", flag.ExitOnError)
- typesFlag := pokeFlags.Bool("types", false, "Print the declared Pokémon's typing")
- shortTypesFlag := pokeFlags.Bool("t", false, "Prints the declared Pokémon's typing")
+ abilitiesFlag := pokeFlags.Bool("abilities", false, "Print the Pokémon's abilities")
+ shortAbilitiesFlag := pokeFlags.Bool("a", false, "Print the Pokémon's abilities")
+
+ statsFlag := pokeFlags.Bool("stats", false, "Print the Pokémon's base stats")
+ shortStatsFlag := pokeFlags.Bool("s", false, "Print the Pokémon's base stats")
- abilitiesFlag := pokeFlags.Bool("abilities", false, "Print the declared Pokémon's abilities")
- shortAbilitiesFlag := pokeFlags.Bool("a", false, "Print the declared Pokémon's abilities")
+ typesFlag := pokeFlags.Bool("types", false, "Print the Pokémon's typing")
+ shortTypesFlag := pokeFlags.Bool("t", false, "Prints the Pokémon's typing")
pokeFlags.Usage = func() {
fmt.Println(
helpBorder.Render("poke-cli pokemon [flags]",
styleBold.Render("\n\nFLAGS:"), "\n\t", "-a, --abilities", "\t", "Prints out the Pokémon's abilities.",
- "\n\t", "-t, --types", "\t\t", "Prints out the Pokémon's typing."),
+ "\n\t", "-t, --types", "\t\t", "Prints out the Pokémon's typing.", "\n\t", "-s, --stats", "\t\t",
+ "Prints out the Pokémon's base stats."),
)
}
- return pokeFlags, typesFlag, shortTypesFlag, abilitiesFlag, shortAbilitiesFlag
+ return pokeFlags, abilitiesFlag, shortAbilitiesFlag, statsFlag, shortStatsFlag, typesFlag, shortTypesFlag
}
func AbilitiesFlag(endpoint string, pokemonName string) error {
baseURL := "https://pokeapi.co/api/v2/"
- pokemonStruct, _, _ := connections.PokemonApiCall(endpoint, pokemonName, baseURL)
+ pokemonStruct, _, _, _, _ := connections.PokemonApiCall(endpoint, pokemonName, baseURL)
- abilitiesHeaderBold := lipgloss.NewStyle().
- BorderStyle(lipgloss.NormalBorder()).
- BorderForeground(lipgloss.Color("#FFCC00")).
- BorderTop(true).
- Bold(true).
- Render("Abilities")
+ header("Abilities")
- fmt.Println(abilitiesHeaderBold)
for _, pokeAbility := range pokemonStruct.Abilities {
if pokeAbility.Slot == 1 {
fmt.Printf("Ability %d: %s\n", pokeAbility.Slot, pokeAbility.Ability.Name)
@@ -61,9 +71,88 @@ func AbilitiesFlag(endpoint string, pokemonName string) error {
return nil
}
+func StatsFlag(endpoint string, pokemonName string) error {
+ baseURL := "https://pokeapi.co/api/v2/"
+ pokemonStruct, _, _, _, _ := connections.PokemonApiCall(endpoint, pokemonName, baseURL)
+
+ header("Base Stats")
+
+ // Helper function to map stat values to categories
+ getStatCategory := func(value int) string {
+ switch {
+ case value < 20:
+ return "lowest"
+ case value < 60:
+ return "lower"
+ case value < 90:
+ return "low"
+ case value < 120:
+ return "high"
+ case value < 150:
+ return "higher"
+ default:
+ return "highest"
+ }
+ }
+
+ // Helper function to print the bar for a stat
+ printBar := func(label string, value, maxWidth, maxValue int, style lipgloss.Style) {
+ scaledValue := (value * maxWidth) / maxValue
+ bar := strings.Repeat("▇", scaledValue)
+ coloredBar := style.Render(bar)
+ fmt.Printf("%-10s %s %d\n", label, coloredBar, value)
+ }
+
+ // Mapping from API stat names to custom display names
+ nameMapping := map[string]string{
+ "hp": "HP",
+ "attack": "Atk",
+ "defense": "Def",
+ "special-attack": "Sp. Atk",
+ "special-defense": "Sp. Def",
+ "speed": "Speed",
+ }
+
+ statColorMap := map[string]string{
+ "lowest": "#F34444",
+ "lower": "#FF7F0F",
+ "low": "#FFDD57",
+ "high": "#A0E515",
+ "higher": "#22C65A",
+ "highest": "#00C2B8",
+ }
+
+ // Find the maxium stat value
+ maxValue := 0
+ for _, stat := range pokemonStruct.Stats {
+ if stat.BaseStat > maxValue {
+ maxValue = stat.BaseStat
+ }
+ }
+
+ maxWidth := 45
+
+ // Print bars for each stat
+ for _, stat := range pokemonStruct.Stats {
+ apiName := stat.Stat.Name
+ customName, exists := nameMapping[apiName]
+ if !exists {
+ continue
+ }
+
+ category := getStatCategory(stat.BaseStat)
+ color := statColorMap[category]
+ style := lipgloss.NewStyle().Foreground(lipgloss.Color(color))
+
+ printBar(customName, stat.BaseStat, maxWidth, maxValue, style)
+ }
+
+ return nil
+}
+
func TypesFlag(endpoint string, pokemonName string) error {
baseURL := "https://pokeapi.co/api/v2/"
- pokemonStruct, _, _ := connections.PokemonApiCall(endpoint, pokemonName, baseURL)
+ pokemonStruct, _, _, _, _ := connections.PokemonApiCall(endpoint, pokemonName, baseURL)
colorMap := map[string]string{
"normal": "#B7B7A9",
@@ -86,14 +175,8 @@ func TypesFlag(endpoint string, pokemonName string) error {
"fairy": "#EE99EE",
}
- typingHeaderBold := lipgloss.NewStyle().
- BorderStyle(lipgloss.NormalBorder()).
- BorderForeground(lipgloss.Color("#FFCC00")).
- BorderTop(true).
- Bold(true).
- Render("Typing")
+ header("Typing")
- fmt.Println(typingHeaderBold)
for _, pokeType := range pokemonStruct.Types {
colorHex, exists := colorMap[pokeType.Type.Name]
if exists {
diff --git a/flags/pokemonflagset_test.go b/flags/pokemonflagset_test.go
index aaa1569..8fd797e 100644
--- a/flags/pokemonflagset_test.go
+++ b/flags/pokemonflagset_test.go
@@ -4,18 +4,32 @@ import (
"bytes"
"github.com/stretchr/testify/assert"
"os"
+ "regexp"
"testing"
)
+func stripANSI(input string) string {
+ ansiRegex := regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)
+ return ansiRegex.ReplaceAllString(input, "")
+}
+
func TestSetupPokemonFlagSet(t *testing.T) {
// Call the function to get the flag set and types flag
- pokeFlags, typesFlag, shortTypesFlag, abilitiesFlag, shortAbilitiesFlag := SetupPokemonFlagSet()
+ pokeFlags, abilitiesFlag, shortAbilitiesFlag, statsFlag, shortStatsFlag, typesFlag, shortTypesFlag := SetupPokemonFlagSet()
// Assertions
assert.NotNil(t, pokeFlags, "Flag set should not be nil")
assert.Equal(t, "pokeFlags", pokeFlags.Name(), "Flag set name should be 'pokeFlags'")
//assert.Equal(t, flag.ExitOnError, pokeFlags.NFlag(), "Flag set should have ExitOnError behavior")
+ // Check abilities flag
+ assert.NotNil(t, abilitiesFlag, "Abilities flag should not be nil")
+ assert.Equal(t, false, *abilitiesFlag, "Abilities flag name should be 'abilities'")
+
+ // Check short abilities flag
+ assert.NotNil(t, shortAbilitiesFlag, "Short abilities flag should not be nil")
+ assert.Equal(t, false, *shortAbilitiesFlag, "Short abilities flag name should be 'a'")
+
// Check types flag
assert.NotNil(t, typesFlag, "Types flag should not be nil")
assert.Equal(t, false, *typesFlag, "Types flag name should be 'types'")
@@ -25,12 +39,12 @@ func TestSetupPokemonFlagSet(t *testing.T) {
assert.Equal(t, false, *shortTypesFlag, "Short types flag name should be 't'")
// Check abilities flag
- assert.NotNil(t, abilitiesFlag, "Abilities flag should not be nil")
- assert.Equal(t, false, *abilitiesFlag, "Abilities flag name should be 'abilities'")
+ assert.NotNil(t, statsFlag, "Stats flag should not be nil")
+ assert.Equal(t, false, *statsFlag, "Stats flag name should be 'abilities'")
// Check short abilities flag
- assert.NotNil(t, shortAbilitiesFlag, "Short abilities flag should not be nil")
- assert.Equal(t, false, *shortAbilitiesFlag, "Short abilities flag name should be 'a'")
+ assert.NotNil(t, shortStatsFlag, "Short stats flag should not be nil")
+ assert.Equal(t, false, *shortStatsFlag, "Short stats flag name should be 'a'")
}
func TestAbilitiesFlag(t *testing.T) {
@@ -65,10 +79,51 @@ Hidden Ability: chlorophyll
`
// Assert the actual output matches the expected output
- assert.Contains(t, output.String(), "Abilities", "Output should contain 'Abilities'")
- assert.Contains(t, output.String(), "Ability 1: overgrow", "Output should contain 'Ability 1: overgrow'")
- assert.Contains(t, output.String(), "Hidden Ability: chlorophyll", "Output should contain 'Ability 2: chlorophyll'")
- assert.Equal(t, expectedOutput, output.String(), "Output does not match the expected formatting")
+ actualOutput := stripANSI(output.String())
+
+ assert.Equal(t, expectedOutput, actualOutput, "Output should contain data for the abilities flag")
+}
+
+func TestStatsFlag(t *testing.T) {
+ // Capture standard output
+ var output bytes.Buffer
+ stdout := os.Stdout
+ r, w, _ := os.Pipe()
+ os.Stdout = w
+
+ // Call the StatsFlag function with a valid Pokémon
+ err := StatsFlag("pokemon", "bulbasaur")
+
+ // Close and restore stdout
+ if closeErr := w.Close(); closeErr != nil {
+ t.Fatalf("Failed to close pipe writer: %v", closeErr)
+ }
+ os.Stdout = stdout
+
+ _, readErr := output.ReadFrom(r)
+ if readErr != nil {
+ t.Fatalf("Failed to read from pipe: %v", readErr)
+ }
+
+ // Assert no errors occurred
+ assert.NoError(t, err, "StatsFlag should not return an error for a valid Pokémon")
+
+ // Define expected output components
+ expectedOutput := `──────────
+Base Stats
+HP ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 45
+Atk ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 49
+Def ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 49
+Sp. Atk ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 65
+Sp. Def ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 65
+Speed ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 45
+`
+
+ // Assert output contains the expected header and typing information
+ actualOutput := stripANSI(output.String())
+
+ assert.Equal(t, expectedOutput, actualOutput, "Output should contain data for the stats flag")
+
}
func TestTypesFlag(t *testing.T) {
@@ -96,12 +151,14 @@ func TestTypesFlag(t *testing.T) {
assert.NoError(t, err, "TypesFlag should not return an error for a valid Pokémon")
// Define expected output components
- expectedHeader := "Typing"
- expectedType1 := "Type 1: grass"
- expectedType2 := "Type 2: poison"
+ expectedOutput := `──────
+Typing
+Type 1: grass
+Type 2: poison
+`
// Assert output contains the expected header and typing information
- assert.Contains(t, output.String(), expectedHeader, "Output should contain the 'Typing' header")
- assert.Contains(t, output.String(), expectedType1, "Output should contain the Pokémon's first type")
- assert.Contains(t, output.String(), expectedType2, "Output should contain the Pokémon's second type")
+ actualOutput := stripANSI(output.String())
+
+ assert.Equal(t, expectedOutput, actualOutput, "Output should contain data for the types flag")
}