Skip to content

Commit c56f096

Browse files
Merge pull request #73 from digitalghost-dev/0.7.2
0.7.2
2 parents b836db0 + a7382b6 commit c56f096

File tree

12 files changed

+272
-110
lines changed

12 files changed

+272
-110
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ on:
2121
branches:
2222
- main
2323
env:
24-
VERSION_NUMBER: 'v0.7.1'
24+
VERSION_NUMBER: 'v0.7.2'
2525
REGISTRY_NAME: digitalghostdev/poke-cli
2626

2727
jobs:

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<img height="250" width="350" src="https://cdn.simpleicons.org/pokemon/FFCC00" alt="pokemon-logo"/>
33
<h1>Pokémon CLI</h1>
44
<img src="https://img.shields.io/github/v/release/digitalghost-dev/poke-cli?style=flat-square&logo=git&logoColor=FFCC00&label=Release%20Version&labelColor=EEE&color=FFCC00" alt="version-label">
5-
<img src="https://img.shields.io/docker/image-size/digitalghostdev/poke-cli/v0.7.1?arch=arm64&style=flat-square&logo=docker&logoColor=FFCC00&labelColor=EEE&color=FFCC00" alt="docker-image-size">
5+
<img src="https://img.shields.io/docker/image-size/digitalghostdev/poke-cli/v0.7.2?arch=arm64&style=flat-square&logo=docker&logoColor=FFCC00&labelColor=EEE&color=FFCC00" alt="docker-image-size">
66
<img src="https://img.shields.io/github/actions/workflow/status/digitalghost-dev/poke-cli/ci.yml?branch=main&style=flat-square&logo=github&logoColor=FFCC00&label=CI&labelColor=EEE&color=FFCC00">
77
</div>
88

@@ -40,7 +40,7 @@ _Taskfile can build the executable for you_
4040
_Use a Docker Image_
4141

4242
```bash
43-
docker run --rm -it digitalghostdev/poke-cli:v0.7.1 [command] [subcommand] [flag]
43+
docker run --rm -it digitalghostdev/poke-cli:v0.7.2 [command] [subcommand] [flag]
4444
```
4545

4646
### Go Build

cli_test.go

Lines changed: 77 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -2,67 +2,63 @@ package main
22

33
import (
44
"bytes"
5-
"fmt"
6-
"io"
75
"os"
86
"regexp"
97
"testing"
108
)
119

12-
// Strip ANSI color codes
1310
var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*m`)
1411

15-
func stripANSI(input string) string {
16-
return ansiRegex.ReplaceAllString(input, "")
17-
}
12+
func captureOutput(f func()) string {
13+
var buf bytes.Buffer
14+
stdout := os.Stdout
15+
r, w, _ := os.Pipe()
16+
os.Stdout = w
1817

19-
func TestMainFunction(t *testing.T) {
20-
version := "v0.7.0"
18+
f()
2119

22-
// Backup the original exit function and stdout/stderr
23-
originalExit := exit
24-
originalStdout := os.Stdout
25-
originalStderr := os.Stderr
26-
defer func() {
27-
exit = originalExit // Restore exit
28-
os.Stdout = originalStdout // Restore stdout
29-
os.Stderr = originalStderr // Restore stderr
30-
}()
20+
_ = w.Close()
21+
os.Stdout = stdout
22+
_, _ = buf.ReadFrom(r)
3123

32-
// Replace exit with a function that captures the exit code
33-
exitCode := 0
34-
exit = func(code int) { exitCode = code }
24+
return buf.String()
25+
}
3526

27+
func stripANSI(input string) string {
28+
return ansiRegex.ReplaceAllString(input, "")
29+
}
30+
31+
func TestRunCLI(t *testing.T) {
3632
tests := []struct {
33+
name string
3734
args []string
3835
expectedOutput string
39-
expectedExit int
36+
expectedCode int
4037
}{
4138
{
42-
args: []string{"pokemons"},
39+
name: "No Arguments",
40+
args: []string{},
4341
expectedOutput: "╭──────────────────────────────────────────────────────╮\n" +
44-
"│Error! │\n" +
45-
"│ 'pokemons' is not a valid command. │\n" +
42+
"│Welcome! This tool displays data related to Pokémon! │\n" +
4643
"│ │\n" +
47-
"│Available Commands: │\n" +
44+
"│ USAGE: │\n" +
45+
"│ poke-cli [flag] │\n" +
46+
"│ poke-cli <command> [flag] │\n" +
47+
"│ poke-cli <command> <subcommand> [flag] │\n" +
48+
"│ │\n" +
49+
"│ FLAGS: │\n" +
50+
"│ -h, --help Shows the help menu │\n" +
51+
"│ -l, --latest Prints the latest available │\n" +
52+
"│ version of the program │\n" +
53+
"│ │\n" +
54+
"│ AVAILABLE COMMANDS: │\n" +
4855
"│ pokemon Get details of a specific Pokémon │\n" +
4956
"│ types Get details of a specific typing │\n" +
50-
"│ │\n" +
51-
"│Also run [poke-cli -h] for more info! │\n" +
5257
"╰──────────────────────────────────────────────────────╯\n",
53-
expectedExit: 1,
54-
},
55-
{
56-
args: []string{"-l"},
57-
expectedOutput: fmt.Sprintf("Latest Docker image version: %s\nLatest release tag: %s\n", version, version),
58-
expectedExit: 0,
59-
},
60-
{
61-
args: []string{"--latest"},
62-
expectedOutput: fmt.Sprintf("Latest Docker image version: %s\nLatest release tag: %s\n", version, version),
63-
expectedExit: 0,
58+
expectedCode: 0,
6459
},
6560
{
61+
name: "Help Flag Short",
6662
args: []string{"-h"},
6763
expectedOutput: "╭──────────────────────────────────────────────────────╮\n" +
6864
"│Welcome! This tool displays data related to Pokémon! │\n" +
@@ -81,64 +77,59 @@ func TestMainFunction(t *testing.T) {
8177
"│ pokemon Get details of a specific Pokémon │\n" +
8278
"│ types Get details of a specific typing │\n" +
8379
"╰──────────────────────────────────────────────────────╯\n",
84-
expectedExit: 0,
85-
},
86-
{
87-
args: []string{"pokemon", "kingambit"},
88-
expectedOutput: "Your selected Pokémon: Kingambit\nNational Pokédex #: 983\n",
89-
expectedExit: 0,
80+
expectedCode: 0,
9081
},
9182
{
92-
args: []string{"pokemon", "cradily", "--types"},
93-
expectedOutput: "Your selected Pokémon: Cradily\nNational Pokédex #: 346\n──────\nTyping\nType 1: rock\nType 2: grass\n",
94-
expectedExit: 0,
83+
name: "Help Flag Long",
84+
args: []string{"--help"},
85+
expectedOutput: "╭──────────────────────────────────────────────────────╮\n" +
86+
"│Welcome! This tool displays data related to Pokémon! │\n" +
87+
"│ │\n" +
88+
"│ USAGE: │\n" +
89+
"│ poke-cli [flag] │\n" +
90+
"│ poke-cli <command> [flag] │\n" +
91+
"│ poke-cli <command> <subcommand> [flag] │\n" +
92+
"│ │\n" +
93+
"│ FLAGS: │\n" +
94+
"│ -h, --help Shows the help menu │\n" +
95+
"│ -l, --latest Prints the latest available │\n" +
96+
"│ version of the program │\n" +
97+
"│ │\n" +
98+
"│ AVAILABLE COMMANDS: │\n" +
99+
"│ pokemon Get details of a specific Pokémon │\n" +
100+
"│ types Get details of a specific typing │\n" +
101+
"╰──────────────────────────────────────────────────────╯\n",
102+
expectedCode: 0,
95103
},
96104
{
97-
args: []string{"pokemon", "giratina-altered", "--abilities"},
98-
expectedOutput: "Your selected Pokémon: Giratina-Altered\nNational Pokédex #: 487\n─────────\nAbilities\nAbility 1: pressure\nHidden Ability: telepathy\n",
99-
expectedExit: 0,
105+
name: "Invalid Command",
106+
args: []string{"invalid"},
107+
expectedOutput: "Error!",
108+
expectedCode: 1,
100109
},
101110
{
102-
args: []string{"pokemon", "coPPeraJAH", "-t", "-a"},
103-
expectedOutput: "Your selected Pokémon: Copperajah\nNational Pokédex #: 879\n──────\nTyping\nType 1: steel\n─────────\nAbilities\nAbility 1: sheer-force\nHidden Ability: heavy-metal\n",
104-
expectedExit: 0,
111+
name: "Latest Flag",
112+
args: []string{"-l"},
113+
expectedOutput: "Latest Docker image version: v0.7.1\nLatest release tag: v0.7.1\n",
114+
expectedCode: 0,
105115
},
106116
}
107117

108-
for _, test := range tests {
109-
// Create a pipe to capture output
110-
r, w, _ := os.Pipe()
111-
os.Stdout = w
112-
os.Stderr = w
113-
114-
// Set os.Args for the test case
115-
os.Args = append([]string{"poke-cli"}, test.args...)
116-
117-
// Run the main function
118-
main()
119-
120-
// Close the writer and restore stdout and stderr
121-
err := w.Close()
122-
if err != nil {
123-
t.Fatalf("Error closing pipe writer: %v", err)
124-
}
125-
os.Stdout = originalStdout
126-
os.Stderr = originalStderr
127-
128-
// Read from the pipe
129-
var buf bytes.Buffer
130-
if _, err := io.Copy(&buf, r); err != nil {
131-
t.Errorf("Error copying output: %v", err)
132-
}
118+
for _, tt := range tests {
119+
t.Run(tt.name, func(t *testing.T) {
120+
exit = func(code int) {}
121+
output := captureOutput(func() {
122+
code := runCLI(tt.args)
123+
if code != tt.expectedCode {
124+
t.Errorf("Expected exit code %d, got %d", tt.expectedCode, code)
125+
}
126+
})
133127

134-
// Strip ANSI color codes from the actual output
135-
actualOutput := stripANSI(buf.String())
136-
if actualOutput != test.expectedOutput {
137-
t.Errorf("Args: %v\nExpected output: %q\nGot: %q\n", test.args, test.expectedOutput, actualOutput)
138-
}
128+
output = stripANSI(output)
139129

140-
if exitCode != test.expectedExit {
141-
t.Errorf("Args: %v\nExpected exit code: %d\nGot: %d\n", test.args, test.expectedExit, exitCode)
142-
}
130+
if !bytes.Contains([]byte(output), []byte(tt.expectedOutput)) {
131+
t.Errorf("Expected output to contain %q, got %q", tt.expectedOutput, output)
132+
}
133+
})
143134
}
144135
}

cmd/pokemon_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package cmd
22

33
import (
4+
"bytes"
45
"github.com/stretchr/testify/assert"
6+
"os"
57
"testing"
68
)
79

@@ -49,3 +51,38 @@ func TestValidatePokemonArgs_TooManyArgs(t *testing.T) {
4951
assert.NotEqual(t, expectedError, err.Error())
5052
}
5153
}
54+
55+
func TestPokemonCommand(t *testing.T) {
56+
// Capture standard output
57+
var output bytes.Buffer
58+
stdout := os.Stdout
59+
r, w, _ := os.Pipe()
60+
os.Stdout = w
61+
62+
// Set up test arguments (focus only on Pokémon name and command)
63+
os.Args = []string{"poke-cli", "pokemon", "bulbasaur"}
64+
65+
// Call the function
66+
PokemonCommand()
67+
68+
// Close and restore stdout
69+
if closeErr := w.Close(); closeErr != nil {
70+
t.Fatalf("Failed to close pipe writer: %v", closeErr)
71+
}
72+
os.Stdout = stdout
73+
74+
_, readErr := output.ReadFrom(r)
75+
if readErr != nil {
76+
t.Fatalf("Failed to read from pipe: %v", readErr)
77+
}
78+
79+
// Define expected output based on actual API response
80+
expectedName := "Bulbasaur"
81+
expectedID := "1"
82+
83+
// Assert output contains expected Pokémon details
84+
assert.Contains(t, output.String(), "Your selected Pokémon:", "Output should contain Pokémon details header")
85+
assert.Contains(t, output.String(), expectedName, "Output should contain the Pokémon name")
86+
assert.Contains(t, output.String(), "National Pokédex #:", "Output should contain Pokémon ID header")
87+
assert.Contains(t, output.String(), expectedID, "Output should contain the Pokémon ID")
88+
}

cmd/styles.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,10 @@ var (
3838
"fairy": "#EE99EE",
3939
}
4040
)
41+
42+
// Helper function to get color for a given type name from colorMap
43+
func getTypeColor(typeName string) string {
44+
color := colorMap[typeName]
45+
46+
return color
47+
}

cmd/styles_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package cmd
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"testing"
6+
)
7+
8+
func TestGetTypeColor(t *testing.T) {
9+
// Test known types
10+
for typeName, expectedColor := range colorMap {
11+
t.Run(typeName, func(t *testing.T) {
12+
color := getTypeColor(typeName)
13+
assert.Equal(t, expectedColor, color, "Expected color for type %s to be %s", typeName, expectedColor)
14+
})
15+
}
16+
17+
// Test unknown type
18+
t.Run("unknown type", func(t *testing.T) {
19+
color := getTypeColor("unknown")
20+
assert.Equal(t, "", color, "Expected color for unknown type to be an empty string")
21+
})
22+
}

cmd/types.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,6 @@ func (m model) View() string {
5151
return "Select a type! Hit 'Q' or 'CTRL-C' to quit.\n" + typesTableBorder.Render(m.table.View()) + "\n"
5252
}
5353

54-
// Helper function to get color for a given type name from colorMap
55-
func getTypeColor(typeName string) string {
56-
color := colorMap[typeName]
57-
58-
return color
59-
}
60-
6154
// Function to display type details after a type is selected
6255
func displayTypeDetails(typesName string, endpoint string) {
6356

cmd/types_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,27 @@ func TestValidateTypesArgs_TooManyArgs(t *testing.T) {
2929
assert.NotEqual(t, expectedError, err.Error())
3030
}
3131
}
32+
33+
func TestModelInit(t *testing.T) {
34+
m := model{}
35+
result := m.Init()
36+
37+
assert.Nil(t, result, "Expected Init() to return nil")
38+
}
39+
40+
func TestModelView_SelectedOption(t *testing.T) {
41+
m := model{selectedOption: "someOption"}
42+
43+
output := m.View()
44+
45+
assert.Equal(t, "", output, "Expected output to be an empty string when selectedOption is set")
46+
}
47+
48+
func TestModelView_DisplayTable(t *testing.T) {
49+
m := model{selectedOption: ""}
50+
expectedOutput := "Select a type! Hit 'Q' or 'CTRL-C' to quit.\n" + typesTableBorder.Render(m.table.View()) + "\n"
51+
52+
output := m.View()
53+
54+
assert.Equal(t, expectedOutput, output, "Expected View output to include table view")
55+
}

connections/connection.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,12 @@ type TypesJSONStruct struct {
6868
} `json:"damage_relations"`
6969
}
7070

71-
var httpGet = http.Get
7271
var red = lipgloss.Color("#F2055C")
7372
var errorColor = lipgloss.NewStyle().Foreground(red)
7473

7574
// ApiCallSetup Helper function to handle API calls and JSON unmarshalling
7675
func ApiCallSetup(url string, target interface{}) error {
77-
res, err := httpGet(url)
76+
res, err := http.Get(url)
7877
if err != nil {
7978
return fmt.Errorf("error making GET request: %w", err)
8079
}

0 commit comments

Comments
 (0)