Skip to content

Commit 73da8da

Browse files
Merge pull request #59 from digitalghost-dev/0.6.5
0.6.5
2 parents efe7ab0 + f662bd2 commit 73da8da

File tree

5 files changed

+96
-130
lines changed

5 files changed

+96
-130
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.6.4'
24+
VERSION_NUMBER: 'v0.6.5'
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.6.4?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.6.5?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.6.3 [command] [subcommand] [flag]
43+
docker run --rm -it digitalghostdev/poke-cli:v0.6.5 [command] [subcommand] [flag]
4444
```
4545

4646
### Go Build

cli.go

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ var (
2020
BorderForeground(lipgloss.Color("#F2055C"))
2121
)
2222

23-
func main() {
24-
latestFlag := flag.Bool("latest", false, "Prints the program's latest Docker Image and Release versions.")
25-
shortLatestFlag := flag.Bool("l", false, "Prints the program's latest Docker Image and Release versions.")
23+
func runCLI(args []string) int {
24+
mainFlagSet := flag.NewFlagSet("poke-cli", flag.ContinueOnError)
25+
latestFlag := mainFlagSet.Bool("latest", false, "Prints the program's latest Docker Image and Release versions.")
26+
shortLatestFlag := mainFlagSet.Bool("l", false, "Prints the program's latest Docker Image and Release versions.")
2627

27-
flag.Usage = func() {
28+
mainFlagSet.Usage = func() {
2829
helpMessage := helpBorder.Render(
2930
"Welcome! This tool displays data related to Pokémon!",
3031
"\n\n", styleBold.Render("USAGE:"),
@@ -42,19 +43,33 @@ func main() {
4243
fmt.Println(helpMessage)
4344
}
4445

45-
flag.Parse()
46+
// Check for help flag manually
47+
for _, arg := range args {
48+
if arg == "-h" || arg == "--help" {
49+
mainFlagSet.Usage()
50+
return 0
51+
}
52+
}
53+
54+
err := mainFlagSet.Parse(args)
55+
if err != nil {
56+
return 2
57+
}
4658

4759
commands := map[string]func(){
4860
"pokemon": cmd.PokemonCommand,
4961
"types": cmd.TypesCommand,
5062
}
5163

5264
if len(os.Args) < 2 {
53-
flag.Usage()
65+
mainFlagSet.Usage()
66+
return 1
5467
} else if *latestFlag || *shortLatestFlag {
5568
flags.LatestFlag()
69+
return 0
5670
} else if cmdFunc, exists := commands[os.Args[1]]; exists {
5771
cmdFunc()
72+
return 0
5873
} else {
5974
errMessage := errorBorder.Render(
6075
errorColor.Render("Error!"),
@@ -64,5 +79,12 @@ func main() {
6479
fmt.Sprintf("\nAlso run %s for more info!", styleBold.Render("[poke-cli -h]")),
6580
)
6681
fmt.Printf("%s\n", errMessage)
82+
return 1
6783
}
6884
}
85+
86+
var exit = os.Exit // Default to os.Exit, but you can override this in tests
87+
88+
func main() {
89+
exit(runCLI(os.Args[1:]))
90+
}

cli_test.go

Lines changed: 59 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,37 @@ package main
22

33
import (
44
"bytes"
5-
"os/exec"
5+
"fmt"
6+
"io"
7+
"os"
8+
"regexp"
69
"testing"
710
)
811

9-
func TestCLI(t *testing.T) {
12+
// Strip ANSI color codes
13+
var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*m`)
14+
15+
func stripANSI(input string) string {
16+
return ansiRegex.ReplaceAllString(input, "")
17+
}
18+
19+
func TestMainFunction(t *testing.T) {
20+
version := "v0.6.4"
21+
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+
}()
31+
32+
// Replace exit with a function that captures the exit code
33+
exitCode := 0
34+
exit = func(code int) { exitCode = code }
35+
1036
tests := []struct {
1137
args []string
1238
expectedOutput string
@@ -22,94 +48,20 @@ func TestCLI(t *testing.T) {
2248
"│ │\n" +
2349
"│Also run [poke-cli -h] for more info! │\n" +
2450
"╰──────────────────────────────────────────────────────╯\n",
25-
expectedExit: 0,
26-
},
27-
{
28-
args: []string{"pokemon"},
29-
expectedOutput: "╭────────────────────────────────────────────────────────────╮\n" +
30-
"│Error! │\n" +
31-
"│Please declare a Pokémon's name after the [pokemon] command │\n" +
32-
"│Run 'poke-cli pokemon -h' for more details │\n" +
33-
"│error: insufficient arguments │\n" +
34-
"╰────────────────────────────────────────────────────────────╯\n",
3551
expectedExit: 1,
3652
},
3753
{
38-
args: []string{"pokemon", "bulbasaur"},
39-
expectedOutput: "Your selected Pokémon: Bulbasaur\nNational Pokédex #: 1\n",
54+
args: []string{"-l"},
55+
expectedOutput: fmt.Sprintf("Latest Docker image version: %s\nLatest release tag: %s\n", version, version),
4056
expectedExit: 0,
4157
},
4258
{
43-
args: []string{"pokemon", "mew", "--types"},
44-
expectedOutput: "Your selected Pokémon: Mew\nNational Pokédex #: 151\n──────\nTyping\nType 1: psychic\n",
59+
args: []string{"--latest"},
60+
expectedOutput: fmt.Sprintf("Latest Docker image version: %s\nLatest release tag: %s\n", version, version),
4561
expectedExit: 0,
4662
},
4763
{
48-
args: []string{"pokemon", "cacturne", "--types"},
49-
expectedOutput: "Your selected Pokémon: Cacturne\nNational Pokédex #: 332\n──────\nTyping\nType 1: grass\nType 2: dark\n",
50-
expectedExit: 0,
51-
},
52-
{
53-
args: []string{"pokemon", "chimchar", "types"},
54-
expectedOutput: "╭─────────────────────────────────────────────────────────────────────────────────╮\n" +
55-
"│Error! │\n" +
56-
"│Invalid argument 'types'. Only flags are allowed after declaring a Pokémon's name│\n" +
57-
"╰─────────────────────────────────────────────────────────────────────────────────╯\n",
58-
expectedExit: 1,
59-
},
60-
{
61-
args: []string{"pokemon", "flutter-mane", "types"},
62-
expectedOutput: "╭─────────────────────────────────────────────────────────────────────────────────╮\n" +
63-
"│Error! │\n" +
64-
"│Invalid argument 'types'. Only flags are allowed after declaring a Pokémon's name│\n" +
65-
"╰─────────────────────────────────────────────────────────────────────────────────╯\n",
66-
expectedExit: 1,
67-
},
68-
{
69-
args: []string{
70-
"pokemon", "AmPhaROs", "--types", "--abilities",
71-
},
72-
expectedOutput: "Your selected Pokémon: Ampharos\n" +
73-
"National Pokédex #: 181\n" +
74-
"──────\n" +
75-
"Typing\n" +
76-
"Type 1: electric\n" +
77-
"─────────\n" +
78-
"Abilities\n" +
79-
"Ability 1: static\n" +
80-
"Hidden Ability: plus\n",
81-
expectedExit: 0,
82-
},
83-
{
84-
args: []string{
85-
"pokemon", "CLOysTeR", "-t", "-a",
86-
},
87-
expectedOutput: "Your selected Pokémon: Cloyster\n" +
88-
"National Pokédex #: 91\n" +
89-
"──────\n" +
90-
"Typing\n" +
91-
"Type 1: water\n" +
92-
"Type 2: ice\n" +
93-
"─────────\n" +
94-
"Abilities\n" +
95-
"Ability 1: shell-armor\n" +
96-
"Ability 2: skill-link\n" +
97-
"Hidden Ability: overcoat\n",
98-
expectedExit: 0,
99-
},
100-
{
101-
args: []string{"pokemon", "gyarados", "--help"},
102-
expectedOutput: "╭──────────────────────────────────────────────────────────────╮\n" +
103-
"│poke-cli pokemon <pokemon-name> [flags] │\n" +
104-
"│ │\n" +
105-
"│FLAGS: │\n" +
106-
"│ -a, --abilities Prints out the Pokémon's abilities. │\n" +
107-
"│ -t, --types Prints out the Pokémon's typing. │\n" +
108-
"╰──────────────────────────────────────────────────────────────╯\n",
109-
expectedExit: 0,
110-
},
111-
{
112-
args: []string{"--help"},
64+
args: []string{"-h"},
11365
expectedOutput: "╭──────────────────────────────────────────────────────╮\n" +
11466
"│Welcome! This tool displays data related to Pokémon! │\n" +
11567
"│ │\n" +
@@ -129,50 +81,42 @@ func TestCLI(t *testing.T) {
12981
"╰──────────────────────────────────────────────────────╯\n",
13082
expectedExit: 0,
13183
},
132-
{
133-
args: []string{"types", "ground", "all"},
134-
expectedOutput: "╭──────────────────╮\n" +
135-
"│Error! │\n" +
136-
"│Too many arguments│\n" +
137-
"╰──────────────────╯\n",
138-
expectedExit: 1,
139-
},
140-
{
141-
args: []string{"types", "--help"},
142-
expectedOutput: "╭───────────────────────────────────────────────────────────────╮\n" +
143-
"│USAGE: │\n" +
144-
"│ poke-cli types [flag] │\n" +
145-
"│ Get details about a specific typing │\n" +
146-
"│ ---------- │\n" +
147-
"│ Examples: │\n" +
148-
"│ poke-cli types │\n" +
149-
"│ A table will then display with the option to select a type.│\n" +
150-
"╰───────────────────────────────────────────────────────────────╯\n",
151-
expectedExit: 0,
152-
},
15384
}
15485

15586
for _, test := range tests {
156-
cmd := exec.Command("poke-cli", test.args...)
157-
var out bytes.Buffer
158-
cmd.Stdout = &out
159-
cmd.Stderr = &out
87+
// Create a pipe to capture output
88+
r, w, _ := os.Pipe()
89+
os.Stdout = w
90+
os.Stderr = w
91+
92+
// Set os.Args for the test case
93+
os.Args = append([]string{"poke-cli"}, test.args...)
16094

161-
err := cmd.Run()
95+
// Run the main function
96+
main()
16297

98+
// Close the writer and restore stdout and stderr
99+
err := w.Close()
163100
if err != nil {
164-
// If there's an error, but we expected a successful exit
165-
if test.expectedExit == 0 {
166-
t.Errorf("Unexpected error: %v", err)
167-
}
101+
t.Fatalf("Error closing pipe writer: %v", err)
102+
}
103+
os.Stdout = originalStdout
104+
os.Stderr = originalStderr
105+
106+
// Read from the pipe
107+
var buf bytes.Buffer
108+
if _, err := io.Copy(&buf, r); err != nil {
109+
t.Errorf("Error copying output: %v", err)
168110
}
169111

170-
if out.String() != test.expectedOutput {
171-
t.Errorf("Args: %v, Expected output: %q, Got: %q", test.args, test.expectedOutput, out.String())
112+
// Strip ANSI color codes from the actual output
113+
actualOutput := stripANSI(buf.String())
114+
if actualOutput != test.expectedOutput {
115+
t.Errorf("Args: %v\nExpected output: %q\nGot: %q\n", test.args, test.expectedOutput, actualOutput)
172116
}
173117

174-
if cmd.ProcessState.ExitCode() != test.expectedExit {
175-
t.Errorf("Args: %v, Expected exit code: %d, Got: %d", test.args, test.expectedExit, cmd.ProcessState.ExitCode())
118+
if exitCode != test.expectedExit {
119+
t.Errorf("Args: %v\nExpected exit code: %d\nGot: %d\n", test.args, test.expectedExit, exitCode)
176120
}
177121
}
178122
}

flags/pokemonflagset_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@ func TestSetupPokemonFlagSet(t *testing.T) {
1616

1717
// Check types flag
1818
assert.NotNil(t, typesFlag, "Types flag should not be nil")
19-
assert.Equal(t, bool(false), *typesFlag, "Types flag name should be 'types'")
19+
assert.Equal(t, false, *typesFlag, "Types flag name should be 'types'")
2020

2121
// Check short types flag
22-
assert.NotNil(t, shortTypesFlag, "Types flag should not be nil")
23-
assert.Equal(t, bool(false), *shortTypesFlag, "Types flag name should be 't'")
22+
assert.NotNil(t, shortTypesFlag, "Short types flag should not be nil")
23+
assert.Equal(t, false, *shortTypesFlag, "Short types flag name should be 't'")
2424

2525
// Check abilities flag
2626
assert.NotNil(t, abilitiesFlag, "Abilities flag should not be nil")
27-
assert.Equal(t, bool(false), *abilitiesFlag, "Abilities flag name should be 'abilities'")
27+
assert.Equal(t, false, *abilitiesFlag, "Abilities flag name should be 'abilities'")
2828

2929
// Check short abilities flag
30-
assert.NotNil(t, shortAbilitiesFlag, "Abilities flag should not be nil")
31-
assert.Equal(t, bool(false), *shortAbilitiesFlag, "Abilities flag name should be 'a'")
30+
assert.NotNil(t, shortAbilitiesFlag, "Short abilities flag should not be nil")
31+
assert.Equal(t, false, *shortAbilitiesFlag, "Short abilities flag name should be 'a'")
3232
}

0 commit comments

Comments
 (0)